Skip to content

Commit 46956b0

Browse files
authored
Merge pull request #3810 from dotty-staging/fix-1846
Fix #1846: add regression test
2 parents e78a0be + 4630203 commit 46956b0

File tree

7 files changed

+77
-7
lines changed

7 files changed

+77
-7
lines changed

compiler/src/dotty/tools/dotc/parsing/Parsers.scala

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1575,7 +1575,6 @@ object Parsers {
15751575
* | `(' [Patterns] `)'
15761576
* | SimplePattern1 [TypeArgs] [ArgumentPatterns]
15771577
* SimplePattern1 ::= Path
1578-
* | `{' Block `}'
15791578
* | SimplePattern1 `.' id
15801579
* PatVar ::= id
15811580
* | `_'
@@ -1598,8 +1597,6 @@ object Parsers {
15981597
} else wildIndent
15991598
case LPAREN =>
16001599
atPos(in.offset) { makeTupleOrParens(inParens(patternsOpt())) }
1601-
case LBRACE =>
1602-
dotSelectors(blockExpr())
16031600
case XMLSTART =>
16041601
xmlLiteralPattern()
16051602
case _ =>

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ class ReTyper extends Typer {
3535

3636
override def typedSelect(tree: untpd.Select, pt: Type)(implicit ctx: Context): Tree = {
3737
assert(tree.hasType, tree)
38-
val qual1 = typed(tree.qualifier, AnySelectionProto)
38+
// a qualifier cannot be a pattern
39+
val qual1 = typed(tree.qualifier, AnySelectionProto)(ctx.retractMode(Mode.Pattern))
3940
untpd.cpy.Select(tree)(qual1, tree.name).withType(tree.typeOpt)
4041
}
4142

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

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -411,9 +411,23 @@ class Typer extends Namer
411411
tree.withType(ownType)
412412
}
413413

414+
checkStableIdentPattern(tree1, pt)
414415
checkValue(tree1, pt)
415416
}
416417

418+
/** Check that a stable identifier pattern is indeed stable (SLS 8.1.5)
419+
*/
420+
private def checkStableIdentPattern(tree: Tree, pt: Type)(implicit ctx: Context): Tree = {
421+
if (ctx.mode.is(Mode.Pattern) &&
422+
!tree.isType &&
423+
!pt.isInstanceOf[ApplyingProto] &&
424+
!tree.tpe.isStable &&
425+
!isWildcardArg(tree))
426+
ctx.error(s"stable identifier required, but ${tree.show} found", tree.pos)
427+
428+
tree
429+
}
430+
417431
private def typedSelect(tree: untpd.Select, pt: Type, qual: Tree)(implicit ctx: Context): Select =
418432
checkValue(assignType(cpy.Select(tree)(qual, tree.name), qual), pt)
419433

@@ -423,7 +437,7 @@ class Typer extends Namer
423437
val qual1 = typedExpr(tree.qualifier, selectionProto(tree.name, pt, this))
424438
if (tree.name.isTypeName) checkStable(qual1.tpe, qual1.pos)
425439
val select = typedSelect(tree, pt, qual1)
426-
if (select.tpe ne TryDynamicCallType) select
440+
if (select.tpe ne TryDynamicCallType) checkStableIdentPattern(select, pt)
427441
else if (pt.isInstanceOf[PolyProto] || pt.isInstanceOf[FunProto] || pt == AssignProto) select
428442
else typedDynamicSelect(tree, Nil, pt)
429443
}

docs/docs/internals/syntax.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ ParArgumentExprs ::= ‘(’ ExprsInParens ‘)’
202202
| ‘(’ [ExprsInParens] PostfixExpr ‘:’ ‘_’ ‘*’ ‘)’ exprs :+ Typed(expr, Ident(wildcardStar))
203203
ArgumentExprs ::= ParArgumentExprs
204204
| [nl] BlockExpr
205-
BlockExpr ::= ‘{’ BlockExprContents ‘}’
205+
BlockExpr ::= ‘{’ BlockExprContents ‘}’
206206
BlockExprContents ::= CaseClauses | Block
207207
Block ::= {BlockStat semi} [BlockResult] Block(stats, expr?)
208208
BlockStat ::= Import
@@ -234,7 +234,6 @@ SimplePattern ::= PatVar
234234
| XmlPattern
235235
| SimplePattern1 [TypeArgs] [ArgumentPatterns]
236236
SimplePattern1 ::= Path
237-
| ‘{’ Block ‘}’
238237
| SimplePattern1 ‘.’ id
239238
PatVar ::= varid
240239
| ‘_’

tests/neg/i1846.scala

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
object Test {
2+
def main(args: Array[String]): Unit = {
3+
val x = 42
4+
val Y = "42"
5+
6+
x match { case { 42 } => () } // error
7+
x match { case { 42.toString } => () } // error
8+
x match { case { 42 }.toString => () } // error
9+
x match { case "42".toInt => () } // error
10+
x match { case { "42".toInt } => () } // error
11+
x match { case { "42" }.toInt => () } // error
12+
x match { case { "42".toInt } => () } // error
13+
x match { case Y => () } // error
14+
x match { case { Y.toInt } => () } // error
15+
x match { case { Y }.toInt => () } // error
16+
x match { case { Y }.toString => () } // error
17+
x match { case { Y.toString } => () } // error
18+
}
19+
}

tests/neg/i3812.scala

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
object Test {
2+
def main(args: Array[String]): Unit = {
3+
val x = 42
4+
val Y = "42"
5+
6+
x match { case { 42 } => () } // error
7+
x match { case { "42".toInt } => () } // error
8+
x match { case { "42" }.toInt => () } // error
9+
x match { case { "42".toInt } => () } // error
10+
x match { case { Y.toInt } => () } // error
11+
x match { case { Y }.toInt => () } // error
12+
}
13+
}

tests/neg/i3812b.scala

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
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+
x match { case Y1.toString => () } // error
14+
15+
x match { case Z1.v => () } // error
16+
x match { case Z2.v => () } // ok
17+
18+
Some(x) match { case Some(Z1.v) => () } // error
19+
Some(x) match { case Some(Z2.v) => () } // ok
20+
21+
Some(x) match { case Some(4) | Some(Z1.v) => () } // error
22+
Some(x) match { case a @ Some(Z1.v) => () } // error
23+
24+
Some(x) match { case Some(4) | Some(Z2.v) => () } // ok
25+
Some(x) match { case a @ Some(Z2.v) => () } // ok
26+
}
27+
}

0 commit comments

Comments
 (0)