aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorodersky <odersky@gmail.com>2016-10-16 13:26:34 +0200
committerGitHub <noreply@github.com>2016-10-16 13:26:34 +0200
commit0fdd4e37ffca9b1da770ba348aece793c200f1ff (patch)
treecab76702a7a8e31618d39cacac017ae144344dc0 /src
parent009398bf72d4ec3e10f4b6f56431927065c3b846 (diff)
parent5d531ec78173b9524acd3b58485f89099dbe6991 (diff)
downloaddotty-0fdd4e37ffca9b1da770ba348aece793c200f1ff.tar.gz
dotty-0fdd4e37ffca9b1da770ba348aece793c200f1ff.tar.bz2
dotty-0fdd4e37ffca9b1da770ba348aece793c200f1ff.zip
Merge pull request #1592 from dotty-staging/fix-#1590
Fix #1590: Eliminate wildcards when approximating a type
Diffstat (limited to 'src')
-rw-r--r--src/dotty/tools/dotc/core/ConstraintHandling.scala24
1 files changed, 23 insertions, 1 deletions
diff --git a/src/dotty/tools/dotc/core/ConstraintHandling.scala b/src/dotty/tools/dotc/core/ConstraintHandling.scala
index 3835d553c..0e155b9e1 100644
--- a/src/dotty/tools/dotc/core/ConstraintHandling.scala
+++ b/src/dotty/tools/dotc/core/ConstraintHandling.scala
@@ -162,7 +162,8 @@ trait ConstraintHandling {
/** Solve constraint set for given type parameter `param`.
* If `fromBelow` is true the parameter is approximated by its lower bound,
* otherwise it is approximated by its upper bound. However, any occurrences
- * of the parameter in a refinement somewhere in the bound are removed.
+ * of the parameter in a refinement somewhere in the bound are removed. Also
+ * wildcard types in bounds are approximated by their upper or lower bounds.
* (Such occurrences can arise for F-bounded types).
* The constraint is left unchanged.
* @return the instantiating type
@@ -174,6 +175,27 @@ trait ConstraintHandling {
def apply(tp: Type) = mapOver {
tp match {
case tp: RefinedType if param occursIn tp.refinedInfo => tp.parent
+ case tp: WildcardType =>
+ val bounds = tp.optBounds.orElse(TypeBounds.empty).bounds
+ // 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
}
}