Skip to content

Commit bd1fff2

Browse files
authored
Merge pull request #8710 from dotty-staging/typed-patterns
More precise type for typed patterns, less precise for literal patterns
2 parents 85ab20f + 2b1d5c0 commit bd1fff2

File tree

3 files changed

+41
-4
lines changed

3 files changed

+41
-4
lines changed

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

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1718,10 +1718,16 @@ class Typer extends Namer
17181718
}
17191719
if (name == nme.WILDCARD) body1
17201720
else {
1721-
// for a singleton pattern like `x @ Nil`, `x` should get the type from the scrutinee
1722-
// see tests/neg/i3200b.scala and SI-1503
1721+
// In `x @ Nil`, `Nil` is a _stable identifier pattern_ and will be compiled
1722+
// to an `==` test, so the type of `x` is unrelated to the type of `Nil`.
1723+
// Similarly, in `x @ 1`, `1` is a _literal pattern_ and will also be compiled
1724+
// to an `==` test.
1725+
// See i3200*.scala and https://github.com/scala/bug/issues/1503.
1726+
val isStableIdentifierOrLiteral =
1727+
body1.isInstanceOf[RefTree] && !isWildcardArg(body1)
1728+
|| body1.isInstanceOf[Literal]
17231729
val symTp =
1724-
if body1.tpe.isInstanceOf[TermRef] then pt
1730+
if isStableIdentifierOrLiteral then pt
17251731
else if isWildcardStarArg(body1)
17261732
|| pt == defn.ImplicitScrutineeTypeRef
17271733
|| body1.tpe <:< pt // There is some strange interaction with gadt matching.

tests/neg/i3200b.scala

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
object Test {
22
def main(args: Array[String]): Unit = {
3-
val a : Nil.type = (Vector(): Any) match { case n @ Nil => n } // error
3+
val a: Nil.type = (Vector(): Any) match { case n @ Nil => n } // error
4+
val b: Nil.type = (Vector(): Any) match { case n @ (m @ Nil) => n } // error
5+
val c: Int = (1.0: Any) match { case n @ 1 => n } // error
6+
val d: Int = (1.0: Any) match { case n @ (m @ 1) => n } // error
47
}
58
}

tests/run/i3200c.scala

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
sealed trait X
2+
case object Y extends X
3+
4+
object Test {
5+
def yIs1(proof: Y.type): Int = 1
6+
7+
def test(x: X) = x match {
8+
case y: Y.type => yIs1(y)
9+
}
10+
11+
def test2(x: X) = x match {
12+
case y @ (yy: Y.type) =>
13+
yIs1(y)
14+
yIs1(yy)
15+
}
16+
17+
def main(args: Array[String]): Unit = {
18+
test(Y)
19+
20+
val a: Nil.type = (Vector(): Any) match {
21+
case n: Nil.type =>
22+
assert(false, "should not be reached")
23+
n
24+
case _ =>
25+
Nil
26+
}
27+
}
28+
}

0 commit comments

Comments
 (0)