Skip to content

Commit 1c36fc2

Browse files
committed
Fix cutting problem
Test case: orInf.scala. This showed a problem where an `either` operation had to arbitrarily pick one constraint over another, leading to a type error down the line. What happened was that a `constrainResult` generated the constraint Set[A] <: Set[String] | Set[Int] But this constraint cannot be simplified without a cut and a resulting loss of information. We avoid the problem by not constraining the result if the prototype is a disjunction.
1 parent 60480d4 commit 1c36fc2

File tree

2 files changed

+11
-3
lines changed

2 files changed

+11
-3
lines changed

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import StdNames.{nme, tpnme}
88
import collection.mutable
99
import util.{Stats, DotClass, SimpleMap}
1010
import config.Config
11-
import config.Printers.{typr, constr, subtyping}
11+
import config.Printers.{typr, constr, subtyping, noPrinter}
1212
import TypeErasure.{erasedLub, erasedGlb}
1313
import TypeApplications._
1414
import scala.util.control.NonFatal
@@ -837,8 +837,11 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
837837
op1 && {
838838
val leftConstraint = constraint
839839
constraint = preConstraint
840-
if (!(op2 && subsumes(leftConstraint, constraint, preConstraint)))
840+
if (!(op2 && subsumes(leftConstraint, constraint, preConstraint))) {
841+
if (constr != noPrinter && !subsumes(constraint, leftConstraint, preConstraint))
842+
constr.println(i"CUT - prefer $leftConstraint over $constraint")
841843
constraint = leftConstraint
844+
}
842845
true
843846
} || op2
844847
}

src/dotty/tools/dotc/typer/ProtoTypes.scala

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ object ProtoTypes {
4343
isCompatible(normalize(tp, pt)(nestedCtx), pt)(nestedCtx)
4444
}
4545

46+
private def disregardProto(pt: Type)(implicit ctx: Context): Boolean = pt.dealias match {
47+
case _: OrType => true
48+
case pt => pt.isRef(defn.UnitClass)
49+
}
50+
4651
/** Check that the result type of the current method
4752
* fits the given expected result type.
4853
*/
@@ -54,7 +59,7 @@ object ProtoTypes {
5459
case _ =>
5560
true
5661
}
57-
case _: ValueTypeOrProto if !(pt isRef defn.UnitClass) =>
62+
case _: ValueTypeOrProto if !disregardProto(pt) =>
5863
mt match {
5964
case mt: MethodType =>
6065
mt.isDependent || isCompatible(normalize(mt, pt), pt)

0 commit comments

Comments
 (0)