Skip to content

Commit 162f3fa

Browse files
committed
Drop MergeError
1 parent 0cf9ee1 commit 162f3fa

File tree

5 files changed

+51
-227
lines changed

5 files changed

+51
-227
lines changed

compiler/src/dotty/tools/dotc/core/Denotations.scala

Lines changed: 36 additions & 162 deletions
Original file line numberDiff line numberDiff line change
@@ -387,8 +387,6 @@ object Denotations {
387387
* with one of the operand symbols (unspecified which one), and an info which
388388
* is the intersection (using `&` or `safe_&` if `safeIntersection` is true)
389389
* of the infos of the operand denotations.
390-
*
391-
* If SingleDenotations with different signatures are joined, return NoDenotation.
392390
*/
393391
def & (that: Denotation, pre: Type, safeIntersection: Boolean = false)(implicit ctx: Context): Denotation = {
394392
/** Try to merge denot1 and denot2 without adding a new signature. */
@@ -418,10 +416,10 @@ object Denotations {
418416

419417
/** Does `sym1` come before `sym2` in the linearization of `pre`? */
420418
def precedes(sym1: Symbol, sym2: Symbol) = {
421-
def precedesIn(bcs: List[ClassSymbol]): Boolean = bcs match {
419+
def precedesIn(bcs: List[ClassSymbol]): Boolean = bcs match
422420
case bc :: bcs1 => (sym1 eq bc) || !(sym2 eq bc) && precedesIn(bcs1)
423421
case Nil => false
424-
}
422+
425423
(sym1 ne sym2) &&
426424
(sym1.derivesFrom(sym2) ||
427425
!sym2.derivesFrom(sym1) && precedesIn(pre.baseClasses))
@@ -503,12 +501,13 @@ object Denotations {
503501
else if (sym1Accessible && sym2.exists && !sym2Accessible) denot1
504502
else if (sym2Accessible && sym1.exists && !sym1Accessible) denot2
505503
else if isDoubleDef(sym1, sym2) then handleConflict
506-
else try
504+
else
507505
val sym = if preferSym(sym2, sym1) then sym2 else sym1
508-
val jointInfo = infoMeet(info1, info2, sym1, sym2, safeIntersection)
509-
JointRefDenotation(sym, jointInfo, denot1.validFor & denot2.validFor, pre)
510-
catch case ex: MergeError =>
511-
handleConflict
506+
val jointInfo = infoMeet(info1, info2, safeIntersection)
507+
if jointInfo.exists then
508+
JointRefDenotation(sym, jointInfo, denot1.validFor & denot2.validFor, pre)
509+
else
510+
handleConflict
512511
end mergeSingleDenot
513512

514513
if (this eq that) this
@@ -523,63 +522,6 @@ object Denotations {
523522
}
524523
}
525524

526-
/** Form a choice between this denotation and that one.
527-
* @param pre The prefix type of the members of the denotation, used
528-
* to determine an accessible symbol if it exists.
529-
*/
530-
def | (that: Denotation, pre: Type)(implicit ctx: Context): Denotation = {
531-
532-
def unionDenot(denot1: SingleDenotation, denot2: SingleDenotation): Denotation =
533-
if (denot1.matches(denot2)) {
534-
val sym1 = denot1.symbol
535-
val sym2 = denot2.symbol
536-
val info1 = denot1.info
537-
val info2 = denot2.info
538-
val sameSym = sym1 eq sym2
539-
if (sameSym && (info1.widenExpr frozen_<:< info2.widenExpr)) denot2
540-
else if (sameSym && (info2.widenExpr frozen_<:< info1.widenExpr)) denot1
541-
else {
542-
val jointSym =
543-
if (sameSym) sym1
544-
else {
545-
val owner2 = if (sym2 ne NoSymbol) sym2.owner else NoSymbol
546-
/** Determine a symbol which is overridden by both sym1 and sym2.
547-
* Preference is given to accessible symbols.
548-
*/
549-
def lubSym(overrides: Iterator[Symbol], previous: Symbol): Symbol =
550-
if (!overrides.hasNext) previous
551-
else {
552-
val candidate = overrides.next()
553-
if (owner2 derivesFrom candidate.owner)
554-
if (candidate isAccessibleFrom pre) candidate
555-
else lubSym(overrides, previous orElse candidate)
556-
else
557-
lubSym(overrides, previous)
558-
}
559-
lubSym(sym1.allOverriddenSymbols, NoSymbol)
560-
}
561-
new JointRefDenotation(
562-
jointSym, infoJoin(info1, info2, sym1, sym2), denot1.validFor & denot2.validFor, pre)
563-
}
564-
}
565-
else NoDenotation
566-
567-
if (this eq that) this
568-
else if (!this.exists) this
569-
else if (!that.exists) that
570-
else this match {
571-
case denot1 @ MultiDenotation(denot11, denot12) =>
572-
denot1.derivedUnionDenotation(denot11 | (that, pre), denot12 | (that, pre))
573-
case denot1: SingleDenotation =>
574-
that match {
575-
case denot2 @ MultiDenotation(denot21, denot22) =>
576-
denot2.derivedUnionDenotation(this | (denot21, pre), this | (denot22, pre))
577-
case denot2: SingleDenotation =>
578-
unionDenot(denot1, denot2)
579-
}
580-
}
581-
}
582-
583525
final def asSingleDenotation: SingleDenotation = asInstanceOf[SingleDenotation]
584526
final def asSymDenotation: SymDenotation = asInstanceOf[SymDenotation]
585527

@@ -593,36 +535,32 @@ object Denotations {
593535

594536
// ------ Info meets and joins ---------------------------------------------
595537

596-
/** Handle merge conflict by throwing a `MergeError` exception */
597-
private def mergeConflict(sym1: Symbol, sym2: Symbol, tp1: Type, tp2: Type)(implicit ctx: Context): Type =
598-
throw new MergeError(sym1, sym2, tp1, tp2, NoPrefix)
599-
600538
/** Merge parameter names of lambda types. If names in corresponding positions match, keep them,
601539
* otherwise generate new synthetic names.
602540
*/
603541
private def mergeParamNames(tp1: LambdaType, tp2: LambdaType): List[tp1.ThisName] =
604542
(for ((name1, name2, idx) <- tp1.paramNames.lazyZip(tp2.paramNames).lazyZip(tp1.paramNames.indices))
605543
yield if (name1 == name2) name1 else tp1.companion.syntheticParamName(idx)).toList
606544

607-
/** Normally, `tp1 & tp2`.
545+
/** Normally, `tp1 & tp2`
608546
* Special cases for matching methods and classes, with
609-
* the possibility of raising a merge error.
547+
* the possibility of returning NoType.
610548
* Special handling of ExprTypes, where mixed intersections widen the ExprType away.
611549
*/
612-
def infoMeet(tp1: Type, tp2: Type, sym1: Symbol, sym2: Symbol, safeIntersection: Boolean)(implicit ctx: Context): Type =
550+
def infoMeet(tp1: Type, tp2: Type, safeIntersection: Boolean)(implicit ctx: Context): Type =
613551
if (tp1 eq tp2) tp1
614552
else tp1 match {
615553
case tp1: TypeBounds =>
616554
tp2 match {
617555
case tp2: TypeBounds => if (safeIntersection) tp1 safe_& tp2 else tp1 & tp2
618556
case tp2: ClassInfo => tp2
619-
case _ => mergeConflict(sym1, sym2, tp1, tp2)
557+
case _ => NoType
620558
}
621559
case tp1: ClassInfo =>
622560
tp2 match {
623561
case tp2: ClassInfo if tp1.cls eq tp2.cls => tp1.derivedClassInfo(tp1.prefix & tp2.prefix)
624562
case tp2: TypeBounds => tp1
625-
case _ => mergeConflict(sym1, sym2, tp1, tp2)
563+
case _ => NoType
626564
}
627565

628566
// Two remedial strategies:
@@ -640,40 +578,39 @@ object Denotations {
640578
// and result types.
641579
case tp1: MethodType =>
642580
tp2 match {
643-
case tp2: PolyType =>
644-
tp1
645581
case tp2: MethodType
646582
if ctx.typeComparer.matchingMethodParams(tp1, tp2) && (tp1.companion eq tp2.companion) =>
647-
tp1.derivedLambdaType(
648-
mergeParamNames(tp1, tp2),
649-
tp1.paramInfos,
650-
infoMeet(tp1.resultType, tp2.resultType.subst(tp2, tp1), sym1, sym2, safeIntersection))
583+
val resType = infoMeet(tp1.resType, tp2.resType.subst(tp2, tp1), safeIntersection)
584+
if resType.exists then
585+
tp1.derivedLambdaType(mergeParamNames(tp1, tp2), tp1.paramInfos, resType)
586+
else
587+
NoType
651588
case _ =>
652-
mergeConflict(sym1, sym2, tp1, tp2)
589+
NoType
653590
}
654591
case tp1: PolyType =>
655592
tp2 match {
656-
case tp2: MethodType =>
657-
tp2
658593
case tp2: PolyType if ctx.typeComparer.matchingPolyParams(tp1, tp2) =>
659-
tp1.derivedLambdaType(
660-
mergeParamNames(tp1, tp2),
661-
tp1.paramInfos.zipWithConserve(tp2.paramInfos) { (p1, p2) =>
662-
infoMeet(p1, p2.subst(tp2, tp1), sym1, sym2, safeIntersection).bounds
663-
},
664-
infoMeet(tp1.resultType, tp2.resultType.subst(tp2, tp1), sym1, sym2, safeIntersection))
594+
val resType = infoMeet(tp1.resType, tp2.resType.subst(tp2, tp1), safeIntersection)
595+
if resType.exists then
596+
tp1.derivedLambdaType(
597+
mergeParamNames(tp1, tp2),
598+
tp1.paramInfos.zipWithConserve(tp2.paramInfos)( _ & _ ),
599+
resType)
600+
else
601+
NoType
665602
case _ =>
666-
mergeConflict(sym1, sym2, tp1, tp2)
603+
NoType
667604
}
668605
case ExprType(rtp1) =>
669606
tp2 match {
670607
case ExprType(rtp2) => ExprType(rtp1 & rtp2)
671-
case _ => infoMeet(rtp1, tp2, sym1, sym2, safeIntersection)
608+
case _ => infoMeet(rtp1, tp2, safeIntersection)
672609
}
673610
case _ =>
674611
tp2 match
675612
case _: MethodType | _: PolyType =>
676-
mergeConflict(sym1, sym2, tp1, tp2)
613+
NoType
677614
case _ =>
678615
try tp1 & tp2.widenExpr
679616
catch
@@ -682,57 +619,6 @@ object Denotations {
682619
throw ex
683620
}
684621

685-
/** Normally, `tp1 | tp2`.
686-
* Special cases for matching methods and classes, with
687-
* the possibility of raising a merge error.
688-
* Special handling of ExprTypes, where mixed unions widen the ExprType away.
689-
*/
690-
def infoJoin(tp1: Type, tp2: Type, sym1: Symbol, sym2: Symbol)(implicit ctx: Context): Type = tp1 match {
691-
case tp1: TypeBounds =>
692-
tp2 match {
693-
case tp2: TypeBounds => tp1 | tp2
694-
case tp2: ClassInfo if tp1 contains tp2 => tp1
695-
case _ => mergeConflict(sym1, sym2, tp1, tp2)
696-
}
697-
case tp1: ClassInfo =>
698-
tp2 match {
699-
case tp2: ClassInfo if tp1.cls eq tp2.cls => tp1.derivedClassInfo(tp1.prefix | tp2.prefix)
700-
case tp2: TypeBounds if tp2 contains tp1 => tp2
701-
case _ => mergeConflict(sym1, sym2, tp1, tp2)
702-
}
703-
case tp1: MethodType =>
704-
tp2 match {
705-
case tp2: MethodType
706-
if ctx.typeComparer.matchingMethodParams(tp1, tp2) && (tp1.companion eq tp2.companion) =>
707-
tp1.derivedLambdaType(
708-
mergeParamNames(tp1, tp2),
709-
tp1.paramInfos,
710-
infoJoin(tp1.resultType, tp2.resultType.subst(tp2, tp1), sym1, sym2))
711-
case _ =>
712-
mergeConflict(sym1, sym2, tp1, tp2)
713-
}
714-
case tp1: PolyType =>
715-
tp2 match {
716-
case tp2: PolyType
717-
if ctx.typeComparer.matchingPolyParams(tp1, tp2) =>
718-
tp1.derivedLambdaType(
719-
mergeParamNames(tp1, tp2),
720-
tp1.paramInfos.zipWithConserve(tp2.paramInfos) { (p1, p2) =>
721-
infoJoin(p1, p2.subst(tp2, tp1), sym1, sym2).bounds
722-
},
723-
infoJoin(tp1.resultType, tp2.resultType.subst(tp2, tp1), sym1, sym2))
724-
case _ =>
725-
mergeConflict(sym1, sym2, tp1, tp2)
726-
}
727-
case ExprType(rtp1) =>
728-
tp2 match {
729-
case ExprType(rtp2) => ExprType(rtp1 | rtp2)
730-
case _ => rtp1 | tp2
731-
}
732-
case _ =>
733-
tp1 | tp2.widenExpr
734-
}
735-
736622
/** A non-overloaded denotation */
737623
abstract class SingleDenotation(symbol: Symbol, initInfo: Type) extends Denotation(symbol, initInfo) {
738624
protected def newLikeThis(symbol: Symbol, info: Type, pre: Type): SingleDenotation
@@ -1248,20 +1134,6 @@ object Denotations {
12481134
(sym1 `ne` sym2) && (sym1.effectiveOwner `eq` sym2.effectiveOwner) &&
12491135
!sym1.is(Bridge) && !sym2.is(Bridge))
12501136

1251-
def doubleDefError(denot1: Denotation, denot2: Denotation, pre: Type = NoPrefix)(implicit ctx: Context): Nothing = {
1252-
val sym1 = denot1.symbol
1253-
val sym2 = denot2.symbol
1254-
if (denot1.isTerm)
1255-
throw new MergeError(sym1, sym2, sym1.info, sym2.info, pre) {
1256-
override def addendum(implicit ctx: Context) =
1257-
i"""
1258-
|they are both defined in ${this.sym1.effectiveOwner} but have matching signatures
1259-
| ${denot1.info} and
1260-
| ${denot2.info}${super.addendum}"""
1261-
}
1262-
else throw new MergeError(sym1, sym2, denot1.info, denot2.info, pre)
1263-
}
1264-
12651137
// --- Overloaded denotations and predenotations -------------------------------------------------
12661138

12671139
trait MultiPreDenotation extends PreDenotation {
@@ -1318,10 +1190,12 @@ object Denotations {
13181190
def suchThat(p: Symbol => Boolean)(implicit ctx: Context): SingleDenotation = {
13191191
val sd1 = denot1.suchThat(p)
13201192
val sd2 = denot2.suchThat(p)
1321-
if (sd1.exists)
1322-
if (sd2.exists)
1323-
if (isDoubleDef(denot1.symbol, denot2.symbol)) doubleDefError(denot1, denot2)
1324-
else throw new TypeError(i"failure to disambiguate overloaded reference at $this")
1193+
if sd1.exists then
1194+
if sd2.exists then
1195+
throw TypeError(
1196+
em"""Failure to disambiguate oberloaded reference with
1197+
| ${denot1.symbol.showLocated}: ${denot1.info} and
1198+
| ${denot2.symbol.showLocated}: ${denot2.info}""")
13251199
else sd1
13261200
else sd2
13271201
}

compiler/src/dotty/tools/dotc/core/TypeComparer.scala

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2049,16 +2049,6 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] w
20492049
* instantiated TypeVars are dereferenced and annotations are stripped.
20502050
* Finally, refined types with the same refined name are
20512051
* opportunistically merged.
2052-
*
2053-
* Sometimes, the conjunction of two types cannot be formed because
2054-
* the types are in conflict of each other. In particular:
2055-
*
2056-
* 1. Two different class types are conflicting.
2057-
* 2. A class type conflicts with a type bounds that does not include the class reference.
2058-
* 3. Two method or poly types with different (type) parameters but the same
2059-
* signature are conflicting
2060-
*
2061-
* In these cases, a MergeError is thrown.
20622052
*/
20632053
final def andType(tp1: Type, tp2: Type, isErased: Boolean = ctx.erasedTypes): Type =
20642054
andTypeGen(tp1, tp2, AndType(_, _), isErased = isErased)
@@ -2072,10 +2062,6 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] w
20722062
* ExprType, LambdaType). Also, when forming an `|`,
20732063
* instantiated TypeVars are dereferenced and annotations are stripped.
20742064
*
2075-
* Sometimes, the disjunction of two types cannot be formed because
2076-
* the types are in conflict of each other. (@see `andType` for an enumeration
2077-
* of these cases). In cases of conflict a `MergeError` is raised.
2078-
*
20792065
* @param isErased Apply erasure semantics. If erased is true, instead of creating
20802066
* an OrType, the lub will be computed using TypeCreator#erasedLub.
20812067
*/
@@ -2141,13 +2127,11 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] w
21412127
// gives =:= types), but it keeps the type smaller.
21422128
tp2 match {
21432129
case tp2: RefinedType if tp1.refinedName == tp2.refinedName =>
2144-
try {
2145-
val jointInfo = Denotations.infoMeet(tp1.refinedInfo, tp2.refinedInfo, NoSymbol, NoSymbol, safeIntersection = false)
2130+
val jointInfo = Denotations.infoMeet(tp1.refinedInfo, tp2.refinedInfo, safeIntersection = false)
2131+
if jointInfo.exists then
21462132
tp1.derivedRefinedType(tp1.parent & tp2.parent, tp1.refinedName, jointInfo)
2147-
}
2148-
catch {
2149-
case ex: MergeError => NoType
2150-
}
2133+
else
2134+
NoType
21512135
case _ =>
21522136
NoType
21532137
}

compiler/src/dotty/tools/dotc/core/TypeErrors.scala

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -163,32 +163,3 @@ object CyclicReference {
163163
}
164164
}
165165

166-
class MergeError(val sym1: Symbol, val sym2: Symbol, val tp1: Type, val tp2: Type, prefix: Type) extends TypeError {
167-
168-
private def showSymbol(sym: Symbol)(implicit ctx: Context): String =
169-
if (sym.exists) sym.showLocated else "[unknown]"
170-
171-
private def showType(tp: Type)(implicit ctx: Context) = tp match {
172-
case ClassInfo(_, cls, _, _, _) => cls.showLocated
173-
case _ => tp.show
174-
}
175-
176-
protected def addendum(implicit ctx: Context): String =
177-
if (prefix `eq` NoPrefix) ""
178-
else {
179-
val owner = prefix match {
180-
case prefix: ThisType => prefix.cls.show
181-
case prefix: TermRef => prefix.symbol.show
182-
case _ => i"type $prefix"
183-
}
184-
s"\nas members of $owner"
185-
}
186-
187-
override def produceMessage(implicit ctx: Context): Message = {
188-
if (ctx.debug) printStackTrace()
189-
i"""cannot merge
190-
| ${showSymbol(sym1)} of type ${showType(tp1)} and
191-
| ${showSymbol(sym2)} of type ${showType(tp2)}$addendum
192-
"""
193-
}
194-
}

0 commit comments

Comments
 (0)