From 18d0361a5060edd1b72991f27fb058e4df925cde Mon Sep 17 00:00:00 2001 From: liu fengyun Date: Thu, 11 Jan 2018 17:24:24 +0100 Subject: [PATCH 01/10] Fix #1846: add regression test --- tests/pos/i1846.scala | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 tests/pos/i1846.scala diff --git a/tests/pos/i1846.scala b/tests/pos/i1846.scala new file mode 100644 index 000000000000..310bf62e8a84 --- /dev/null +++ b/tests/pos/i1846.scala @@ -0,0 +1,4 @@ +object Bug { + val x = 42 + x match {case {42}.toString => 42} +} From 96afef1769e3fd0a3fdaa140c1ccc27a7366c7ac Mon Sep 17 00:00:00 2001 From: liu fengyun Date: Thu, 11 Jan 2018 17:58:27 +0100 Subject: [PATCH 02/10] add more tests --- tests/pos/i1846.scala | 4 ---- tests/run/i1846.check | 4 ++++ tests/run/i1846.scala | 22 ++++++++++++++++++++++ 3 files changed, 26 insertions(+), 4 deletions(-) delete mode 100644 tests/pos/i1846.scala create mode 100644 tests/run/i1846.check create mode 100644 tests/run/i1846.scala diff --git a/tests/pos/i1846.scala b/tests/pos/i1846.scala deleted file mode 100644 index 310bf62e8a84..000000000000 --- a/tests/pos/i1846.scala +++ /dev/null @@ -1,4 +0,0 @@ -object Bug { - val x = 42 - x match {case {42}.toString => 42} -} diff --git a/tests/run/i1846.check b/tests/run/i1846.check new file mode 100644 index 000000000000..7c049cde1c62 --- /dev/null +++ b/tests/run/i1846.check @@ -0,0 +1,4 @@ +0 +42 +0 +0 diff --git a/tests/run/i1846.scala b/tests/run/i1846.scala new file mode 100644 index 000000000000..ce95e0c7053e --- /dev/null +++ b/tests/run/i1846.scala @@ -0,0 +1,22 @@ +object Test { + def main(args: Array[String]): Unit = { + val x = 42 + + x match { + case {42}.toString => println(42) + case _ => println(0) + } + + 42 match { case { 42 } => println(42) } + + 42 match { + case { 42 }.toString => println(42) + case _ => println(0) + } + + "h" match { + case { 42.toString } => println(42) + case _ => println(0) + } + } +} From 47256d2fb2768f87cb970c1fce83765bc8af6fc4 Mon Sep 17 00:00:00 2001 From: liu fengyun Date: Fri, 12 Jan 2018 00:04:35 +0100 Subject: [PATCH 03/10] Add Eq check for Apply tree in adapting patterns --- .../src/dotty/tools/dotc/typer/Typer.scala | 2 +- tests/neg/i1846.scala | 18 +++++++++++++++ tests/run/i1846.check | 4 ---- tests/run/i1846.scala | 22 ------------------- 4 files changed, 19 insertions(+), 27 deletions(-) create mode 100644 tests/neg/i1846.scala delete mode 100644 tests/run/i1846.check delete mode 100644 tests/run/i1846.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 20d7369bf11f..ef75644d0a94 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -2453,7 +2453,7 @@ class Typer extends Namer */ protected def checkEqualityEvidence(tree: tpd.Tree, pt: Type)(implicit ctx: Context) : Unit = { tree match { - case _: RefTree | _: Literal + case _: RefTree | _: Literal | _: Apply if !isVarPattern(tree) && !(tree.tpe <:< pt) (ctx.addMode(Mode.GADTflexible)) => val cmp = diff --git a/tests/neg/i1846.scala b/tests/neg/i1846.scala new file mode 100644 index 000000000000..187b00a1914c --- /dev/null +++ b/tests/neg/i1846.scala @@ -0,0 +1,18 @@ +object Test { + def main(args: Array[String]): Unit = { + val x = 42 + val Y = "h" + + x match { case { 42 } => 42 } // ok + x match { case { 42.toString } => 42 } // error + x match { case { 42 }.toString => 42 } // error + x match { case { "h" }.toString => println(42) } // error + x match { case { "h".toString } => println(42) } // error + x match { case Y => println(42) } // error + x match { case Y.toString => println(42) } // error + + Y match { case Y.toString => println(42) } // ok + Y match { case { Y.toString } => println(42) } // ok + Y match { case { Y }.toString => println(42) } // ok + } +} diff --git a/tests/run/i1846.check b/tests/run/i1846.check deleted file mode 100644 index 7c049cde1c62..000000000000 --- a/tests/run/i1846.check +++ /dev/null @@ -1,4 +0,0 @@ -0 -42 -0 -0 diff --git a/tests/run/i1846.scala b/tests/run/i1846.scala deleted file mode 100644 index ce95e0c7053e..000000000000 --- a/tests/run/i1846.scala +++ /dev/null @@ -1,22 +0,0 @@ -object Test { - def main(args: Array[String]): Unit = { - val x = 42 - - x match { - case {42}.toString => println(42) - case _ => println(0) - } - - 42 match { case { 42 } => println(42) } - - 42 match { - case { 42 }.toString => println(42) - case _ => println(0) - } - - "h" match { - case { 42.toString } => println(42) - case _ => println(0) - } - } -} From cff4826e9fd0fbc51c4ea8169500f061475994a4 Mon Sep 17 00:00:00 2001 From: Allan Renucci Date: Fri, 12 Jan 2018 13:49:07 +0100 Subject: [PATCH 04/10] Fix #3812: Refine tests for pattern match --- tests/neg/i1846.scala | 27 +++++++++++++++------------ tests/run/i3812.scala | 15 +++++++++++++++ 2 files changed, 30 insertions(+), 12 deletions(-) create mode 100644 tests/run/i3812.scala diff --git a/tests/neg/i1846.scala b/tests/neg/i1846.scala index 187b00a1914c..1f95975ed16c 100644 --- a/tests/neg/i1846.scala +++ b/tests/neg/i1846.scala @@ -1,18 +1,21 @@ object Test { def main(args: Array[String]): Unit = { val x = 42 - val Y = "h" + val Y = "42" - x match { case { 42 } => 42 } // ok - x match { case { 42.toString } => 42 } // error - x match { case { 42 }.toString => 42 } // error - x match { case { "h" }.toString => println(42) } // error - x match { case { "h".toString } => println(42) } // error - x match { case Y => println(42) } // error - x match { case Y.toString => println(42) } // error - - Y match { case Y.toString => println(42) } // ok - Y match { case { Y.toString } => println(42) } // ok - Y match { case { Y }.toString => println(42) } // ok + x match { case { 42 } => () } // ok + x match { case { 42.toString } => () } // error + x match { case { 42 }.toString => () } // error + x match { case "42".toInt => () } // error + x match { case { "42".toInt } => () } // ok + x match { case { "42" }.toInt => () } // ok + x match { case { "42".toInt } => () } // ok + x match { case Y => () } // error + x match { case Y.toInt => () } // ok + x match { case { Y.toInt } => () } // ok + x match { case { Y }.toInt => () } // ok + x match { case Y.toString => () } // error + x match { case { Y }.toString => () } // error + x match { case { Y.toString } => () } // error } } diff --git a/tests/run/i3812.scala b/tests/run/i3812.scala new file mode 100644 index 000000000000..a097072b9be8 --- /dev/null +++ b/tests/run/i3812.scala @@ -0,0 +1,15 @@ +object Test { + def main(args: Array[String]): Unit = { + val x = 42 + val Y = "42" + + x match { case { 42 } => () } // ok + x match { case { "42".toInt } => () } // ok + x match { case { "42" }.toInt => () } // ok + x match { case { "42".toInt } => () } // ok + x match { case { Y.toInt } => () } // ok + x match { case { Y }.toInt => () } // ok + + // x match { case Y.toInt => () } // compiles but rejected by Ycheck + } +} From 27349589af84a2541e04de8b191958f84b17c176 Mon Sep 17 00:00:00 2001 From: liu fengyun Date: Fri, 12 Jan 2018 17:10:11 +0100 Subject: [PATCH 05/10] fix retyper in checking Select in patterns --- compiler/src/dotty/tools/dotc/typer/ReTyper.scala | 3 ++- tests/run/i3812.scala | 3 +-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/typer/ReTyper.scala b/compiler/src/dotty/tools/dotc/typer/ReTyper.scala index 7031b7920f2a..b5ca1c651443 100644 --- a/compiler/src/dotty/tools/dotc/typer/ReTyper.scala +++ b/compiler/src/dotty/tools/dotc/typer/ReTyper.scala @@ -35,7 +35,8 @@ class ReTyper extends Typer { override def typedSelect(tree: untpd.Select, pt: Type)(implicit ctx: Context): Tree = { assert(tree.hasType, tree) - val qual1 = typed(tree.qualifier, AnySelectionProto) + // a qualifier cannot be a pattern + val qual1 = typed(tree.qualifier, AnySelectionProto)(ctx.retractMode(Mode.Pattern)) untpd.cpy.Select(tree)(qual1, tree.name).withType(tree.typeOpt) } diff --git a/tests/run/i3812.scala b/tests/run/i3812.scala index a097072b9be8..6345e6a73593 100644 --- a/tests/run/i3812.scala +++ b/tests/run/i3812.scala @@ -9,7 +9,6 @@ object Test { x match { case { "42".toInt } => () } // ok x match { case { Y.toInt } => () } // ok x match { case { Y }.toInt => () } // ok - - // x match { case Y.toInt => () } // compiles but rejected by Ycheck + x match { case Y.toInt => () } // ok } } From 0677c77f5e4be7e9ab624281e87c4d7b2b657df0 Mon Sep 17 00:00:00 2001 From: liu fengyun Date: Wed, 17 Jan 2018 14:53:44 +0100 Subject: [PATCH 06/10] remove block syntax in patterns --- .../src/dotty/tools/dotc/parsing/Parsers.scala | 3 --- docs/docs/internals/syntax.md | 3 +-- tests/neg/i1846.scala | 12 ++++++------ tests/neg/i3812.scala | 14 ++++++++++++++ tests/run/i3812.scala | 6 ------ 5 files changed, 21 insertions(+), 17 deletions(-) create mode 100644 tests/neg/i3812.scala diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index 2436ad4081f2..d21d991f65ee 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -1564,7 +1564,6 @@ object Parsers { * | `(' [Patterns] `)' * | SimplePattern1 [TypeArgs] [ArgumentPatterns] * SimplePattern1 ::= Path - * | `{' Block `}' * | SimplePattern1 `.' id * PatVar ::= id * | `_' @@ -1587,8 +1586,6 @@ object Parsers { } else wildIndent case LPAREN => atPos(in.offset) { makeTupleOrParens(inParens(patternsOpt())) } - case LBRACE => - dotSelectors(blockExpr()) case XMLSTART => xmlLiteralPattern() case _ => diff --git a/docs/docs/internals/syntax.md b/docs/docs/internals/syntax.md index ddc70855ff1d..40825d221589 100644 --- a/docs/docs/internals/syntax.md +++ b/docs/docs/internals/syntax.md @@ -202,7 +202,7 @@ ParArgumentExprs ::= ‘(’ ExprsInParens ‘)’ | ‘(’ [ExprsInParens] PostfixExpr ‘:’ ‘_’ ‘*’ ‘)’ exprs :+ Typed(expr, Ident(wildcardStar)) ArgumentExprs ::= ParArgumentExprs | [nl] BlockExpr -BlockExpr ::= ‘{’ BlockExprContents ‘}’ +BlockExpr ::= ‘{’ BlockExprContents ‘}’ BlockExprContents ::= CaseClauses | Block Block ::= {BlockStat semi} [BlockResult] Block(stats, expr?) BlockStat ::= Import @@ -234,7 +234,6 @@ SimplePattern ::= PatVar | XmlPattern | SimplePattern1 [TypeArgs] [ArgumentPatterns] SimplePattern1 ::= Path - | ‘{’ Block ‘}’ | SimplePattern1 ‘.’ id PatVar ::= varid | ‘_’ diff --git a/tests/neg/i1846.scala b/tests/neg/i1846.scala index 1f95975ed16c..295a25bdced3 100644 --- a/tests/neg/i1846.scala +++ b/tests/neg/i1846.scala @@ -3,17 +3,17 @@ object Test { val x = 42 val Y = "42" - x match { case { 42 } => () } // ok + x match { case { 42 } => () } // error x match { case { 42.toString } => () } // error x match { case { 42 }.toString => () } // error x match { case "42".toInt => () } // error - x match { case { "42".toInt } => () } // ok - x match { case { "42" }.toInt => () } // ok - x match { case { "42".toInt } => () } // ok + x match { case { "42".toInt } => () } // error + x match { case { "42" }.toInt => () } // error + x match { case { "42".toInt } => () } // error x match { case Y => () } // error x match { case Y.toInt => () } // ok - x match { case { Y.toInt } => () } // ok - x match { case { Y }.toInt => () } // ok + x match { case { Y.toInt } => () } // error + x match { case { Y }.toInt => () } // error x match { case Y.toString => () } // error x match { case { Y }.toString => () } // error x match { case { Y.toString } => () } // error diff --git a/tests/neg/i3812.scala b/tests/neg/i3812.scala new file mode 100644 index 000000000000..d528b74f62d2 --- /dev/null +++ b/tests/neg/i3812.scala @@ -0,0 +1,14 @@ +object Test { + def main(args: Array[String]): Unit = { + val x = 42 + val Y = "42" + + x match { case { 42 } => () } // error + x match { case { "42".toInt } => () } // error + x match { case { "42" }.toInt => () } // error + x match { case { "42".toInt } => () } // error + x match { case { Y.toInt } => () } // error + x match { case { Y }.toInt => () } // error + x match { case Y.toInt => () } // ok + } +} diff --git a/tests/run/i3812.scala b/tests/run/i3812.scala index 6345e6a73593..ad7099a4bbfe 100644 --- a/tests/run/i3812.scala +++ b/tests/run/i3812.scala @@ -3,12 +3,6 @@ object Test { val x = 42 val Y = "42" - x match { case { 42 } => () } // ok - x match { case { "42".toInt } => () } // ok - x match { case { "42" }.toInt => () } // ok - x match { case { "42".toInt } => () } // ok - x match { case { Y.toInt } => () } // ok - x match { case { Y }.toInt => () } // ok x match { case Y.toInt => () } // ok } } From 2fe794060dc8852a5aa131038a31e4da3a3ba366 Mon Sep 17 00:00:00 2001 From: liu fengyun Date: Thu, 18 Jan 2018 10:04:22 +0100 Subject: [PATCH 07/10] check qualifier is stable in pattern select --- .../dotty/tools/dotc/typer/RefChecks.scala | 29 +++++++++++++++++++ tests/neg/i1846.scala | 1 - tests/neg/i3812.scala | 5 +++- tests/neg/i3812b.scala | 26 +++++++++++++++++ tests/run/i3812.scala | 8 ----- 5 files changed, 59 insertions(+), 10 deletions(-) create mode 100644 tests/neg/i3812b.scala delete mode 100644 tests/run/i3812.scala diff --git a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala index 138830b1e2cb..8533ab27b44a 100644 --- a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala +++ b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala @@ -75,6 +75,15 @@ object RefChecks { } } + /** Check that a stable identifier pattern is indeed stable (SLS 8.1.5) + */ + private def checkStableIdentPattern(tree: Tree)(implicit ctx: Context) = tree match { + case _: Select | _: Ident if !isWildcardArg(tree) => + if (!tree.tpe.isStable) + ctx.error(s"stable identifier required, but ${tree.show} found", tree.pos) + case _ => + } + /** The this-type of `cls` which should be used when looking at the types of * inherited members. If `cls` has a non-trivial self type, this returns a skolem * with the class type instead of the `this-type` of the class as usual. @@ -884,6 +893,26 @@ class RefChecks extends MiniPhase { thisPhase => currentLevel.enterReference(sym, tree.pos) tree } + + override def transformUnApply(tree: UnApply)(implicit ctx: Context): Tree = { + tree.patterns.foreach(checkStableIdentPattern(_)) + tree + } + + override def transformAlternative(tree: Alternative)(implicit ctx: Context): Tree = { + tree.trees.foreach(checkStableIdentPattern(_)) + tree + } + + override def transformBind(tree: Bind)(implicit ctx: Context): Tree = { + checkStableIdentPattern(tree.body) + tree + } + + override def transformCaseDef(tree: CaseDef)(implicit ctx: Context) = { + checkStableIdentPattern(tree.pat) + tree + } } /* todo: rewrite and re-enable diff --git a/tests/neg/i1846.scala b/tests/neg/i1846.scala index 295a25bdced3..c52fda7ebb64 100644 --- a/tests/neg/i1846.scala +++ b/tests/neg/i1846.scala @@ -11,7 +11,6 @@ object Test { x match { case { "42" }.toInt => () } // error x match { case { "42".toInt } => () } // error x match { case Y => () } // error - x match { case Y.toInt => () } // ok x match { case { Y.toInt } => () } // error x match { case { Y }.toInt => () } // error x match { case Y.toString => () } // error diff --git a/tests/neg/i3812.scala b/tests/neg/i3812.scala index d528b74f62d2..d16c2cb85fcf 100644 --- a/tests/neg/i3812.scala +++ b/tests/neg/i3812.scala @@ -1,7 +1,11 @@ object Test { def main(args: Array[String]): Unit = { + case class Box(v: Int) + val x = 42 val Y = "42" + var Z1 = Box(4) + val Z2 = Box(4) x match { case { 42 } => () } // error x match { case { "42".toInt } => () } // error @@ -9,6 +13,5 @@ object Test { x match { case { "42".toInt } => () } // error x match { case { Y.toInt } => () } // error x match { case { Y }.toInt => () } // error - x match { case Y.toInt => () } // ok } } diff --git a/tests/neg/i3812b.scala b/tests/neg/i3812b.scala new file mode 100644 index 000000000000..85804838cb52 --- /dev/null +++ b/tests/neg/i3812b.scala @@ -0,0 +1,26 @@ +object Test { + def main(args: Array[String]): Unit = { + case class Box(v: Int) + + val x = 42 + var Y1 = 42 + val Y2 = "42" + var Z1 = Box(4) + val Z2 = Box(4) + + x match { case Y1 => () } // error + x match { case Y2.toInt => () } // error + + x match { case Z1.v => () } // error + x match { case Z2.v => () } // ok + + Some(x) match { case Some(Z1.v) => () } // error + Some(x) match { case Some(Z2.v) => () } // ok + + Some(x) match { case Some(4) | Some(Z1.v) => () } // error + Some(x) match { case a @ Some(Z1.v) => () } // error + + Some(x) match { case Some(4) | Some(Z2.v) => () } // ok + Some(x) match { case a @ Some(Z2.v) => () } // ok + } +} diff --git a/tests/run/i3812.scala b/tests/run/i3812.scala deleted file mode 100644 index ad7099a4bbfe..000000000000 --- a/tests/run/i3812.scala +++ /dev/null @@ -1,8 +0,0 @@ -object Test { - def main(args: Array[String]): Unit = { - val x = 42 - val Y = "42" - - x match { case Y.toInt => () } // ok - } -} From 798b0d3f63552bd04472ac4ea885ad5384d60e65 Mon Sep 17 00:00:00 2001 From: liu fengyun Date: Thu, 18 Jan 2018 14:30:49 +0100 Subject: [PATCH 08/10] remove noise in test code --- tests/neg/i3812.scala | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/neg/i3812.scala b/tests/neg/i3812.scala index d16c2cb85fcf..182721d65ea0 100644 --- a/tests/neg/i3812.scala +++ b/tests/neg/i3812.scala @@ -1,11 +1,7 @@ object Test { def main(args: Array[String]): Unit = { - case class Box(v: Int) - val x = 42 val Y = "42" - var Z1 = Box(4) - val Z2 = Box(4) x match { case { 42 } => () } // error x match { case { "42".toInt } => () } // error From 77ac75c1c19c1b42bd3e4afad8e0a431e84154a6 Mon Sep 17 00:00:00 2001 From: liu fengyun Date: Thu, 18 Jan 2018 14:58:24 +0100 Subject: [PATCH 09/10] revert the change to typer --- .../src/dotty/tools/dotc/typer/RefChecks.scala | 16 +++++++++++----- compiler/src/dotty/tools/dotc/typer/Typer.scala | 2 +- tests/neg/i1846.scala | 1 - tests/neg/i3812b.scala | 1 + 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala index 8533ab27b44a..442615d303b3 100644 --- a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala +++ b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala @@ -77,11 +77,17 @@ object RefChecks { /** Check that a stable identifier pattern is indeed stable (SLS 8.1.5) */ - private def checkStableIdentPattern(tree: Tree)(implicit ctx: Context) = tree match { - case _: Select | _: Ident if !isWildcardArg(tree) => - if (!tree.tpe.isStable) - ctx.error(s"stable identifier required, but ${tree.show} found", tree.pos) - case _ => + private def checkStableIdentPattern(tree: Tree)(implicit ctx: Context) = { + def error = ctx.error(s"stable identifier required, but ${tree.show} found", tree.pos) + tree match { + case _: Ident if !isWildcardArg(tree) => + if (!tree.tpe.isStable) error + case _: Select => + if (!tree.tpe.isStable) error + case _: Apply => + error + case _ => + } } /** The this-type of `cls` which should be used when looking at the types of diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index ef75644d0a94..20d7369bf11f 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -2453,7 +2453,7 @@ class Typer extends Namer */ protected def checkEqualityEvidence(tree: tpd.Tree, pt: Type)(implicit ctx: Context) : Unit = { tree match { - case _: RefTree | _: Literal | _: Apply + case _: RefTree | _: Literal if !isVarPattern(tree) && !(tree.tpe <:< pt) (ctx.addMode(Mode.GADTflexible)) => val cmp = diff --git a/tests/neg/i1846.scala b/tests/neg/i1846.scala index c52fda7ebb64..f661a86d5daf 100644 --- a/tests/neg/i1846.scala +++ b/tests/neg/i1846.scala @@ -13,7 +13,6 @@ object Test { x match { case Y => () } // error x match { case { Y.toInt } => () } // error x match { case { Y }.toInt => () } // error - x match { case Y.toString => () } // error x match { case { Y }.toString => () } // error x match { case { Y.toString } => () } // error } diff --git a/tests/neg/i3812b.scala b/tests/neg/i3812b.scala index 85804838cb52..e9b0c291ef3f 100644 --- a/tests/neg/i3812b.scala +++ b/tests/neg/i3812b.scala @@ -10,6 +10,7 @@ object Test { x match { case Y1 => () } // error x match { case Y2.toInt => () } // error + x match { case Y1.toString => () } // error x match { case Z1.v => () } // error x match { case Z2.v => () } // ok From 46302033089c77af73eea0982cc55ac37f4aa026 Mon Sep 17 00:00:00 2001 From: liu fengyun Date: Mon, 22 Jan 2018 14:52:17 +0100 Subject: [PATCH 10/10] address review: move check to typer --- .../dotty/tools/dotc/typer/RefChecks.scala | 35 ------------------- .../src/dotty/tools/dotc/typer/Typer.scala | 16 ++++++++- 2 files changed, 15 insertions(+), 36 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala index 442615d303b3..138830b1e2cb 100644 --- a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala +++ b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala @@ -75,21 +75,6 @@ object RefChecks { } } - /** Check that a stable identifier pattern is indeed stable (SLS 8.1.5) - */ - private def checkStableIdentPattern(tree: Tree)(implicit ctx: Context) = { - def error = ctx.error(s"stable identifier required, but ${tree.show} found", tree.pos) - tree match { - case _: Ident if !isWildcardArg(tree) => - if (!tree.tpe.isStable) error - case _: Select => - if (!tree.tpe.isStable) error - case _: Apply => - error - case _ => - } - } - /** The this-type of `cls` which should be used when looking at the types of * inherited members. If `cls` has a non-trivial self type, this returns a skolem * with the class type instead of the `this-type` of the class as usual. @@ -899,26 +884,6 @@ class RefChecks extends MiniPhase { thisPhase => currentLevel.enterReference(sym, tree.pos) tree } - - override def transformUnApply(tree: UnApply)(implicit ctx: Context): Tree = { - tree.patterns.foreach(checkStableIdentPattern(_)) - tree - } - - override def transformAlternative(tree: Alternative)(implicit ctx: Context): Tree = { - tree.trees.foreach(checkStableIdentPattern(_)) - tree - } - - override def transformBind(tree: Bind)(implicit ctx: Context): Tree = { - checkStableIdentPattern(tree.body) - tree - } - - override def transformCaseDef(tree: CaseDef)(implicit ctx: Context) = { - checkStableIdentPattern(tree.pat) - tree - } } /* todo: rewrite and re-enable diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 20d7369bf11f..ff40b4a61a5a 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -406,9 +406,23 @@ class Typer extends Namer tree.withType(ownType) } + checkStableIdentPattern(tree1, pt) checkValue(tree1, pt) } + /** Check that a stable identifier pattern is indeed stable (SLS 8.1.5) + */ + private def checkStableIdentPattern(tree: Tree, pt: Type)(implicit ctx: Context): Tree = { + if (ctx.mode.is(Mode.Pattern) && + !tree.isType && + !pt.isInstanceOf[ApplyingProto] && + !tree.tpe.isStable && + !isWildcardArg(tree)) + ctx.error(s"stable identifier required, but ${tree.show} found", tree.pos) + + tree + } + private def typedSelect(tree: untpd.Select, pt: Type, qual: Tree)(implicit ctx: Context): Select = checkValue(assignType(cpy.Select(tree)(qual, tree.name), qual), pt) @@ -418,7 +432,7 @@ class Typer extends Namer val qual1 = typedExpr(tree.qualifier, selectionProto(tree.name, pt, this)) if (tree.name.isTypeName) checkStable(qual1.tpe, qual1.pos) val select = typedSelect(tree, pt, qual1) - if (select.tpe ne TryDynamicCallType) select + if (select.tpe ne TryDynamicCallType) checkStableIdentPattern(select, pt) else if (pt.isInstanceOf[PolyProto] || pt.isInstanceOf[FunProto] || pt == AssignProto) select else typedDynamicSelect(tree, Nil, pt) }