Skip to content

Commit c9bf740

Browse files
authored
Merge pull request #10916 from dotty-staging/fix-#10605
Fix #10605: Avoid mismatched constraints when prototypes are context …
2 parents ce61070 + 5b6c079 commit c9bf740

File tree

2 files changed

+18
-9
lines changed

2 files changed

+18
-9
lines changed

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

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,13 @@ object ProtoTypes {
3838
def isCompatible(tp: Type, pt: Type)(using Context): Boolean =
3939
(tp.widenExpr relaxed_<:< pt.widenExpr) || viewExists(tp, pt)
4040

41-
/** Like isCompatibe, but using a subtype comparison with necessary eithers
42-
* that don't unnecessarily truncate the constraint space, returning false instead.
41+
/** Like normalize and then isCompatible, but using a subtype comparison with
42+
* necessary eithers that does not unnecessarily truncate the constraint space,
43+
* returning false instead.
4344
*/
4445
def necessarilyCompatible(tp: Type, pt: Type)(using Context): Boolean =
45-
val tpw = tp.widenExpr
46-
val ptw = pt.widenExpr
47-
necessarySubType(tpw, ptw) || tpw.isValueSubType(ptw) || viewExists(tp, pt)
46+
val tpn = normalize(tp, pt, followIFT = !defn.isContextFunctionType(pt))
47+
necessarySubType(tpn, pt) || tpn.isValueSubType(pt) || viewExists(tpn, pt)
4848

4949
/** Test compatibility after normalization.
5050
* Do this in a fresh typerstate unless `keepConstraint` is true.
@@ -84,9 +84,9 @@ object ProtoTypes {
8484
case _ => true
8585
}
8686
case _: ValueTypeOrProto if !disregardProto(pt) =>
87-
necessarilyCompatible(normalize(mt, pt), pt)
87+
necessarilyCompatible(mt, pt)
8888
case pt: WildcardType if pt.optBounds.exists =>
89-
necessarilyCompatible(normalize(mt, pt), pt)
89+
necessarilyCompatible(mt, pt)
9090
case _ =>
9191
true
9292
}
@@ -601,7 +601,7 @@ object ProtoTypes {
601601
* of toString method. The problem is solved by dereferencing nullary method types if the corresponding
602602
* function type is not compatible with the prototype.
603603
*/
604-
def normalize(tp: Type, pt: Type)(using Context): Type = {
604+
def normalize(tp: Type, pt: Type, followIFT: Boolean = true)(using Context): Type = {
605605
Stats.record("normalize")
606606
tp.widenSingleton match {
607607
case poly: PolyType =>
@@ -626,7 +626,7 @@ object ProtoTypes {
626626
normalize(et.resultType, pt)
627627
case wtp =>
628628
val iftp = defn.asContextFunctionType(wtp)
629-
if iftp.exists then normalize(iftp.dropDependentRefinement.argInfos.last, pt)
629+
if iftp.exists && followIFT then normalize(iftp.dropDependentRefinement.argInfos.last, pt)
630630
else tp
631631
}
632632
}

tests/neg/i10605.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
def xa[A, B, X, Y](f: X => ((A, B) ?=> Y)) =
2+
(z: X) => (a: A, b: B) => f(z)(using a, b)
3+
4+
def superxa1(using String, Int): Nothing = ???
5+
def superxa2(using String, Int): Unit = ???
6+
7+
def main =
8+
xa(Function.const(superxa1)(_: Int)) // error
9+
xa(Function.const(superxa2)(_: Int)) // error

0 commit comments

Comments
 (0)