Skip to content

Commit 2fe7940

Browse files
committed
check qualifier is stable in pattern select
1 parent 0677c77 commit 2fe7940

File tree

5 files changed

+59
-10
lines changed

5 files changed

+59
-10
lines changed

compiler/src/dotty/tools/dotc/typer/RefChecks.scala

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,15 @@ object RefChecks {
7575
}
7676
}
7777

78+
/** Check that a stable identifier pattern is indeed stable (SLS 8.1.5)
79+
*/
80+
private def checkStableIdentPattern(tree: Tree)(implicit ctx: Context) = tree match {
81+
case _: Select | _: Ident if !isWildcardArg(tree) =>
82+
if (!tree.tpe.isStable)
83+
ctx.error(s"stable identifier required, but ${tree.show} found", tree.pos)
84+
case _ =>
85+
}
86+
7887
/** The this-type of `cls` which should be used when looking at the types of
7988
* inherited members. If `cls` has a non-trivial self type, this returns a skolem
8089
* with the class type instead of the `this-type` of the class as usual.
@@ -884,6 +893,26 @@ class RefChecks extends MiniPhase { thisPhase =>
884893
currentLevel.enterReference(sym, tree.pos)
885894
tree
886895
}
896+
897+
override def transformUnApply(tree: UnApply)(implicit ctx: Context): Tree = {
898+
tree.patterns.foreach(checkStableIdentPattern(_))
899+
tree
900+
}
901+
902+
override def transformAlternative(tree: Alternative)(implicit ctx: Context): Tree = {
903+
tree.trees.foreach(checkStableIdentPattern(_))
904+
tree
905+
}
906+
907+
override def transformBind(tree: Bind)(implicit ctx: Context): Tree = {
908+
checkStableIdentPattern(tree.body)
909+
tree
910+
}
911+
912+
override def transformCaseDef(tree: CaseDef)(implicit ctx: Context) = {
913+
checkStableIdentPattern(tree.pat)
914+
tree
915+
}
887916
}
888917

889918
/* todo: rewrite and re-enable

tests/neg/i1846.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ object Test {
1111
x match { case { "42" }.toInt => () } // error
1212
x match { case { "42".toInt } => () } // error
1313
x match { case Y => () } // error
14-
x match { case Y.toInt => () } // ok
1514
x match { case { Y.toInt } => () } // error
1615
x match { case { Y }.toInt => () } // error
1716
x match { case Y.toString => () } // error

tests/neg/i3812.scala

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
object Test {
22
def main(args: Array[String]): Unit = {
3+
case class Box(v: Int)
4+
35
val x = 42
46
val Y = "42"
7+
var Z1 = Box(4)
8+
val Z2 = Box(4)
59

610
x match { case { 42 } => () } // error
711
x match { case { "42".toInt } => () } // error
812
x match { case { "42" }.toInt => () } // error
913
x match { case { "42".toInt } => () } // error
1014
x match { case { Y.toInt } => () } // error
1115
x match { case { Y }.toInt => () } // error
12-
x match { case Y.toInt => () } // ok
1316
}
1417
}

tests/neg/i3812b.scala

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
object Test {
2+
def main(args: Array[String]): Unit = {
3+
case class Box(v: Int)
4+
5+
val x = 42
6+
var Y1 = 42
7+
val Y2 = "42"
8+
var Z1 = Box(4)
9+
val Z2 = Box(4)
10+
11+
x match { case Y1 => () } // error
12+
x match { case Y2.toInt => () } // error
13+
14+
x match { case Z1.v => () } // error
15+
x match { case Z2.v => () } // ok
16+
17+
Some(x) match { case Some(Z1.v) => () } // error
18+
Some(x) match { case Some(Z2.v) => () } // ok
19+
20+
Some(x) match { case Some(4) | Some(Z1.v) => () } // error
21+
Some(x) match { case a @ Some(Z1.v) => () } // error
22+
23+
Some(x) match { case Some(4) | Some(Z2.v) => () } // ok
24+
Some(x) match { case a @ Some(Z2.v) => () } // ok
25+
}
26+
}

tests/run/i3812.scala

Lines changed: 0 additions & 8 deletions
This file was deleted.

0 commit comments

Comments
 (0)