Skip to content

Commit e64e2d3

Browse files
authored
Merge pull request #3834 from dotty-staging/fix-#2982
Fix #2982: Avoid instantiating to Nothing in some situations
2 parents 73ea385 + b4805bf commit e64e2d3

File tree

5 files changed

+12
-9
lines changed

5 files changed

+12
-9
lines changed

compiler/src/dotty/tools/dotc/core/Types.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3327,6 +3327,10 @@ object Types {
33273327
def instantiate(fromBelow: Boolean)(implicit ctx: Context): Type =
33283328
instantiateWith(ctx.typeComparer.instanceType(origin, fromBelow))
33293329

3330+
/** For uninstantiated type variables: Is the lower bound different from Nothing? */
3331+
def hasLowerBound(implicit ctx: Context) =
3332+
!ctx.typerState.constraint.entry(origin).loBound.isBottomType
3333+
33303334
/** Unwrap to instance (if instantiated) or origin (if not), until result
33313335
* is no longer a TypeVar
33323336
*/

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,7 @@ trait Inferencing { this: Typer =>
389389
if (!(vs contains tvar) && qualifies(tvar)) {
390390
typr.println(s"instantiating non-occurring ${tvar.show} in ${tp.show} / $tp")
391391
ensureConstrained()
392-
tvar.instantiate(fromBelow = true)
392+
tvar.instantiate(fromBelow = tvar.hasLowerBound)
393393
}
394394
}
395395
if (constraint.uninstVars exists qualifies) interpolate()

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,8 @@ trait TypeAssigner {
113113
case tp: SkolemType if partsToAvoid(mutable.Set.empty, tp.info).nonEmpty =>
114114
range(tp.info.bottomType, apply(tp.info))
115115
case tp: TypeVar if ctx.typerState.constraint.contains(tp) =>
116-
val lo = ctx.typeComparer.instanceType(tp.origin, fromBelow = variance >= 0)
116+
val lo = ctx.typeComparer.instanceType(
117+
tp.origin, fromBelow = variance > 0 || variance == 0 && tp.hasLowerBound)
117118
val lo1 = apply(lo)
118119
if (lo1 ne lo) lo1 else tp
119120
case _ =>

tests/neg-tailcall/tailrec.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ class Failures {
5656
}
5757

5858
// unsafe
59-
@tailrec final def fail3[T](x: Int): Int = fail3(x - 1)
59+
@tailrec final def fail3[T](x: Int): Int = fail3(x - 1) // error // error: recursive application has different type arguments
6060

6161
// unsafe
6262
class Tom[T](x: Int) {

tests/pos/i2982.scala

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1+
12
object A {
2-
def fun[E >: B](a: A[E]): E => Unit = ???
3-
val x = fun(new A[C])
3+
def fun[E](a: A[E]): Unit = ()
4+
fun(new A[Int])
45
}
5-
class B extends C
6-
class C
7-
8-
class A[-X >: B]
6+
class A[-X]

0 commit comments

Comments
 (0)