aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2016-10-10 18:59:44 +0200
committerGuillaume Martres <smarter@ubuntu.com>2016-10-11 19:21:02 +0200
commit8067b952875426d640968be865773f6ef3783f3c (patch)
treee00a6b210e27ed1df71f6e84811df976c7f54cf1 /src
parentda344548d7425368ccd5bf7a98e522d00cdc95aa (diff)
downloaddotty-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.scala7
-rw-r--r--src/dotty/tools/dotc/typer/ProtoTypes.scala7
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)