@@ -38,9 +38,29 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
38
38
// bounds are usually widened during instantiation.
39
39
instArg(tp.tp1)
40
40
case tvar : TypeVar if ctx.typerState.constraint.contains(tvar) =>
41
+ // If tvar has a lower or upper bound:
42
+ // 1. If the bound is not another type variable, use this as approximation.
43
+ // 2. Otherwise, if the type can be forced to be fully defined, use that type
44
+ // as approximation.
45
+ // 3. Otherwise leave argument uninstantiated.
46
+ // The reason for (2) is that we observed complicated constraints in i23611.scala
47
+ // that get better types if a fully defined type is computed than if several type
48
+ // variables are approximated incrementally. This is a minimization of some ZIP code.
49
+ // So in order to keep backwards compatibility (where before we _only_ did 2) we
50
+ // add that special case.
51
+ def isGroundConstr (tp : Type ): Boolean = tp.dealias match
52
+ case tvar : TypeVar if ctx.typerState.constraint.contains(tvar) => false
53
+ case tp : AndOrType => isGroundConstr(tp.tp1) && isGroundConstr(tp.tp2)
54
+ case _ => true
41
55
instArg(
42
- if tvar.hasLowerBound then tvar.instantiate(fromBelow = true )
43
- else if tvar.hasUpperBound then tvar.instantiate(fromBelow = false )
56
+ if tvar.hasLowerBound then
57
+ if isGroundConstr(tvar.lowerBound) then tvar.instantiate(fromBelow = true )
58
+ else if isFullyDefined(tp, ForceDegree .all) then tp
59
+ else NoType
60
+ else if tvar.hasUpperBound then
61
+ if isGroundConstr(tvar.upperBound) then tvar.instantiate(fromBelow = false )
62
+ else if isFullyDefined(tp, ForceDegree .all) then tp
63
+ else NoType
44
64
else NoType )
45
65
case _ =>
46
66
tp
0 commit comments