Skip to content

Commit 674f5a8

Browse files
committed
Add completions to Rechecker
Complete val and def definitions lazily on first access. Now, recheckDefDef and recheckValDef are called the first time the new info of the defined symbol is needed, or, if the info is never needed, when the typer gets to the definitions. This only applied to definitions with inferred types. The others are handled in typer sequence, as before. The motivation of the change is that some modifications to inferred types of symbols can be made in subclasses without running into ordering problems.
1 parent 6f2c093 commit 674f5a8

File tree

2 files changed

+27
-15
lines changed

2 files changed

+27
-15
lines changed

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

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ abstract class Recheck extends Phase, IdentityDenotTransformer:
7272
def knownType(tree: Tree) =
7373
tree.attachmentOrElse(RecheckedType, tree.tpe)
7474

75+
def needsRecompletion(tree: ValOrDefDef)(using Context): Boolean =
76+
tree.tpt.hasAttachment(RecheckedType) && !tree.symbol.isConstructor
77+
7578
def transformType(tp: Type, inferred: Boolean)(using Context): Type = tp
7679

7780
object transformTypes extends TreeTraverser:
@@ -80,7 +83,7 @@ abstract class Recheck extends Phase, IdentityDenotTransformer:
8083
tree match
8184
case tree: TypeTree =>
8285
transformType(tree.tpe, tree.isInstanceOf[InferredTypeTree]).rememberFor(tree)
83-
case tree: ValOrDefDef if tree.tpt.hasAttachment(RecheckedType) =>
86+
case tree: ValOrDefDef if needsRecompletion(tree) =>
8487
val sym = tree.symbol
8588
def integrateRT(restp: Type, info: Type, psymss: List[List[Symbol]]): Type = info match
8689
case info: MethodOrPoly =>
@@ -90,10 +93,13 @@ abstract class Recheck extends Phase, IdentityDenotTransformer:
9093
info.derivedExprType(resType = restp)
9194
case _ =>
9295
restp
93-
if !sym.isConstructor then
94-
val info1 = integrateRT(knownType(tree.tpt), sym.info, sym.paramSymss)
95-
recheckr.println(i"update info $sym: ${sym.info} --> $info1")
96-
sym.updateInfo(info1)
96+
val newInfo = integrateRT(knownType(tree.tpt), sym.info, sym.paramSymss)
97+
.showing(i"update info $sym: ${sym.info} --> $result", recheckr)
98+
val completer = new LazyType:
99+
def complete(denot: SymDenotation)(using Context) =
100+
denot.info = newInfo
101+
recheckDef(tree, sym)
102+
sym.updateInfo(completer)
97103
case tree: Bind =>
98104
val sym = tree.symbol
99105
sym.updateInfo(transformType(sym.info, inferred = true))
@@ -133,15 +139,13 @@ abstract class Recheck extends Phase, IdentityDenotTransformer:
133139
val exprType = recheck(expr, defn.UnitType)
134140
bindType
135141

136-
def recheckValDef(tree: ValDef, sym: Symbol)(using Context): Type =
142+
def recheckValDef(tree: ValDef, sym: Symbol)(using Context): Unit =
137143
if !tree.rhs.isEmpty then recheck(tree.rhs, sym.info)
138-
sym.termRef
139144

140-
def recheckDefDef(tree: DefDef, sym: Symbol)(using Context): Type =
145+
def recheckDefDef(tree: DefDef, sym: Symbol)(using Context): Unit =
141146
val rhsCtx = linkConstructorParams(sym)
142147
if !tree.rhs.isEmpty && !sym.isInlineMethod && !sym.isEffectivelyErased then
143148
inContext(rhsCtx) { recheck(tree.rhs, recheck(tree.tpt)) }
144-
sym.termRef
145149

146150
def recheckTypeDef(tree: TypeDef, sym: Symbol)(using Context): Type =
147151
recheck(tree.rhs)
@@ -281,6 +285,13 @@ abstract class Recheck extends Phase, IdentityDenotTransformer:
281285
def recheckStats(stats: List[Tree])(using Context): Unit =
282286
stats.foreach(recheck(_))
283287

288+
def recheckDef(tree: ValOrDefDef, sym: Symbol)(using Context): Unit =
289+
inContext(ctx.localContext(tree, sym)) {
290+
tree match
291+
case tree: ValDef => recheckValDef(tree, sym)
292+
case tree: DefDef => recheckDefDef(tree, sym)
293+
}
294+
284295
/** Recheck tree without adapting it, returning its new type.
285296
* @param tree the original tree
286297
* @param pt the expected result type
@@ -293,11 +304,12 @@ abstract class Recheck extends Phase, IdentityDenotTransformer:
293304
case tree: Ident => recheckIdent(tree)
294305
case tree: Select => recheckSelect(tree)
295306
case tree: Bind => recheckBind(tree, pt)
296-
case tree: ValDef =>
307+
case tree: ValOrDefDef =>
297308
if tree.isEmpty then NoType
298-
else recheckValDef(tree, sym)(using ctx.localContext(tree, sym))
299-
case tree: DefDef =>
300-
recheckDefDef(tree, sym)(using ctx.localContext(tree, sym))
309+
else
310+
if needsRecompletion(tree) then sym.ensureCompleted()
311+
else recheckDef(tree, sym)
312+
sym.termRef
301313
case tree: TypeDef =>
302314
tree.rhs match
303315
case impl: Template =>

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -267,10 +267,10 @@ class CheckCaptures extends Recheck:
267267
if tree.symbol.is(Method) then includeCallCaptures(tree.symbol, tree.srcPos)
268268
super.recheckIdent(tree)
269269

270-
override def recheckValDef(tree: ValDef, sym: Symbol)(using Context): Type =
270+
override def recheckValDef(tree: ValDef, sym: Symbol)(using Context): Unit =
271271
super.recheckValDef(tree, sym)
272272

273-
override def recheckDefDef(tree: DefDef, sym: Symbol)(using Context): Type =
273+
override def recheckDefDef(tree: DefDef, sym: Symbol)(using Context): Unit =
274274
val saved = curEnv
275275
val localSet = capturedVars(sym)
276276
if !localSet.isAlwaysEmpty then curEnv = Env(sym, localSet, false, curEnv)

0 commit comments

Comments
 (0)