@@ -266,31 +266,72 @@ trait TypeOps { this: Context => // TODO: Make standalone object.
266266 val accu1 = if (accu exists (_ derivesFrom c)) accu else c :: accu
267267 if (cs == c.baseClasses) accu1 else dominators(rest, accu1)
268268 }
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)
288294 case _ =>
289- val commonBaseClasses = tp.mapReduceOr(_.baseClasses)(intersect)
290- val doms = dominators(commonBaseClasses, Nil )
291- doms.map(tp.baseTypeWithArgs).reduceLeft(AndType .apply)
292295 }
296+ case _ =>
293297 }
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)
294335 case tp @ AndType (tp1, tp2) =>
295336 tp derived_& (approximateUnion(tp1), approximateUnion(tp2))
296337 case tp : RefinedType =>
0 commit comments