@@ -20,6 +20,7 @@ import ast.tpd.*
2020import  Synthesizer .* 
2121import  sbt .ExtractDependencies .* 
2222import  xsbti .api .DependencyContext .* 
23+ import  TypeComparer .{fullLowerBound , fullUpperBound }
2324
2425/**  Synthesize terms for special classes */ 
2526class  Synthesizer (typer : Typer )(using  @ constructorOnly c : Context ): 
@@ -38,10 +39,32 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
3839        //  bounds are usually widened during instantiation.
3940        instArg(tp.tp1)
4041      case  tvar : TypeVar  if  ctx.typerState.constraint.contains(tvar) => 
42+       	//  If tvar has a lower or upper bound:
43+       	//    1. If the bound is not another type variable, use this as approximation.
44+       	//    2. Otherwise, if the type can be forced to be fully defined, use that type
45+       	//       as approximation.
46+       	//    3. Otherwise leave argument uninstantiated.
47+       	//  The reason for (2) is that we observed complicated constraints in i23611.scala
48+       	//  that get better types if a fully defined type is computed than if several type
49+       	//  variables are approximated incrementally. This is a minimization of some ZIO code.
50+       	//  So in order to keep backwards compatibility (where before we _only_ did 2) we
51+       	//  add that special case.
52+         def  isGroundConstr (tp : Type ):  Boolean  =  tp.dealias match 
53+           case  tvar : TypeVar  if  ctx.typerState.constraint.contains(tvar) =>  false 
54+           case  pref : TypeParamRef  if  ctx.typerState.constraint.contains(pref) =>  false 
55+           case  tp : AndOrType  =>  isGroundConstr(tp.tp1) &&  isGroundConstr(tp.tp2)
56+           case  _ =>  true 
4157        instArg(
42-             if  tvar.hasLowerBound then  tvar.instantiate(fromBelow =  true )
43-             else  if  tvar.hasUpperBound then  tvar.instantiate(fromBelow =  false )
44-             else  NoType )
58+             if  tvar.hasLowerBound then 
59+               if  isGroundConstr(fullLowerBound(tvar.origin)) then  tvar.instantiate(fromBelow =  true )
60+               else  if  isFullyDefined(tp, ForceDegree .all) then  tp
61+               else  NoType 
62+             else  if  tvar.hasUpperBound then 
63+               if  isGroundConstr(fullUpperBound(tvar.origin)) then  tvar.instantiate(fromBelow =  false )
64+               else  if  isFullyDefined(tp, ForceDegree .all) then  tp
65+               else  NoType 
66+             else 
67+               NoType )
4568      case  _ => 
4669        tp
4770
@@ -569,9 +592,8 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
569592                  resType <:<  target
570593                  val  tparams  =  poly.paramRefs
571594                  val  variances  =  childClass.typeParams.map(_.paramVarianceSign)
572-                   val  instanceTypes  =  tparams.lazyZip(variances).map( (tparam, variance) => 
595+                   val  instanceTypes  =  tparams.lazyZip(variances).map:   (tparam, variance) => 
573596                    TypeComparer .instanceType(tparam, fromBelow =  variance <  0 , Widen .Unions )
574-                   )
575597                  val  instanceType  =  resType.substParams(poly, instanceTypes)
576598                  //  this is broken in tests/run/i13332intersection.scala,
577599                  //  because type parameters are not correctly inferred.
0 commit comments