@@ -18,6 +18,7 @@ import annotation.{tailrec, constructorOnly}
18
18
import ast .tpd
19
19
import ast .tpd .*
20
20
import Synthesizer .*
21
+ import TypeComparer .{fullLowerBound , fullUpperBound }
21
22
22
23
/** Synthesize terms for special classes */
23
24
class Synthesizer (typer : Typer )(using @ constructorOnly c : Context ):
@@ -36,10 +37,32 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
36
37
// bounds are usually widened during instantiation.
37
38
instArg(tp.tp1)
38
39
case tvar : TypeVar if ctx.typerState.constraint.contains(tvar) =>
40
+ // If tvar has a lower or upper bound:
41
+ // 1. If the bound is not another type variable, use this as approximation.
42
+ // 2. Otherwise, if the type can be forced to be fully defined, use that type
43
+ // as approximation.
44
+ // 3. Otherwise leave argument uninstantiated.
45
+ // The reason for (2) is that we observed complicated constraints in i23611.scala
46
+ // that get better types if a fully defined type is computed than if several type
47
+ // variables are approximated incrementally. This is a minimization of some ZIO code.
48
+ // So in order to keep backwards compatibility (where before we _only_ did 2) we
49
+ // add that special case.
50
+ def isGroundConstr (tp : Type ): Boolean = tp.dealias match
51
+ case tvar : TypeVar if ctx.typerState.constraint.contains(tvar) => false
52
+ case pref : TypeParamRef if ctx.typerState.constraint.contains(pref) => false
53
+ case tp : AndOrType => isGroundConstr(tp.tp1) && isGroundConstr(tp.tp2)
54
+ case _ => true
39
55
instArg(
40
- if tvar.hasLowerBound then tvar.instantiate(fromBelow = true )
41
- else if tvar.hasUpperBound then tvar.instantiate(fromBelow = false )
42
- else NoType )
56
+ if tvar.hasLowerBound then
57
+ if isGroundConstr(fullLowerBound(tvar.origin)) 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(fullUpperBound(tvar.origin)) then tvar.instantiate(fromBelow = false )
62
+ else if isFullyDefined(tp, ForceDegree .all) then tp
63
+ else NoType
64
+ else
65
+ NoType )
43
66
case _ =>
44
67
tp
45
68
0 commit comments