@@ -266,31 +266,72 @@ trait TypeOps { this: Context => // TODO: Make standalone object.
266
266
val accu1 = if (accu exists (_ derivesFrom c)) accu else c :: accu
267
267
if (cs == c.baseClasses) accu1 else dominators(rest, accu1)
268
268
}
269
- if (ctx.featureEnabled(defn.LanguageModuleClass , nme.keepUnions)) tp
270
- else tp match {
271
- case tp : OrType =>
272
- def isClassRef (tp : Type ): Boolean = tp match {
273
- case tp : TypeRef => tp.symbol.isClass
274
- case tp : RefinedType => isClassRef(tp.parent)
275
- case _ => false
276
- }
277
- def next (tp : TypeProxy ) = tp.underlying match {
278
- case TypeBounds (_, hi) => hi
279
- case nx => nx
280
- }
281
- tp.tp1 match {
282
- case tp1 : TypeProxy if ! isClassRef(tp1) =>
283
- approximateUnion(next(tp1) | tp.tp2)
284
- case _ =>
285
- tp.tp2 match {
286
- case tp2 : TypeProxy if ! isClassRef(tp2) =>
287
- approximateUnion(tp.tp1 | next(tp2))
269
+ def approximateOr (tp1 : Type , tp2 : Type ): Type = {
270
+ def isClassRef (tp : Type ): Boolean = tp match {
271
+ case tp : TypeRef => tp.symbol.isClass
272
+ case tp : RefinedType => isClassRef(tp.parent)
273
+ case _ => false
274
+ }
275
+ def next (tp : TypeProxy ) = tp.underlying match {
276
+ case TypeBounds (_, hi) => hi
277
+ case nx => nx
278
+ }
279
+ /** If `tp1` and `tp2` are typebounds, try to make one fit into the other
280
+ * or to make them equal, by instantiating uninstantiated type variables.
281
+ */
282
+ def homogenizedUnion (tp1 : Type , tp2 : Type ): Type = {
283
+ tp1 match {
284
+ case tp1 : TypeBounds =>
285
+ tp2 match {
286
+ case tp2 : TypeBounds =>
287
+ def fitInto (tp1 : TypeBounds , tp2 : TypeBounds ): Unit = {
288
+ val nestedCtx = ctx.fresh.setNewTyperState
289
+ if (tp2.boundsInterval.contains(tp1.boundsInterval)(nestedCtx))
290
+ nestedCtx.typerState.commit()
291
+ }
292
+ fitInto(tp1, tp2)
293
+ fitInto(tp2, tp1)
288
294
case _ =>
289
- val commonBaseClasses = tp.mapReduceOr(_.baseClasses)(intersect)
290
- val doms = dominators(commonBaseClasses, Nil )
291
- doms.map(tp.baseTypeWithArgs).reduceLeft(AndType .apply)
292
295
}
296
+ case _ =>
293
297
}
298
+ tp1 | tp2
299
+ }
300
+
301
+ tp1 match {
302
+ case tp1 : RefinedType =>
303
+ tp2 match {
304
+ case tp2 : RefinedType if tp1.refinedName == tp2.refinedName =>
305
+ return tp1.derivedRefinedType(
306
+ approximateUnion(OrType (tp1.parent, tp2.parent)),
307
+ tp1.refinedName,
308
+ homogenizedUnion(tp1.refinedInfo, tp2.refinedInfo).substRefinedThis(tp2, RefinedThis (tp1)))
309
+ // .ensuring { x => println(i"approx or $tp1 | $tp2 = $x\n constr = ${ctx.typerState.constraint}"); true } // DEBUG
310
+ case _ =>
311
+ }
312
+ case _ =>
313
+ }
314
+ tp1 match {
315
+ case tp1 : TypeProxy if ! isClassRef(tp1) =>
316
+ approximateUnion(next(tp1) | tp2)
317
+ case _ =>
318
+ tp2 match {
319
+ case tp2 : TypeProxy if ! isClassRef(tp2) =>
320
+ approximateUnion(tp1 | next(tp2))
321
+ case _ =>
322
+ val commonBaseClasses = tp.mapReduceOr(_.baseClasses)(intersect)
323
+ val doms = dominators(commonBaseClasses, Nil )
324
+ def baseTp (cls : ClassSymbol ): Type =
325
+ if (tp1.typeParams.nonEmpty) tp.baseTypeRef(cls)
326
+ else tp.baseTypeWithArgs(cls)
327
+ doms.map(baseTp).reduceLeft(AndType .apply)
328
+ }
329
+ }
330
+ }
331
+ if (ctx.featureEnabled(defn.LanguageModuleClass , nme.keepUnions)) tp
332
+ else tp match {
333
+ case tp : OrType =>
334
+ approximateOr(tp.tp1, tp.tp2)
294
335
case tp @ AndType (tp1, tp2) =>
295
336
tp derived_& (approximateUnion(tp1), approximateUnion(tp2))
296
337
case tp : RefinedType =>
0 commit comments