@@ -14,6 +14,7 @@ import Uniques._
1414import config .Printers .typr
1515import util .SourceFile
1616import util .Property
17+ import TypeComparer .necessarySubType
1718
1819import scala .annotation .internal .sharable
1920
@@ -37,6 +38,14 @@ object ProtoTypes {
3738 def isCompatible (tp : Type , pt : Type )(using Context ): Boolean =
3839 (tp.widenExpr relaxed_<:< pt.widenExpr) || viewExists(tp, pt)
3940
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+
4049 /** Test compatibility after normalization.
4150 * Do this in a fresh typerstate unless `keepConstraint` is true.
4251 */
@@ -67,24 +76,22 @@ object ProtoTypes {
6776 * fits the given expected result type.
6877 */
6978 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
8792 }
93+ if ! res then ctx.typerState.constraint = savedConstraint
94+ res
8895
8996 /** Constrain result with special case if `meth` is an inlineable method in an inlineable context.
9097 * In that case, we should always succeed and not constrain type parameters in the expected type,
0 commit comments