Skip to content

Commit edc1b5d

Browse files
committed
Instantiate type variables of implicits to or-dominators
Instantiate type variables of implicits to or-dominators of their lower bound. This is necessary to compile code like this: def useOrd[T: math.Ordering](xs: T*) = () useOrd(Some(1), None)
1 parent d541452 commit edc1b5d

File tree

2 files changed

+25
-7
lines changed

2 files changed

+25
-7
lines changed

compiler/src/dotty/tools/dotc/typer/Inferencing.scala

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,12 @@ object Inferencing {
4545
else throw new Error(i"internal error: type of $what $tp is not fully defined, pos = $pos") // !!! DEBUG
4646

4747

48-
/** Instantiate selected type variables `tvars` in type `tp` */
48+
/** Instantiate selected type variables `tvars` in type `tp`. Instantiation
49+
* proceeds with `implicitMode = true`, that is, type variables are approximated
50+
* from below using or-dominators.
51+
*/
4952
def instantiateSelected(tp: Type, tvars: List[Type])(implicit ctx: Context): Unit =
50-
new IsFullyDefinedAccumulator(new ForceDegree.Value(tvars.contains, minimizeAll = true)).process(tp)
53+
new IsFullyDefinedAccumulator(new ForceDegree.Value(tvars.contains, implicitMode = true)).process(tp)
5154

5255
/** The accumulator which forces type variables using the policy encoded in `force`
5356
* and returns whether the type is fully defined. The direction in which
@@ -81,14 +84,25 @@ object Inferencing {
8184
case tvar: TypeVar
8285
if !tvar.isInstantiated && ctx.typerState.constraint.contains(tvar) =>
8386
force.appliesTo(tvar) && {
87+
if (force.implicitMode) {
88+
// instantiate to or-dominator of lower bound; without this tweak we'd
89+
// fail to find an implicit in situations like this:
90+
//
91+
// def f[T: Ordering](xs: T*) = ...
92+
// f(Some(1), None)
93+
//
94+
// The problem is that there is no implicit Ordering instance for the otherwise inferred
95+
// lower bound of T, which is `Some[Int] | None`.
96+
ctx.orDominator(ctx.typeComparer.bounds(tvar.origin).lo) <:< tvar.origin
97+
}
8498
val direction = instDirection(tvar.origin)
8599
if (direction != 0) {
86100
//if (direction > 0) println(s"inst $tvar dir = up")
87101
instantiate(tvar, direction < 0)
88102
}
89103
else {
90104
val minimize =
91-
force.minimizeAll ||
105+
force.implicitMode ||
92106
variance >= 0 && !(
93107
force == ForceDegree.noBottom &&
94108
defn.isBottomType(ctx.typeComparer.approximation(tvar.origin, fromBelow = true)))
@@ -366,9 +380,9 @@ object Inferencing {
366380

367381
/** An enumeration controlling the degree of forcing in "is-dully-defined" checks. */
368382
@sharable object ForceDegree {
369-
class Value(val appliesTo: TypeVar => Boolean, val minimizeAll: Boolean)
370-
val none = new Value(_ => false, minimizeAll = false)
371-
val all = new Value(_ => true, minimizeAll = false)
372-
val noBottom = new Value(_ => true, minimizeAll = false)
383+
class Value(val appliesTo: TypeVar => Boolean, val implicitMode: Boolean)
384+
val none = new Value(_ => false, implicitMode = false)
385+
val all = new Value(_ => true, implicitMode = false)
386+
val noBottom = new Value(_ => true, implicitMode = false)
373387
}
374388

tests/pos/implicits1.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,8 @@ object Implicits {
5454

5555
val xx: Int = (1: Byte)
5656

57+
// Problem with implicits over or types
58+
def useOrd[T: math.Ordering](xs: T*) = ()
59+
useOrd(Some(1), None)
60+
5761
}

0 commit comments

Comments
 (0)