aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2016-10-13 18:39:42 +0200
committerMartin Odersky <odersky@gmail.com>2016-10-13 18:39:42 +0200
commit5d531ec78173b9524acd3b58485f89099dbe6991 (patch)
treeb249e848507a5b7b2705796e003bdb4cd99a23bc
parenta45a3e5f573fc5b768fcd0d6be507a0af8fd53cc (diff)
downloaddotty-5d531ec78173b9524acd3b58485f89099dbe6991.tar.gz
dotty-5d531ec78173b9524acd3b58485f89099dbe6991.tar.bz2
dotty-5d531ec78173b9524acd3b58485f89099dbe6991.zip
Refinement of interpolation direction
-rw-r--r--src/dotty/tools/dotc/core/ConstraintHandling.scala20
-rw-r--r--tests/pos/i1590.scala9
2 files changed, 28 insertions, 1 deletions
diff --git a/src/dotty/tools/dotc/core/ConstraintHandling.scala b/src/dotty/tools/dotc/core/ConstraintHandling.scala
index 95fa40704..0e155b9e1 100644
--- a/src/dotty/tools/dotc/core/ConstraintHandling.scala
+++ b/src/dotty/tools/dotc/core/ConstraintHandling.scala
@@ -177,7 +177,25 @@ trait ConstraintHandling {
case tp: RefinedType if param occursIn tp.refinedInfo => tp.parent
case tp: WildcardType =>
val bounds = tp.optBounds.orElse(TypeBounds.empty).bounds
- if (fromBelow == (variance >= 0)) bounds.lo else bounds.hi
+ // Try to instantiate the wildcard to a type that is known to conform to it.
+ // This means:
+ // If fromBelow is true, we minimize the type overall
+ // Hence, if variance < 0, pick the maximal safe type: bounds.lo
+ // (i.e. the whole bounds range is over the type)
+ // if variance > 0, pick the minimal safe type: bounds.hi
+ // (i.e. the whole bounds range is under the type)
+ // if variance == 0, pick bounds.lo anyway (this is arbitrary but in line with
+ // the principle that we pick the smaller type when in doubt).
+ // If fromBelow is false, we maximize the type overall and reverse the bounds
+ // if variance != 0. For variance == 0, we still minimize.
+ // In summary we pick the bound given by this table:
+ //
+ // variance | -1 0 1
+ // ------------------------
+ // from below | lo lo hi
+ // from above | hi lo lo
+ //
+ if (variance == 0 || fromBelow == (variance < 0)) bounds.lo else bounds.hi
case _ => tp
}
}
diff --git a/tests/pos/i1590.scala b/tests/pos/i1590.scala
index a8f36de45..ab922c218 100644
--- a/tests/pos/i1590.scala
+++ b/tests/pos/i1590.scala
@@ -1 +1,10 @@
case class W[T](seq: Option[Option[T]] = Option.empty)
+object W {
+ def apply[T] = new W[T]()
+}
+
+case class V[T](vv: W[W[T]] = W.apply)
+object Test {
+ W[Int]()
+ // V[Int]() fails in scalac and dotty: both instantiate the vv-default to W[Nothing]
+}