Skip to content

Commit abc5010

Browse files
committed
Check that we don't leak uninstantiated type variables
Type variable instantiation should only occur in Typer, TreeChecker and during exhaustiveness checking, this means that no uninstantiated type variable should exist outside of these phases. This was not enforced until now, and was not always true before #4080.
1 parent e531634 commit abc5010

File tree

7 files changed

+17
-4
lines changed

7 files changed

+17
-4
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,4 +94,6 @@ object Mode {
9494
/** We are in the IDE */
9595
val Interactive = newMode(20, "Interactive")
9696

97+
/** Allow instantiating type variables after Typer */
98+
val AllowTypevarsInstantiation = newMode(21, "AllowTypevarsInstantiation")
9799
}

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,9 @@ object Phases {
310310
*/
311311
def isTyper = false
312312

313+
/** Is this phase an instance of TreeChecker ? */
314+
def isTreeChecker = false
315+
313316
/** Can this transform create or delete non-private members? */
314317
def changesMembers: Boolean = false
315318

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3384,7 +3384,11 @@ object Types {
33843384
* uninstantiated
33853385
*/
33863386
def instanceOpt(implicit ctx: Context): Type =
3387-
if (inst.exists) inst else ctx.typerState.instType(this)
3387+
if (inst.exists) inst else {
3388+
assert(ctx.phase.isTyper || ctx.phase.isTreeChecker || ctx.mode.is(Mode.AllowTypevarsInstantiation),
3389+
s"Detected uninstantiated type variable $this in phase ${ctx.phase}")
3390+
ctx.typerState.instType(this)
3391+
}
33883392

33893393
/** Is the variable already instantiated? */
33903394
def isInstantiated(implicit ctx: Context) = instanceOpt.exists

compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ class PatternMatcher extends MiniPhase {
3232
val translated = new Translator(tree.tpe, this).translateMatch(tree)
3333

3434
// check exhaustivity and unreachability
35-
val engine = new patmat.SpaceEngine
35+
val engine = new patmat.SpaceEngine(ctx)
3636

3737
if (engine.checkable(tree)) {
3838
engine.checkExhaustivity(tree)

compiler/src/dotty/tools/dotc/transform/PatternMatcherOld.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ class PatternMatcherOld extends MiniPhase with DenotTransformer {
5151
val translated = new Translator()(ctx).translator.translateMatch(tree)
5252

5353
// check exhaustivity and unreachability
54-
val engine = new SpaceEngine
54+
val engine = new SpaceEngine(ctx)
5555
if (engine.checkable(tree)) {
5656
engine.checkExhaustivity(tree)
5757
engine.checkRedundancy(tree)

compiler/src/dotty/tools/dotc/transform/TreeChecker.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ class TreeChecker extends Phase with SymTransformer {
4949
import ast.tpd._
5050
import TreeChecker._
5151

52+
override def isTreeChecker = true
53+
5254
private val seenClasses = collection.mutable.HashMap[String, Symbol]()
5355
private val seenModuleVals = collection.mutable.HashMap[String, Symbol]()
5456

compiler/src/dotty/tools/dotc/transform/patmat/Space.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,9 +279,11 @@ trait SpaceLogic {
279279
}
280280

281281
/** Scala implementation of space logic */
282-
class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
282+
class SpaceEngine(ictx: Context) extends SpaceLogic {
283283
import tpd._
284284

285+
implicit val ctx: Context = ictx.addMode(Mode.AllowTypevarsInstantiation)
286+
285287
private val scalaSomeClass = ctx.requiredClass("scala.Some")
286288
private val scalaSeqFactoryClass = ctx.requiredClass("scala.collection.generic.SeqFactory")
287289
private val scalaListType = ctx.requiredClassRef("scala.collection.immutable.List")

0 commit comments

Comments
 (0)