From 6efc6c8be747045b1ce75b79fb915d5dbfb5a35c Mon Sep 17 00:00:00 2001 From: Vitor Vieira Date: Sun, 26 Nov 2017 01:02:07 +0100 Subject: [PATCH 1/4] #1589: Add error message for not emitting @switch. PatternMatcher.911 --- .../reporting/diagnostic/ErrorMessageID.java | 1 + .../dotc/reporting/diagnostic/messages.scala | 32 +++++++++++++++++++ .../tools/dotc/transform/PatternMatcher.scala | 3 +- 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java b/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java index 4f5ed0ef4ab6..32dac326b93d 100644 --- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java +++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java @@ -118,6 +118,7 @@ public enum ErrorMessageID { StaticFieldsOnlyAllowedInObjectsID, CyclicInheritanceID, UnableToExtendSealedClassID, + UnableToEmitSwitchID, ; public int errorNumber() { diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala index 94192d13ee57..60914114f994 100644 --- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala @@ -1972,4 +1972,36 @@ object messages { val msg = hl"Cannot extend ${"sealed"} $pclazz in a different source file" val explanation = "A sealed class or trait can only be extended in the same file as its declaration" } + + case class UnableToEmitSwitch()(implicit ctx: Context) + extends Message(UnableToEmitSwitchID) { + val kind = "Syntax" + val msg = hl"""Could not emit switch for ${"@switch"} annotated match""" + val explanation = { + val errorCodeExample = + """val middle = 'm' + |val last = 'z' + | + |val number = (middle: @switch) match { + | case 'a' => 1 + | case 'm' => 13 + | case last => 26 //a non-literal may prevent switch generation: this would not compile. + | case _ => 0 + |}""".stripMargin + + hl"""The compiler verifies that the match has been compiled to a tableswitch or lookupswitch. + |An error will be issued in case it compiles into a series of conditional expressions. + | + |Consider the following example: + | + |$errorCodeExample + | + |The example above would fail as it matches a non-literal value. + |The compiler will apply the tableswitch optimization when: + |-The matched value is a known integer or types implicitly convertible to integer. + |-The matched expression only matches literal values, without type checks, if statements, or extractors. + |-The expression have its value available at compile time. + |-There are more than two case statements.""" + } + } } diff --git a/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala b/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala index a16f7ab427f7..8d217cf96e0d 100644 --- a/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala +++ b/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala @@ -14,6 +14,7 @@ import Decorators._ import patmat.Space import NameKinds.{UniqueNameKind, PatMatStdBinderName, PatMatCaseName} import config.Printers.patmatch +import reporting.diagnostic.messages._ /** The pattern matching transform. * After this phase, the only Match nodes remaining in the code are simple switches @@ -908,7 +909,7 @@ object PatternMatcher { tpes.toSet.size: Int // without the type ascription, testPickling fails because of #2840. } if (numConsts(resultCases) < numConsts(original.cases)) - ctx.warning(i"could not emit switch for @switch annotated match", original.pos) + ctx.warning(UnableToEmitSwitch(), original.pos) case _ => } From a2798f5ababd38eb5175eb26264208f937084b54 Mon Sep 17 00:00:00 2001 From: Vitor Vieira Date: Sun, 26 Nov 2017 12:00:11 +0100 Subject: [PATCH 2/4] #1589: Updated code example in error explanation. --- .../dotty/tools/dotc/reporting/diagnostic/messages.scala | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala index 60914114f994..7d918cce409a 100644 --- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala @@ -1979,13 +1979,13 @@ object messages { val msg = hl"""Could not emit switch for ${"@switch"} annotated match""" val explanation = { val errorCodeExample = - """val middle = 'm' - |val last = 'z' + """val Middle = 'm' + |val Last = 'z' | - |val number = (middle: @switch) match { + |val number = (Middle: @switch) match { | case 'a' => 1 | case 'm' => 13 - | case last => 26 //a non-literal may prevent switch generation: this would not compile. + | case Last => 26 //a non-literal may prevent switch generation: this would not compile. | case _ => 0 |}""".stripMargin From 2c4984beead06f01d2b8bb1e96ca13680ed98224 Mon Sep 17 00:00:00 2001 From: Vitor Vieira Date: Sun, 26 Nov 2017 23:45:57 +0100 Subject: [PATCH 3/4] #1589: Updated code example and error explanation based on code review. --- .../dotc/reporting/diagnostic/messages.scala | 44 +++++++++---------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala index 7d918cce409a..06566c96d06d 100644 --- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala @@ -1976,32 +1976,30 @@ object messages { case class UnableToEmitSwitch()(implicit ctx: Context) extends Message(UnableToEmitSwitchID) { val kind = "Syntax" - val msg = hl"""Could not emit switch for ${"@switch"} annotated match""" + val msg = hl"Could not emit switch for ${"@switch"} annotated match" val explanation = { - val errorCodeExample = - """val Middle = 'm' - |val Last = 'z' - | - |val number = (Middle: @switch) match { - | case 'a' => 1 - | case 'm' => 13 - | case Last => 26 //a non-literal may prevent switch generation: this would not compile. - | case _ => 0 + val codeExample = + """val ConstantB = 'B' + |final val ConstantC = 'C' + |def tokenMe(ch: Char) = (ch: @switch) match { + | case '\t' | '\n' => 1 + | case 'A' => 2 + | case ConstantB => 3 // a non-literal may prevent switch generation: this would not compile + | case ConstantC => 4 // a constant value is allowed + | case _ => 5 |}""".stripMargin - hl"""The compiler verifies that the match has been compiled to a tableswitch or lookupswitch. - |An error will be issued in case it compiles into a series of conditional expressions. - | - |Consider the following example: - | - |$errorCodeExample - | - |The example above would fail as it matches a non-literal value. - |The compiler will apply the tableswitch optimization when: - |-The matched value is a known integer or types implicitly convertible to integer. - |-The matched expression only matches literal values, without type checks, if statements, or extractors. - |-The expression have its value available at compile time. - |-There are more than two case statements.""" + hl"""If annotated with ${"@switch"}, the compiler will verify that the match has been compiled to a + |tableswitch or lookupswitch and issue an error if it instead compiles into a series of conditional + |expressions. Example usage: + | + |$codeExample + | + |The compiler will not apply the optimisation if: + |- the matched value is not of type ${"Int"}, ${"Byte"}, ${"Short"} or ${"Char"} + |- the matched value is not a constant literal + |- there are less than three cases + """.stripMargin } } } From 445e8e08e4d04baf4f24acc6ac409925c9dbb4dc Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Sun, 26 Nov 2017 23:56:41 +0100 Subject: [PATCH 4/4] Polish --- .../dotc/reporting/diagnostic/messages.scala | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala index 06566c96d06d..eb2947893753 100644 --- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala @@ -1990,16 +1990,15 @@ object messages { |}""".stripMargin hl"""If annotated with ${"@switch"}, the compiler will verify that the match has been compiled to a - |tableswitch or lookupswitch and issue an error if it instead compiles into a series of conditional - |expressions. Example usage: - | - |$codeExample - | - |The compiler will not apply the optimisation if: - |- the matched value is not of type ${"Int"}, ${"Byte"}, ${"Short"} or ${"Char"} - |- the matched value is not a constant literal - |- there are less than three cases - """.stripMargin + |tableswitch or lookupswitch and issue an error if it instead compiles into a series of conditional + |expressions. Example usage: + | + |$codeExample + | + |The compiler will not apply the optimisation if: + |- the matched value is not of type ${"Int"}, ${"Byte"}, ${"Short"} or ${"Char"} + |- the matched value is not a constant literal + |- there are less than three cases""" } } }