@@ -79,42 +79,42 @@ trait ConstraintHandling {
79
79
def fullBounds (param : TypeParamRef )(using Context ): TypeBounds =
80
80
nonParamBounds(param).derivedTypeBounds(fullLowerBound(param), fullUpperBound(param))
81
81
82
- protected def allowWildcards : Boolean = true
82
+ /** If true: eliminate wildcards in bounds by avoidance.
83
+ * Otherwise replace them by fresh variables, except that
84
+ * in mode TypeVarsMissContext, wildcards are always eliminated by approximation.
85
+ */
86
+ protected def approximateWildcards : Boolean = true
83
87
84
- protected def addOneBound (param : TypeParamRef , bound : Type , isUpper : Boolean )(using Context ): Boolean =
88
+ protected def addOneBound (param : TypeParamRef , bound0 : Type , isUpper : Boolean )(using Context ): Boolean =
85
89
if ! constraint.contains(param) then true
86
- else if ! isUpper && param.occursIn(bound ) then
90
+ else if ! isUpper && param.occursIn(bound0 ) then
87
91
// We don't allow recursive lower bounds when defining a type,
88
92
// so we shouldn't allow them as constraints either.
89
93
false
90
94
else
95
+ val dropWildcards = new ApproximatingTypeMap :
96
+ if ! isUpper then variance = - 1
97
+ def apply (t : Type ): Type = t match
98
+ case t : WildcardType =>
99
+ if approximateWildcards || ctx.mode.is(Mode .TypevarsMissContext ) then
100
+ val bounds = t.effectiveBounds
101
+ range(bounds.lo, bounds.hi)
102
+ else
103
+ newTypeVar(t.effectiveBounds)
104
+ case _ =>
105
+ mapOver(t)
106
+ val bound1 = dropWildcards(bound0)
91
107
val oldBounds @ TypeBounds (lo, hi) = constraint.nonParamBounds(param)
92
- val equalBounds = (if isUpper then lo else hi) eq bound
93
- if equalBounds
94
- && ! bound.existsPart(bp => bp.isInstanceOf [WildcardType ] || (bp eq param))
95
- then
96
- // The narrowed bounds are equal and do not contain wildcards,
108
+ val equalBounds = (if isUpper then lo else hi) eq bound1
109
+ if equalBounds && ! bound1.existsPart(_ eq param, stopAtStatic = true ) then
110
+ // The narrowed bounds are equal and not recursive,
97
111
// so we can remove `param` from the constraint.
98
- // (Handling wildcards requires choosing a bound, but we don't know which
99
- // bound to choose here, this is handled in `ConstraintHandling#approximation`)
100
- constraint = constraint.replace(param, bound)
112
+ constraint = constraint.replace(param, bound1)
101
113
true
102
114
else
103
- val dropWildcards = new ApproximatingTypeMap :
104
- if ! isUpper then variance = - 1
105
- def apply (t : Type ): Type = t match
106
- case t : WildcardType =>
107
- if ! allowWildcards || ctx.mode.is(Mode .TypevarsMissContext ) then
108
- val bounds = t.effectiveBounds
109
- range(bounds.lo, bounds.hi)
110
- else
111
- newTypeVar(t.effectiveBounds)
112
- case _ =>
113
- mapOver(t)
114
115
// Narrow one of the bounds of type parameter `param`
115
116
// If `isUpper` is true, ensure that `param <: `bound`, otherwise ensure
116
117
// that `param >: bound`.
117
- val bound1 = dropWildcards(bound)
118
118
val narrowedBounds =
119
119
val saved = homogenizeArgs
120
120
homogenizeArgs = Config .alignArgsInAnd
0 commit comments