@@ -334,17 +334,6 @@ object Denotations {
334334 else asSingleDenotation
335335 }
336336
337- /** Handle merge conflict by throwing a `MergeError` exception */
338- private def mergeConflict (tp1 : Type , tp2 : Type , that : Denotation )(implicit ctx : Context ): Type =
339- throw new MergeError (this .symbol, that.symbol, tp1, tp2, NoPrefix )
340-
341- /** Merge parameter names of lambda types. If names in corresponding positions match, keep them,
342- * otherwise generate new synthetic names.
343- */
344- private def mergeParamNames (tp1 : LambdaType , tp2 : LambdaType ): List [tp1.ThisName ] =
345- (for ((name1, name2, idx) <- (tp1.paramNames, tp2.paramNames, tp1.paramNames.indices).zipped)
346- yield if (name1 == name2) name1 else tp1.companion.syntheticParamName(idx)).toList
347-
348337 /** Form a denotation by conjoining with denotation `that`.
349338 *
350339 * NoDenotations are dropped. MultiDenotations are handled by merging
@@ -374,72 +363,6 @@ object Denotations {
374363 * If SingleDenotations with different signatures are joined, return NoDenotation.
375364 */
376365 def & (that : Denotation , pre : Type , safeIntersection : Boolean = false )(implicit ctx : Context ): Denotation = {
377-
378- /** Normally, `tp1 & tp2`. Special cases for matching methods and classes, with
379- * the possibility of raising a merge error.
380- */
381- def infoMeet (tp1 : Type , tp2 : Type ): Type = {
382- if (tp1 eq tp2) tp1
383- else tp1 match {
384- case tp1 : TypeBounds =>
385- tp2 match {
386- case tp2 : TypeBounds => if (safeIntersection) tp1 safe_& tp2 else tp1 & tp2
387- case tp2 : ClassInfo if tp1 contains tp2 => tp2
388- case _ => mergeConflict(tp1, tp2, that)
389- }
390- case tp1 : ClassInfo =>
391- tp2 match {
392- case tp2 : ClassInfo if tp1.cls eq tp2.cls => tp1.derivedClassInfo(tp1.prefix & tp2.prefix)
393- case tp2 : TypeBounds if tp2 contains tp1 => tp1
394- case _ => mergeConflict(tp1, tp2, that)
395- }
396-
397- // Two remedial strategies:
398- //
399- // 1. Prefer method types over poly types. This is necessary to handle
400- // overloaded definitions like the following
401- //
402- // def ++ [B >: A](xs: C[B]): D[B]
403- // def ++ (xs: C[A]): D[A]
404- //
405- // (Code like this is found in the collection strawman)
406- //
407- // 2. In the case of two method types or two polytypes with matching
408- // parameters and implicit status, merge corresponding parameter
409- // and result types.
410- case tp1 : MethodType =>
411- tp2 match {
412- case tp2 : PolyType =>
413- tp1
414- case tp2 : MethodType if ctx.typeComparer.matchingMethodParams(tp1, tp2) &&
415- tp1.isImplicitMethod == tp2.isImplicitMethod =>
416- tp1.derivedLambdaType(
417- mergeParamNames(tp1, tp2),
418- tp1.paramInfos,
419- infoMeet(tp1.resultType, tp2.resultType.subst(tp2, tp1)))
420- case _ =>
421- mergeConflict(tp1, tp2, that)
422- }
423- case tp1 : PolyType =>
424- tp2 match {
425- case tp2 : MethodType =>
426- tp2
427- case tp2 : PolyType if ctx.typeComparer.matchingPolyParams(tp1, tp2) =>
428- tp1.derivedLambdaType(
429- mergeParamNames(tp1, tp2),
430- tp1.paramInfos.zipWithConserve(tp2.paramInfos) { (p1, p2) =>
431- infoMeet(p1, p2.subst(tp2, tp1)).bounds
432- },
433- infoMeet(tp1.resultType, tp2.resultType.subst(tp2, tp1)))
434- case _ =>
435- mergeConflict(tp1, tp2, that)
436- }
437-
438- case _ =>
439- tp1 & tp2
440- }
441- }
442-
443366 /** Try to merge denot1 and denot2 without adding a new signature. */
444367 def mergeDenot (denot1 : Denotation , denot2 : SingleDenotation ): Denotation = denot1 match {
445368 case denot1 @ MultiDenotation (denot11, denot12) =>
@@ -535,7 +458,7 @@ object Denotations {
535458 if (preferSym(sym2, sym1)) sym2
536459 else sym1
537460 val jointInfo =
538- try infoMeet(info1, info2)
461+ try infoMeet(info1, info2, sym1, sym2, safeIntersection )
539462 catch {
540463 case ex : MergeError =>
541464 // TODO: this picks one type over the other whereas it might be better
@@ -571,51 +494,6 @@ object Denotations {
571494 */
572495 def | (that : Denotation , pre : Type )(implicit ctx : Context ): Denotation = {
573496
574- /** Normally, `tp1 | tp2`. Special cases for matching methods and classes, with
575- * the possibility of raising a merge error.
576- */
577- def infoJoin (tp1 : Type , tp2 : Type ): Type = tp1 match {
578- case tp1 : TypeBounds =>
579- tp2 match {
580- case tp2 : TypeBounds => tp1 | tp2
581- case tp2 : ClassInfo if tp1 contains tp2 => tp1
582- case _ => mergeConflict(tp1, tp2, that)
583- }
584- case tp1 : ClassInfo =>
585- tp2 match {
586- case tp2 : ClassInfo if tp1.cls eq tp2.cls => tp1.derivedClassInfo(tp1.prefix | tp2.prefix)
587- case tp2 : TypeBounds if tp2 contains tp1 => tp2
588- case _ => mergeConflict(tp1, tp2, that)
589- }
590- case tp1 : MethodType =>
591- tp2 match {
592- case tp2 : MethodType
593- if ctx.typeComparer.matchingMethodParams(tp1, tp2) &&
594- tp1.isImplicitMethod == tp2.isImplicitMethod =>
595- tp1.derivedLambdaType(
596- mergeParamNames(tp1, tp2),
597- tp1.paramInfos,
598- tp1.resultType | tp2.resultType.subst(tp2, tp1))
599- case _ =>
600- mergeConflict(tp1, tp2, that)
601- }
602- case tp1 : PolyType =>
603- tp2 match {
604- case tp2 : PolyType
605- if ctx.typeComparer.matchingPolyParams(tp1, tp2) =>
606- tp1.derivedLambdaType(
607- mergeParamNames(tp1, tp2),
608- tp1.paramInfos.zipWithConserve(tp2.paramInfos) { (p1, p2) =>
609- (p1 | p2.subst(tp2, tp1)).bounds
610- },
611- tp1.resultType | tp2.resultType.subst(tp2, tp1))
612- case _ =>
613- mergeConflict(tp1, tp2, that)
614- }
615- case _ =>
616- tp1 | tp2
617- }
618-
619497 def unionDenot (denot1 : SingleDenotation , denot2 : SingleDenotation ): Denotation =
620498 if (denot1.matches(denot2)) {
621499 val sym1 = denot1.symbol
@@ -646,7 +524,7 @@ object Denotations {
646524 lubSym(sym1.allOverriddenSymbols, NoSymbol )
647525 }
648526 new JointRefDenotation (
649- jointSym, infoJoin(info1, info2), denot1.validFor & denot2.validFor)
527+ jointSym, infoJoin(info1, info2, sym1, sym2 ), denot1.validFor & denot2.validFor)
650528 }
651529 }
652530 else NoDenotation
@@ -678,6 +556,134 @@ object Denotations {
678556 final def containsSym (sym : Symbol ): Boolean = hasUniqueSym && (symbol eq sym)
679557 }
680558
559+ // ------ Info meets and joins ---------------------------------------------
560+
561+ /** Handle merge conflict by throwing a `MergeError` exception */
562+ private def mergeConflict (sym1 : Symbol , sym2 : Symbol , tp1 : Type , tp2 : Type )(implicit ctx : Context ): Type =
563+ throw new MergeError (sym1, sym2, tp1, tp2, NoPrefix )
564+
565+ /** Merge parameter names of lambda types. If names in corresponding positions match, keep them,
566+ * otherwise generate new synthetic names.
567+ */
568+ private def mergeParamNames (tp1 : LambdaType , tp2 : LambdaType ): List [tp1.ThisName ] =
569+ (for ((name1, name2, idx) <- (tp1.paramNames, tp2.paramNames, tp1.paramNames.indices).zipped)
570+ yield if (name1 == name2) name1 else tp1.companion.syntheticParamName(idx)).toList
571+
572+ /** Normally, `tp1 & tp2`. Special cases for matching methods and classes, with
573+ * the possibility of raising a merge error.
574+ */
575+ def infoMeet (tp1 : Type , tp2 : Type , sym1 : Symbol , sym2 : Symbol , safeIntersection : Boolean )(implicit ctx : Context ): Type = {
576+ if (tp1 eq tp2) tp1
577+ else tp1 match {
578+ case tp1 : TypeBounds =>
579+ tp2 match {
580+ case tp2 : TypeBounds => if (safeIntersection) tp1 safe_& tp2 else tp1 & tp2
581+ case tp2 : ClassInfo if tp1 contains tp2 => tp2
582+ case _ => mergeConflict(sym1, sym2, tp1, tp2)
583+ }
584+ case tp1 : ClassInfo =>
585+ tp2 match {
586+ case tp2 : ClassInfo if tp1.cls eq tp2.cls => tp1.derivedClassInfo(tp1.prefix & tp2.prefix)
587+ case tp2 : TypeBounds if tp2 contains tp1 => tp1
588+ case _ => mergeConflict(sym1, sym2, tp1, tp2)
589+ }
590+
591+ // Two remedial strategies:
592+ //
593+ // 1. Prefer method types over poly types. This is necessary to handle
594+ // overloaded definitions like the following
595+ //
596+ // def ++ [B >: A](xs: C[B]): D[B]
597+ // def ++ (xs: C[A]): D[A]
598+ //
599+ // (Code like this is found in the collection strawman)
600+ //
601+ // 2. In the case of two method types or two polytypes with matching
602+ // parameters and implicit status, merge corresponding parameter
603+ // and result types.
604+ case tp1 : MethodType =>
605+ tp2 match {
606+ case tp2 : PolyType =>
607+ tp1
608+ case tp2 : MethodType if ctx.typeComparer.matchingMethodParams(tp1, tp2) &&
609+ tp1.isImplicitMethod == tp2.isImplicitMethod =>
610+ tp1.derivedLambdaType(
611+ mergeParamNames(tp1, tp2),
612+ tp1.paramInfos,
613+ infoMeet(tp1.resultType, tp2.resultType.subst(tp2, tp1), sym1, sym2, safeIntersection))
614+ case _ =>
615+ mergeConflict(sym1, sym2, tp1, tp2)
616+ }
617+ case tp1 : PolyType =>
618+ tp2 match {
619+ case tp2 : MethodType =>
620+ tp2
621+ case tp2 : PolyType if ctx.typeComparer.matchingPolyParams(tp1, tp2) =>
622+ tp1.derivedLambdaType(
623+ mergeParamNames(tp1, tp2),
624+ tp1.paramInfos.zipWithConserve(tp2.paramInfos) { (p1, p2) =>
625+ infoMeet(p1, p2.subst(tp2, tp1), sym1, sym2, safeIntersection).bounds
626+ },
627+ infoMeet(tp1.resultType, tp2.resultType.subst(tp2, tp1), sym1, sym2, safeIntersection))
628+ case _ =>
629+ mergeConflict(sym1, sym2, tp1, tp2)
630+ }
631+
632+ case _ =>
633+ try tp1 & tp2
634+ catch {
635+ case ex : Throwable =>
636+ println(i " error for meet: $tp1 &&& $tp2, ${tp1.getClass}, ${tp2.getClass}" )
637+ throw ex
638+ }
639+ }
640+ }
641+
642+ /** Normally, `tp1 | tp2`. Special cases for matching methods and classes, with
643+ * the possibility of raising a merge error.
644+ */
645+ def infoJoin (tp1 : Type , tp2 : Type , sym1 : Symbol , sym2 : Symbol )(implicit ctx : Context ): Type = tp1 match {
646+ case tp1 : TypeBounds =>
647+ tp2 match {
648+ case tp2 : TypeBounds => tp1 | tp2
649+ case tp2 : ClassInfo if tp1 contains tp2 => tp1
650+ case _ => mergeConflict(sym1, sym2, tp1, tp2)
651+ }
652+ case tp1 : ClassInfo =>
653+ tp2 match {
654+ case tp2 : ClassInfo if tp1.cls eq tp2.cls => tp1.derivedClassInfo(tp1.prefix | tp2.prefix)
655+ case tp2 : TypeBounds if tp2 contains tp1 => tp2
656+ case _ => mergeConflict(sym1, sym2, tp1, tp2)
657+ }
658+ case tp1 : MethodType =>
659+ tp2 match {
660+ case tp2 : MethodType
661+ if ctx.typeComparer.matchingMethodParams(tp1, tp2) &&
662+ tp1.isImplicitMethod == tp2.isImplicitMethod =>
663+ tp1.derivedLambdaType(
664+ mergeParamNames(tp1, tp2),
665+ tp1.paramInfos,
666+ tp1.resultType | tp2.resultType.subst(tp2, tp1))
667+ case _ =>
668+ mergeConflict(sym1, sym2, tp1, tp2)
669+ }
670+ case tp1 : PolyType =>
671+ tp2 match {
672+ case tp2 : PolyType
673+ if ctx.typeComparer.matchingPolyParams(tp1, tp2) =>
674+ tp1.derivedLambdaType(
675+ mergeParamNames(tp1, tp2),
676+ tp1.paramInfos.zipWithConserve(tp2.paramInfos) { (p1, p2) =>
677+ (p1 | p2.subst(tp2, tp1)).bounds
678+ },
679+ tp1.resultType | tp2.resultType.subst(tp2, tp1))
680+ case _ =>
681+ mergeConflict(sym1, sym2, tp1, tp2)
682+ }
683+ case _ =>
684+ tp1 | tp2
685+ }
686+
681687 /** A non-overloaded denotation */
682688 abstract class SingleDenotation (symbol : Symbol , initInfo : Type ) extends Denotation (symbol, initInfo) {
683689 protected def newLikeThis (symbol : Symbol , info : Type ): SingleDenotation
0 commit comments