Skip to content

Commit 5772538

Browse files
Merge pull request #8789 from dotty-staging/fix-8758
Fix #8758: strengthen the precondition for comparing extractors
2 parents 1f31d57 + 74e46c5 commit 5772538

File tree

2 files changed

+17
-6
lines changed

2 files changed

+17
-6
lines changed

compiler/src/dotty/tools/dotc/transform/patmat/Space.scala

+12-6
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,13 @@ trait SpaceLogic {
7979
/** Is `tp1` a subtype of `tp2`? */
8080
def isSubType(tp1: Type, tp2: Type): Boolean
8181

82-
/** Is `tp1` the same type as `tp2`? */
83-
def isEqualType(tp1: Type, tp2: Type): Boolean
82+
/** Whether we may assume the two Unapply the same?
83+
* That is, given the same parameter, returns the same result.
84+
*
85+
* This is more general than purity, as the same `unapply` method may
86+
* take different prefix, thus behaves differently.
87+
*/
88+
def isSameUnapply(tp1: TermRef, tp2: TermRef): Boolean
8489

8590
/** Return a space containing the values of both types.
8691
*
@@ -179,7 +184,7 @@ trait SpaceLogic {
179184
// approximation: a type can never be fully matched by a partial extractor
180185
full && isSubType(tp1, tp2) && isSubspace(Prod(tp2, fun, signature(fun, tp2, ss.length).map(Typ(_, false)), full), b)
181186
case (Prod(_, fun1, ss1, _), Prod(_, fun2, ss2, _)) =>
182-
isEqualType(fun1, fun2) && ss1.zip(ss2).forall((isSubspace _).tupled)
187+
isSameUnapply(fun1, fun2) && ss1.zip(ss2).forall((isSubspace _).tupled)
183188
}
184189
}
185190

@@ -217,7 +222,7 @@ trait SpaceLogic {
217222
else if (canDecompose(tp2)) tryDecompose2(tp2)
218223
else Empty
219224
case (Prod(tp1, fun1, ss1, full), Prod(tp2, fun2, ss2, _)) =>
220-
if (!isEqualType(fun1, fun2)) Empty
225+
if (!isSameUnapply(fun1, fun2)) Empty
221226
else if (ss1.zip(ss2).exists(p => simplify(intersect(p._1, p._2)) == Empty)) Empty
222227
else Prod(tp1, fun1, ss1.zip(ss2).map((intersect _).tupled), full)
223228
}
@@ -257,7 +262,7 @@ trait SpaceLogic {
257262
case (Typ(tp1, _), Prod(tp2, _, _, false)) =>
258263
a // approximation
259264
case (Prod(tp1, fun1, ss1, full), Prod(tp2, fun2, ss2, _)) =>
260-
if (!isEqualType(fun1, fun2)) a
265+
if (!isSameUnapply(fun1, fun2)) a
261266
else if (ss1.zip(ss2).exists(p => simplify(intersect(p._1, p._2)) == Empty)) a
262267
else if (ss1.zip(ss2).forall((isSubspace _).tupled)) Empty
263268
else
@@ -499,7 +504,8 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
499504
res
500505
}
501506

502-
def isEqualType(tp1: Type, tp2: Type): Boolean = tp1 =:= tp2
507+
def isSameUnapply(tp1: TermRef, tp2: TermRef): Boolean =
508+
tp1.prefix.isStable && tp2.prefix.isStable && tp1 =:= tp2
503509

504510
/** Parameter types of the case class type `tp`. Adapted from `unapplyPlan` in patternMatcher */
505511
def signature(unapp: TermRef, scrutineeTp: Type, argLen: Int): List[Type] = {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
def test = "?johndoe" match {
2+
case s":$name" => println(s":name $name")
3+
case s"{$name}" => println(s"{name} $name")
4+
case s"?$pos" => println(s"pos $pos")
5+
}

0 commit comments

Comments
 (0)