diff options
author | Martin Odersky <odersky@gmail.com> | 2016-10-10 18:59:44 +0200 |
---|---|---|
committer | Guillaume Martres <smarter@ubuntu.com> | 2016-10-11 19:21:02 +0200 |
commit | 8067b952875426d640968be865773f6ef3783f3c (patch) | |
tree | e00a6b210e27ed1df71f6e84811df976c7f54cf1 /src | |
parent | da344548d7425368ccd5bf7a98e522d00cdc95aa (diff) | |
download | dotty-8067b952875426d640968be865773f6ef3783f3c.tar.gz dotty-8067b952875426d640968be865773f6ef3783f3c.tar.bz2 dotty-8067b952875426d640968be865773f6ef3783f3c.zip |
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.
Diffstat (limited to 'src')
-rw-r--r-- | src/dotty/tools/dotc/core/TypeComparer.scala | 7 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/ProtoTypes.scala | 7 |
2 files changed, 11 insertions, 3 deletions
diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala index 0a51b896a..52b248abb 100644 --- a/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/src/dotty/tools/dotc/core/TypeComparer.scala @@ -8,7 +8,7 @@ import StdNames.{nme, tpnme} import collection.mutable import util.{Stats, DotClass, SimpleMap} import config.Config -import config.Printers.{typr, constr, subtyping} +import config.Printers.{typr, constr, subtyping, noPrinter} import TypeErasure.{erasedLub, erasedGlb} import TypeApplications._ import scala.util.control.NonFatal @@ -837,8 +837,11 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { op1 && { val leftConstraint = constraint constraint = preConstraint - if (!(op2 && subsumes(leftConstraint, constraint, preConstraint))) + if (!(op2 && subsumes(leftConstraint, constraint, preConstraint))) { + if (constr != noPrinter && !subsumes(constraint, leftConstraint, preConstraint)) + constr.println(i"CUT - prefer $leftConstraint over $constraint") constraint = leftConstraint + } true } || op2 } diff --git a/src/dotty/tools/dotc/typer/ProtoTypes.scala b/src/dotty/tools/dotc/typer/ProtoTypes.scala index 0e6697fb7..dd5705fbf 100644 --- a/src/dotty/tools/dotc/typer/ProtoTypes.scala +++ b/src/dotty/tools/dotc/typer/ProtoTypes.scala @@ -43,6 +43,11 @@ object ProtoTypes { isCompatible(normalize(tp, pt)(nestedCtx), pt)(nestedCtx) } + private def disregardProto(pt: Type)(implicit ctx: Context): Boolean = pt.dealias match { + case _: OrType => true + case pt => pt.isRef(defn.UnitClass) + } + /** Check that the result type of the current method * fits the given expected result type. */ @@ -54,7 +59,7 @@ object ProtoTypes { case _ => true } - case _: ValueTypeOrProto if !(pt isRef defn.UnitClass) => + case _: ValueTypeOrProto if !disregardProto(pt) => mt match { case mt: MethodType => mt.isDependent || isCompatible(normalize(mt, pt), pt) |