@@ -171,6 +171,57 @@ trait ConstraintHandling {
171
171
inst
172
172
}
173
173
174
+ /** The instance type of `param` in the current constraint (which contains `param`).
175
+ * If `fromBelow` is true, the instance type is the lub of the parameter's
176
+ * lower bounds; otherwise it is the glb of its upper bounds. However,
177
+ * a lower bound instantiation can be a singleton type only if the upper bound
178
+ * is also a singleton type.
179
+ */
180
+ def instanceType (param : PolyParam , fromBelow : Boolean ): Type = {
181
+ def upperBound = constraint.fullUpperBound(param)
182
+ def isSingleton (tp : Type ): Boolean = tp match {
183
+ case tp : SingletonType => true
184
+ case AndType (tp1, tp2) => isSingleton(tp1) | isSingleton(tp2)
185
+ case OrType (tp1, tp2) => isSingleton(tp1) & isSingleton(tp2)
186
+ case _ => false
187
+ }
188
+ def isFullyDefined (tp : Type ): Boolean = tp match {
189
+ case tp : TypeVar => tp.isInstantiated && isFullyDefined(tp.instanceOpt)
190
+ case tp : TypeProxy => isFullyDefined(tp.underlying)
191
+ case tp : AndOrType => isFullyDefined(tp.tp1) && isFullyDefined(tp.tp2)
192
+ case _ => true
193
+ }
194
+ def isOrType (tp : Type ): Boolean = tp.stripTypeVar.dealias match {
195
+ case tp : OrType => true
196
+ case tp : RefinedOrRecType => isOrType(tp.parent)
197
+ case AndType (tp1, tp2) => isOrType(tp1) | isOrType(tp2)
198
+ case WildcardType (bounds : TypeBounds ) => isOrType(bounds.hi)
199
+ case _ => false
200
+ }
201
+
202
+ // First, solve the constraint.
203
+ var inst = approximation(param, fromBelow)
204
+
205
+ // Then, approximate by (1.) - (3.) and simplify as follows.
206
+ // 1. If instance is from below and is a singleton type, yet
207
+ // upper bound is not a singleton type, widen the instance.
208
+ if (fromBelow && isSingleton(inst) && ! isSingleton(upperBound))
209
+ inst = inst.widen
210
+
211
+ inst = inst.simplified
212
+
213
+ // 2. If instance is from below and is a fully-defined union type, yet upper bound
214
+ // is not a union type, approximate the union type from above by an intersection
215
+ // of all common base types.
216
+ if (fromBelow && isOrType(inst) && isFullyDefined(inst) && ! isOrType(upperBound))
217
+ inst = inst.approximateUnion
218
+
219
+ // 3. If instance is from below, and upper bound has open named parameters
220
+ // make sure the instance has all named parameters of the bound.
221
+ if (fromBelow) inst = inst.widenToNamedTypeParams(param.namedTypeParams)
222
+ inst
223
+ }
224
+
174
225
/** Constraint `c1` subsumes constraint `c2`, if under `c2` as constraint we have
175
226
* for all poly params `p` defined in `c2` as `p >: L2 <: U2`:
176
227
*
0 commit comments