Skip to content

Commit 6d892f5

Browse files
committed
Don't interpolate parameters of anonymous functions
Here, we should wait until we get the info from the outside, which can be arbitrarily much later.
1 parent 4ee38a9 commit 6d892f5

File tree

2 files changed

+14
-5
lines changed

2 files changed

+14
-5
lines changed

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,9 @@ abstract class Recheck extends Phase, IdentityDenotTransformer:
234234
def recheckBlock(stats: List[Tree], expr: Tree, pt: Type)(using Context): Type =
235235
recheckStats(stats)
236236
val exprType = recheck(expr)
237+
// The expected type `pt` is not propagated. Doing so would allow variables in the
238+
// expected type to contain references to local symbols of the block, so the
239+
// local symbols could escape that way.
237240
TypeOps.avoid(exprType, localSyms(stats).filterConserve(_.isTerm))
238241

239242
def recheckBlock(tree: Block, pt: Type)(using Context): Type =

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

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -203,11 +203,11 @@ class CheckCaptures extends Recheck:
203203
tp
204204
end transformType
205205

206-
private def interpolateVars(using Context) = new TypeTraverser:
206+
private def interpolator(using Context) = new TypeTraverser:
207207
override def traverse(t: Type) =
208208
t match
209209
case CapturingType(parent, refs: CaptureSet.Var, _) =>
210-
//if variance < 0 then println(i"solving $t")
210+
if variance < 0 then capt.println(i"solving $t")
211211
refs.solve(variance)
212212
traverse(parent)
213213
case t @ RefinedType(_, nme.apply, rinfo) if defn.isFunctionOrPolyType(t) =>
@@ -220,8 +220,8 @@ class CheckCaptures extends Recheck:
220220

221221
private def interpolateVarsIn(tpt: Tree)(using Context): Unit =
222222
if tpt.isInstanceOf[InferredTypeTree] then
223-
//println(i"solving vars in ${knownType(tpt)}, ${knownType(tpt).toString}")
224-
interpolateVars.traverse(knownType(tpt))
223+
interpolator.traverse(knownType(tpt))
224+
.showing(i"solved vars in ${knownType(tpt)}", capt)
225225

226226
private var curEnv: Env = Env(NoSymbol, CaptureSet.empty, false, null)
227227

@@ -289,7 +289,13 @@ class CheckCaptures extends Recheck:
289289

290290
override def recheckValDef(tree: ValDef, sym: Symbol)(using Context): Unit =
291291
try super.recheckValDef(tree, sym)
292-
finally interpolateVarsIn(tree.tpt)
292+
finally
293+
if !sym.is(Param) then
294+
// parameters with inferred types belong to anonymous methods. We need to wait
295+
// for more info from the context, so we cannot interpolate. Note that we cannot
296+
// expect to have all necessary info available at the point where the anonymous
297+
// function is compiled since we do not propagate expected types into blocks.
298+
interpolateVarsIn(tree.tpt)
293299

294300
override def recheckDefDef(tree: DefDef, sym: Symbol)(using Context): Unit =
295301
val saved = curEnv

0 commit comments

Comments
 (0)