@@ -87,55 +87,85 @@ trait ConstraintHandling[AbstractContext] {
87
87
nonParamBounds(param).derivedTypeBounds(fullLowerBound(param), fullUpperBound(param))
88
88
89
89
protected def addOneBound (param : TypeParamRef , rawBound : Type , isUpper : Boolean )(implicit actx : AbstractContext ): Boolean =
90
- ! constraint.contains(param) || {
91
- def avoidCycle (tp : Type ): Type = tp match
92
- case tp : AndOrType =>
93
- tp.derivedAndOrType(avoidCycle(tp.tp1), avoidCycle(tp.tp2))
94
- case tp : TypeParamRef =>
95
- if tp eq param then
96
- // println(i"stripping $tp from $rawBound, upper = $isUpper in $constraint")
97
- if isUpper then defn.AnyType else defn.NothingType
98
- else constraint.entry(tp) match
99
- case TypeBounds (lo, hi) => if lo eq hi then avoidCycle(lo) else tp
100
- case inst => avoidCycle(inst)
101
- case tp : TypeVar =>
102
- val underlying1 = avoidCycle(tp.underlying)
103
- if underlying1 eq tp.underlying then tp else underlying1
104
- case _ =>
105
- tp
90
+
91
+ /** Normalize the bound `tp` in the following ways:
92
+ *
93
+ * 1. Any toplevel occurrences of the compared parameter `param` are
94
+ * replaced by `Nothing` if bound is from below or `Any` otherwise.
95
+ * 2. Toplevel occurrences of TypeVars over TypeRefs in the current
96
+ * constraint are dereferenced.
97
+ * 3. Toplevel occurrences of TypeRefs that are instantiated in the current
98
+ * constraint are also dereferenced.
99
+ * 4. Toplevel occurrences of ExprTypes lead to a `NoType` return, which
100
+ * causes the addOneBound operation to fail.
101
+ *
102
+ * An occurrence is toplevel if it is the bound itself,
103
+ * or the bound is a union or intersection, and the ocurrence is
104
+ * toplevel in one of the operands of the `&` or `|`.
105
+ */
106
+ def avoidCycle (tp : Type ): Type = tp match
107
+ case tp : AndOrType =>
108
+ val p1 = avoidCycle(tp.tp1)
109
+ val p2 = avoidCycle(tp.tp2)
110
+ if p1.exists && p2.exists then tp.derivedAndOrType(p1, p2) else NoType
111
+ case tp : TypeParamRef =>
112
+ if tp eq param then
113
+ // println(i"stripping $tp from $rawBound, upper = $isUpper in $constraint")
114
+ if isUpper then defn.AnyType else defn.NothingType
115
+ else constraint.entry(tp) match
116
+ case TypeBounds (lo, hi) => if lo eq hi then avoidCycle(lo) else tp
117
+ case inst => avoidCycle(inst)
118
+ case tp : TypeVar =>
119
+ val underlying1 = avoidCycle(tp.underlying)
120
+ if underlying1 eq tp.underlying then tp else underlying1
121
+ case tp : ExprType =>
122
+ // ExprTypes are not value types, so type parameters should not
123
+ // be instantiated to ExprTypes. A scenario where such an attempted
124
+ // instantiation can happen is if we unify (=> T) => () with A => ()
125
+ // where A is a TypeParamRef. See the comment on EtaExpansion.etaExpand
126
+ // why types such as (=> T) => () can be constructed and i7969.scala
127
+ // as a test where this happens.
128
+ // Note that scalac by contrast allows such instantiations. But letting
129
+ // type variables be ExprTypes has its own problems (e.g. you can't write
130
+ // the resulting types down) and is largely unknown terrain.
131
+ NoType
132
+ case _ =>
133
+ tp
134
+
135
+ if ! constraint.contains(param) then false
136
+ else
106
137
val bound = avoidCycle(rawBound)
107
138
108
139
val oldBounds @ TypeBounds (lo, hi) = constraint.nonParamBounds(param)
109
140
val equalBounds = isUpper && (lo eq bound) || ! isUpper && (bound eq hi)
110
- if (equalBounds &&
111
- ! bound.existsPart(bp => bp.isInstanceOf [WildcardType ] || (bp eq param))) {
141
+ if ! bound.exists then false
142
+ else if equalBounds
143
+ && ! bound.existsPart(bp => bp.isInstanceOf [WildcardType ] || (bp eq param))
144
+ then
112
145
// The narrowed bounds are equal and do not contain wildcards,
113
146
// so we can remove `param` from the constraint.
114
147
// (Handling wildcards requires choosing a bound, but we don't know which
115
148
// bound to choose here, this is handled in `ConstraintHandling#approximation`)
116
149
constraint = constraint.replace(param, bound)
117
150
true
118
- }
119
- else {
151
+ else
120
152
// Narrow one of the bounds of type parameter `param`
121
153
// If `isUpper` is true, ensure that `param <: `bound`, otherwise ensure
122
154
// that `param >: bound`.
123
- val narrowedBounds = {
155
+ val narrowedBounds =
124
156
val saved = homogenizeArgs
125
157
homogenizeArgs = Config .alignArgsInAnd
126
158
try
127
159
if (isUpper) oldBounds.derivedTypeBounds(lo, hi & bound)
128
160
else oldBounds.derivedTypeBounds(lo | bound, hi)
129
161
finally homogenizeArgs = saved
130
- }
131
162
val c1 = constraint.updateEntry(param, narrowedBounds)
132
163
(c1 eq constraint) || {
133
164
constraint = c1
134
165
val TypeBounds (lo, hi) = constraint.entry(param)
135
166
isSubType(lo, hi)
136
167
}
137
- }
138
- }
168
+ end addOneBound
139
169
140
170
private def location (implicit ctx : Context ) = " " // i"in ${ctx.typerState.stateChainStr}" // use for debugging
141
171
@@ -201,7 +231,6 @@ trait ConstraintHandling[AbstractContext] {
201
231
up.forall(addOneBound(_, lo, isUpper = false ))
202
232
}
203
233
204
-
205
234
protected def isSubType (tp1 : Type , tp2 : Type , whenFrozen : Boolean )(implicit actx : AbstractContext ): Boolean =
206
235
if (whenFrozen)
207
236
isSubTypeWhenFrozen(tp1, tp2)
@@ -461,49 +490,6 @@ trait ConstraintHandling[AbstractContext] {
461
490
if (fromBelow) isSubType(bound, tp) else isSubType(tp, bound)
462
491
}
463
492
464
- /** Normalize the bound `bnd` in the following ways:
465
- *
466
- * 1. Any toplevel occurrences of the compared parameter `param` are
467
- * replaced by `Nothing` if bound is from below or `Any` otherwise.
468
- * 2. Toplevel occurrences of TypeVars over TypeRefs in the current
469
- * constraint are dereferenced.
470
- * 3. Toplevel occurrences of TypeRefs that are instantiated in the current
471
- * constraint are also referenced.
472
- * 4. Toplevel occurrences of ExprTypes lead to a `NoType` return, which
473
- * causes the addConstraint operation to fail.
474
- *
475
- * An occurrence is toplevel if it is the bound itself,
476
- * or the bound is a union or intersection, and the ocurrence is
477
- * toplevel in one of the operands of the `&` or `|`.
478
- */
479
- def prune (bnd : Type ): Type = bnd match
480
- case bnd : AndOrType =>
481
- val p1 = prune(bnd.tp1)
482
- val p2 = prune(bnd.tp2)
483
- if (p1.exists && p2.exists) bnd.derivedAndOrType(p1, p2)
484
- else NoType
485
- case bnd : TypeVar if constraint contains bnd.origin => // (2)
486
- prune(bnd.underlying)
487
- case bnd : TypeParamRef =>
488
- if bnd eq param then // (1)
489
- if fromBelow then defn.NothingType else defn.AnyType
490
- else constraint.entry(bnd) match
491
- case TypeBounds (lo, hi) => if lo eq hi then prune(lo) else bnd
492
- case inst => prune(inst) // (3)
493
- case bnd : ExprType => // (4)
494
- // ExprTypes are not value types, so type parameters should not
495
- // be instantiated to ExprTypes. A scenario where such an attempted
496
- // instantiation can happen is if we unify (=> T) => () with A => ()
497
- // where A is a TypeParamRef. See the comment on EtaExpansion.etaExpand
498
- // why types such as (=> T) => () can be constructed and i7969.scala
499
- // as a test where this happens.
500
- // Note that scalac by contrast allows such instantiations. But letting
501
- // type variables be ExprTypes has its own problems (e.g. you can't write
502
- // the resulting types down) and is largely unknown terrain.
503
- NoType
504
- case _ =>
505
- bnd
506
-
507
493
def kindCompatible (tp1 : Type , tp2 : Type ): Boolean =
508
494
val tparams1 = tp1.typeParams
509
495
val tparams2 = tp2.typeParams
@@ -521,9 +507,8 @@ trait ConstraintHandling[AbstractContext] {
521
507
case bound : TypeParamRef if constraint contains bound =>
522
508
addParamBound(bound)
523
509
case _ =>
524
- val pbound = prune(pruneLambdaParams(bound))
525
- pbound.exists
526
- && kindCompatible(param, pbound)
510
+ val pbound = pruneLambdaParams(bound)
511
+ kindCompatible(param, pbound)
527
512
&& (if fromBelow then addLowerBound(param, pbound) else addUpperBound(param, pbound))
528
513
finally addConstraintInvocations -= 1
529
514
}
0 commit comments