@@ -79,42 +79,42 @@ trait ConstraintHandling {
7979 def fullBounds (param : TypeParamRef )(using Context ): TypeBounds =
8080 nonParamBounds(param).derivedTypeBounds(fullLowerBound(param), fullUpperBound(param))
8181
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
8387
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 =
8589 if ! constraint.contains(param) then true
86- else if ! isUpper && param.occursIn(bound ) then
90+ else if ! isUpper && param.occursIn(bound0 ) then
8791 // We don't allow recursive lower bounds when defining a type,
8892 // so we shouldn't allow them as constraints either.
8993 false
9094 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)
91107 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,
97111 // 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)
101113 true
102114 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)
114115 // Narrow one of the bounds of type parameter `param`
115116 // If `isUpper` is true, ensure that `param <: `bound`, otherwise ensure
116117 // that `param >: bound`.
117- val bound1 = dropWildcards(bound)
118118 val narrowedBounds =
119119 val saved = homogenizeArgs
120120 homogenizeArgs = Config .alignArgsInAnd
0 commit comments