aboutsummaryrefslogtreecommitdiff
path: root/compiler
diff options
context:
space:
mode:
authorodersky <odersky@gmail.com>2017-01-11 10:15:14 +0700
committerGitHub <noreply@github.com>2017-01-11 10:15:14 +0700
commit486b0293dd07a3d969d75aaa1aeb438ce14ae726 (patch)
tree75f55e4a9b8b372eb24c3cda3f7e808ebf8bded4 /compiler
parentd62a2c911ce481d8d7e2ebd84173b77fc628cc00 (diff)
parent918a3fba3ceeebf0bc3e0087f9ead63f4ae30381 (diff)
downloaddotty-486b0293dd07a3d969d75aaa1aeb438ce14ae726.tar.gz
dotty-486b0293dd07a3d969d75aaa1aeb438ce14ae726.tar.bz2
dotty-486b0293dd07a3d969d75aaa1aeb438ce14ae726.zip
Merge pull request #1893 from dotty-staging/fix-#1891
Fix #1891: Don't add redundant constraint
Diffstat (limited to 'compiler')
-rw-r--r--compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala1
-rw-r--r--compiler/src/dotty/tools/dotc/core/TypeComparer.scala15
2 files changed, 14 insertions, 2 deletions
diff --git a/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala b/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala
index 0e155b9e1..42df53fed 100644
--- a/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala
+++ b/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala
@@ -57,6 +57,7 @@ trait ConstraintHandling {
b match {
case b: AndOrType => occursIn(b.tp1) || occursIn(b.tp2)
case b: TypeVar => occursIn(b.origin)
+ case b: TermRef => occursIn(b.underlying)
case _ => false
}
}
diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala
index 8930983f3..6063cbf38 100644
--- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala
+++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala
@@ -375,11 +375,22 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
thirdTryNamed(tp1, tp2)
case tp2: PolyParam =>
def comparePolyParam =
- (ctx.mode is Mode.TypevarsMissContext) ||
- isSubTypeWhenFrozen(tp1, bounds(tp2).lo) || {
+ (ctx.mode is Mode.TypevarsMissContext) || {
+ val alwaysTrue =
+ // The following condition is carefully formulated to catch all cases
+ // where the subtype relation is true without needing to add a constraint
+ // It's tricky because we might need to either appriximate tp2 by its
+ // lower bound or else widen tp1 and check that the result is a subtype of tp2.
+ // So if the constraint is not yet frozen, we do the same comparison again
+ // with a frozen constraint, which means that we get a chance to do the
+ // widening in `fourthTry` before adding to the constraint.
+ if (frozenConstraint || alwaysFluid) isSubType(tp1, bounds(tp2).lo)
+ else isSubTypeWhenFrozen(tp1, tp2)
+ alwaysTrue || {
if (canConstrain(tp2)) addConstraint(tp2, tp1.widenExpr, fromBelow = true)
else fourthTry(tp1, tp2)
}
+ }
comparePolyParam
case tp2: RefinedType =>
def compareRefinedSlow: Boolean = {