@@ -14,6 +14,7 @@ import Uniques._
14
14
import config .Printers .typr
15
15
import util .SourceFile
16
16
import util .Property
17
+ import TypeComparer .necessarySubType
17
18
18
19
import scala .annotation .internal .sharable
19
20
@@ -37,6 +38,14 @@ object ProtoTypes {
37
38
def isCompatible (tp : Type , pt : Type )(using Context ): Boolean =
38
39
(tp.widenExpr relaxed_<:< pt.widenExpr) || viewExists(tp, pt)
39
40
41
+ /** Like isCompatibe, but using a subtype comparison with necessary eithers
42
+ * that don't unnecessarily truncate the constraint space, returning false instead.
43
+ */
44
+ 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)
48
+
40
49
/** Test compatibility after normalization.
41
50
* Do this in a fresh typerstate unless `keepConstraint` is true.
42
51
*/
@@ -67,24 +76,22 @@ object ProtoTypes {
67
76
* fits the given expected result type.
68
77
*/
69
78
def constrainResult (mt : Type , pt : Type )(using Context ): Boolean =
70
- withMode(Mode .ConstrainResult ) {
71
- val savedConstraint = ctx.typerState.constraint
72
- val res = pt.widenExpr match {
73
- case pt : FunProto =>
74
- mt match {
75
- case mt : MethodType => constrainResult(resultTypeApprox(mt), pt.resultType)
76
- case _ => true
77
- }
78
- case _ : ValueTypeOrProto if ! disregardProto(pt) =>
79
- isCompatible(normalize(mt, pt), pt)
80
- case pt : WildcardType if pt.optBounds.exists =>
81
- isCompatible(normalize(mt, pt), pt)
82
- case _ =>
83
- true
84
- }
85
- if ! res then ctx.typerState.constraint = savedConstraint
86
- res
79
+ val savedConstraint = ctx.typerState.constraint
80
+ val res = pt.widenExpr match {
81
+ case pt : FunProto =>
82
+ mt match {
83
+ case mt : MethodType => constrainResult(resultTypeApprox(mt), pt.resultType)
84
+ case _ => true
85
+ }
86
+ case _ : ValueTypeOrProto if ! disregardProto(pt) =>
87
+ necessarilyCompatible(normalize(mt, pt), pt)
88
+ case pt : WildcardType if pt.optBounds.exists =>
89
+ necessarilyCompatible(normalize(mt, pt), pt)
90
+ case _ =>
91
+ true
87
92
}
93
+ if ! res then ctx.typerState.constraint = savedConstraint
94
+ res
88
95
89
96
/** Constrain result with special case if `meth` is an inlineable method in an inlineable context.
90
97
* In that case, we should always succeed and not constrain type parameters in the expected type,
0 commit comments