@@ -49,25 +49,34 @@ object ProtoTypes {
4949 /** Test compatibility after normalization.
5050 * Do this in a fresh typerstate unless `keepConstraint` is true.
5151 */
52- def normalizedCompatible (tp : Type , pt : Type , keepConstraint : Boolean )(using Context ): Boolean = {
53- def testCompat (using Context ): Boolean = {
52+ def normalizedCompatible (tp : Type , pt : Type , keepConstraint : Boolean )(using Context ): Boolean =
53+
54+ def testCompat (using Context ): Boolean =
5455 val normTp = normalize(tp, pt)
5556 isCompatible(normTp, pt) || pt.isRef(defn.UnitClass ) && normTp.isParameterless
56- }
57- if ( keepConstraint)
58- tp.widenSingleton match {
57+
58+ if keepConstraint || ctx.mode.is( Mode . ConstrainResultDeep ) then
59+ tp.widenSingleton match
5960 case poly : PolyType =>
60- // We can't keep the constraint in this case, since we have to add type parameters
61- // to it, but there's no place to associate them with type variables.
62- // So we'd get a "inconsistent: no typevars were added to committable constraint"
63- // assertion failure in `constrained`. To do better, we'd have to change the
64- // constraint handling architecture so that some type parameters are committable
65- // and others are not. But that's a whole different ballgame.
66- normalizedCompatible(tp, pt, keepConstraint = false )
61+ val newctx = ctx.fresh.setNewTyperState()
62+ val result = testCompat(using newctx)
63+ typr.println(
64+ i """ normalizedCompatible for $poly, $pt = $result
65+ |constraint was: ${ctx.typerState.constraint}
66+ |constraint now: ${newctx.typerState.constraint}""" )
67+ val existingVars = ctx.typerState.uninstVars.toSet
68+ if result
69+ && (ctx.typerState.constraint ne newctx.typerState.constraint)
70+ && newctx.typerState.uninstVars.forall(existingVars.contains)
71+ then newctx.typerState.commit()
72+ // If the new constrait contains fresh type variables we cannot keep it,
73+ // since those type variables are not instantiated anywhere in the source.
74+ // See pos/i6682a.scala for a test case. See pos/11243.scala and pos/i5773b.scala
75+ // for tests where it matters that we keep the constraint otherwise.
76+ result
6777 case _ => testCompat
68- }
6978 else explore(testCompat)
70- }
79+ end normalizedCompatible
7180
7281 private def disregardProto (pt : Type )(using Context ): Boolean =
7382 pt.dealias.isRef(defn.UnitClass )
@@ -80,7 +89,16 @@ object ProtoTypes {
8089 val res = pt.widenExpr match {
8190 case pt : FunProto =>
8291 mt match {
83- case mt : MethodType => constrainResult(resultTypeApprox(mt), pt.resultType)
92+ case mt : MethodType =>
93+ constrainResult(resultTypeApprox(mt), pt.resultType)
94+ && {
95+ if ctx.mode.is(Mode .ConstrainResultDeep ) then
96+ if mt.isImplicitMethod == (pt.applyKind == ApplyKind .Using ) then
97+ val tpargs = pt.args.lazyZip(mt.paramInfos).map(pt.typedArg)
98+ tpargs.tpes.corresponds(mt.paramInfos)(_ <:< _)
99+ else true
100+ else true
101+ }
84102 case _ => true
85103 }
86104 case _ : ValueTypeOrProto if ! disregardProto(pt) =>
@@ -123,6 +141,7 @@ object ProtoTypes {
123141 abstract case class IgnoredProto (ignored : Type ) extends CachedGroundType with MatchAlways :
124142 override def revealIgnored = ignored
125143 override def deepenProto (using Context ): Type = ignored
144+ override def deepenProtoTrans (using Context ): Type = ignored.deepenProtoTrans
126145
127146 override def computeHash (bs : Hashable .Binders ): Int = doHash(bs, ignored)
128147
@@ -202,7 +221,12 @@ object ProtoTypes {
202221 def map (tm : TypeMap )(using Context ): SelectionProto = derivedSelectionProto(name, tm(memberProto), compat)
203222 def fold [T ](x : T , ta : TypeAccumulator [T ])(using Context ): T = ta(x, memberProto)
204223
205- override def deepenProto (using Context ): SelectionProto = derivedSelectionProto(name, memberProto.deepenProto, compat)
224+ override def deepenProto (using Context ): SelectionProto =
225+ derivedSelectionProto(name, memberProto.deepenProto, compat)
226+
227+ override def deepenProtoTrans (using Context ): SelectionProto =
228+ derivedSelectionProto(name, memberProto.deepenProtoTrans, compat)
229+
206230 override def computeHash (bs : Hashable .Binders ): Int = {
207231 val delta = (if (compat eq NoViewsAllowed ) 1 else 0 ) | (if (privateOK) 2 else 0 )
208232 addDelta(doHash(bs, name, memberProto), delta)
@@ -419,7 +443,11 @@ object ProtoTypes {
419443 def fold [T ](x : T , ta : TypeAccumulator [T ])(using Context ): T =
420444 ta(ta.foldOver(x, typedArgs().tpes), resultType)
421445
422- override def deepenProto (using Context ): FunProto = derivedFunProto(args, resultType.deepenProto, typer)
446+ override def deepenProto (using Context ): FunProto =
447+ derivedFunProto(args, resultType.deepenProto, typer)
448+
449+ override def deepenProtoTrans (using Context ): FunProto =
450+ derivedFunProto(args, resultType.deepenProtoTrans, typer)
423451
424452 override def withContext (newCtx : Context ): ProtoType =
425453 if newCtx `eq` protoCtx then this
@@ -472,7 +500,11 @@ object ProtoTypes {
472500 def fold [T ](x : T , ta : TypeAccumulator [T ])(using Context ): T =
473501 ta(ta(x, argType), resultType)
474502
475- override def deepenProto (using Context ): ViewProto = derivedViewProto(argType, resultType.deepenProto)
503+ override def deepenProto (using Context ): ViewProto =
504+ derivedViewProto(argType, resultType.deepenProto)
505+
506+ override def deepenProtoTrans (using Context ): ViewProto =
507+ derivedViewProto(argType, resultType.deepenProtoTrans)
476508 }
477509
478510 class CachedViewProto (argType : Type , resultType : Type ) extends ViewProto (argType, resultType) {
@@ -522,7 +554,11 @@ object ProtoTypes {
522554 def fold [T ](x : T , ta : TypeAccumulator [T ])(using Context ): T =
523555 ta(ta.foldOver(x, targs.tpes), resultType)
524556
525- override def deepenProto (using Context ): PolyProto = derivedPolyProto(targs, resultType.deepenProto)
557+ override def deepenProto (using Context ): PolyProto =
558+ derivedPolyProto(targs, resultType.deepenProto)
559+
560+ override def deepenProtoTrans (using Context ): PolyProto =
561+ derivedPolyProto(targs, resultType.deepenProtoTrans)
526562 }
527563
528564 /** A prototype for expressions [] that are known to be functions:
0 commit comments