8000 SI-9630 Fix spurious warning related to same-named case accessors [ba… · scala/scala@da98683 · GitHub
[go: up one dir, main page]

Skip to content

Commit da98683

Browse files
retronymadriaanm
authored andcommitted
SI-9630 Fix spurious warning related to same-named case accessors [backport]
Hash consing of trees within pattern match analysis was broken, and considered `x1.foo#1` to be the same tree as `x1.foo#2`, even though the two `foo`-s referred to different symbols. The hash consing was based on `Tree#correspondsStructure`, but the predicate in that function cannot veto correspondance, it can only supplement the default structural comparison. I've instead created a custom tree comparison method for use in the pattern matcher that handles the tree shapes that we use. (cherry picked from commit 79a52e6)
1 parent 80ce231 commit da98683

File tree

11 files changed

+112
-7
lines changed

11 files changed

+112
-7
lines changed

src/compiler/scala/tools/nsc/transform/patmat/Logic.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -691,7 +691,7 @@ trait ScalaLogic extends Interface with Logic with TreeAndTypeAnalysis {
691691
// if X is mutable.
692692
freshExistentialSubtype(t.tpe)
693693
}
694-
else trees find (a => a.correspondsStructure(t)(sameValue)) match {
694+
else trees find (a => equivalentTree(a, t)) match {
695695
case Some(orig) =>
696696
debug.patmat("unique tp for tree: " + ((orig, orig.tpe)))
697697
orig.tpe

src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -85,11 +85,15 @@ trait TreeAndTypeAnalysis extends Debugging {
8585
tp <:< tpImpliedNormalizedToAny
8686
}
8787

88-
// TODO: improve, e.g., for constants
89-
def sameValue(a: Tree, b: Tree): Boolean = (a eq b) || ((a, b) match {
90-
case (_ : Ident, _ : Ident) => a.symbol eq b.symbol
91-
case _ => false
92-
})
88+
def equivalentTree(a: Tree, b: Tree): Boolean = (a, b) match {
89+
case (Select(qual1, _), Select(qual2, _)) => equivalentTree(qual1, qual2) && a.symbol == b.symbol
90+
case (Ident(_), Ident(_)) => a.symbol == b.symbol
91+
case (Literal(c1), Literal(c2)) => c1 == c2
92+
case (This(_), This(_)) => a.symbol == b.symbol
93+
case (Apply(fun1, args1), Apply(fun2, args2)) => equivalentTree(fun1, fun2) && args1.corresponds(args2)(equivalentTree)
94+
// Those are the only cases we need to handle in the pattern matcher
95+
case _ => false
96+
}
9397

9498
trait CheckableTreeAndTypeAnalysis {
9599
val typer: Typer
@@ -277,7 +281,7 @@ trait MatchApproximation extends TreeAndTypeAnalysis with ScalaLogic with MatchT
277281

278282
// hashconsing trees (modulo value-equality)
279283
def unique(t: Tree, tpOverride: Type = NoType): Tree =
280-
trees find (a => a.correspondsStructure(t)(sameValue)) match {
284+
trees find (a => equivalentTree(a, t)) match {
281285
case Some(orig) =>
282286
// debug.patmat("unique: "+ (t eq orig, orig))
283287
orig

test/files/pos/t9399.flags

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
-Xfatal-warnings

test/files/pos/t9399.scala

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
sealed abstract class TA
2+
sealed abstract class TB extends TA
3+
case object A extends TA
4+
case object B extends TB
5+
6+
sealed trait C
7+
case class CTA(id: Int, da: TA) extends C
8+
case class CTB(id: Int, da: TB) extends C
9+
10+
class Test {
11+
def test(c: C): Unit = c match {
12+
case CTA(_, A) =>
13+
case CTA(_, B) =>
14+
case CTB(_, B) =>
15+
}
16+
}
17+

test/files/pos/t9411a.flags

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
-Xfatal-warnings

test/files/pos/t9411a.scala

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
object OhNoes {
2+
3+
sealed trait F
4+
sealed abstract class FA extends F
5+
sealed abstract class FB extends F
6+
7+
case object FA1 extends FA
8+
case object FB1 extends FB
9+
case object FB2 extends FB
10+
11+
sealed trait G
12+
case object G1 extends G
13+
case object G2 extends G
14+
15+
sealed trait H
16+
case class H1(a: FB, b: G) extends H
17+
case class H2(a: F) extends H
18+
19+
val demo: H => Unit = {
20+
case H1(FB1, G1) =>
21+
case H1(FB2, G2) =>
22+
case H2(_: FB) =>
23+
case H2(_: FA) =>
24+
case H1(FB1, G2) =>
25+
case H1(FB2, G1) =>
26+
}
27+
}

test/files/pos/t9411b.flags

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
-Xfatal-warnings

test/files/pos/t9411b.scala

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
object OhNoes {
2+
3+
sealed trait F
4+
sealed abstract class FA extends F
5+
sealed abstract class FB extends F
6+
7+
case object FA1 extends FA
8+
case object FB1 extends FB
9+
case object FB2 extends FB
10+
11+
sealed trait G
12+
case object G1 extends G
13+
case object G2 extends G
14+
15+
sealed trait H
16+
case class H1(a: FB, b: G) extends H
17+
case class H2(b: F) extends H
18+
19+
val demo: H => Unit = {
20+
case H1(FB1, G1) =>
21+
case H1(FB2, G2) =>
22+
case H2(_: FB) =>
23+
case H2(_: FA) =>
24+
case H1(FB1, G2) =>
25+
case H1(FB2, G1) =>
26+
}
27+
28+
val demo2: H => Unit = {
29+
case H2(_: FA) =>
30+
case H2(_: FB) =>
31+
case H1(FB1, G1) =>
32+
case H1(FB2, G1) =>
33+
case H1(FB1, G2) =>
34+
case H1(FB2, G2) =>
35+
}
36+
}

test/files/pos/t9630.flags

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
-Xfatal-warnings

test/files/pos/t9630/t9630a.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
2+
sealed trait Base
3+
final case class Base_1(sameName: Some[Any]) extends Base
4+
final case class Base_2(sameName: Nested) extends Base
5+
6+
sealed trait Nested
7+
final case class Nested_1(x: Any) extends Nested
8+
final case class Nested_2(y: Any) extends Nested
9+

test/files/pos/t9630/t9630b.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
2+
class Test {
3+
def test(b: Base): Unit = b match {
4+
case Base_1(Some(_)) =>
5+
case Base_2(Nested_1(_)) =>
6+
case Base_2(Nested_2(_)) =>
7+
}
8+
}

0 commit comments

Comments
 (0)
0