Skip to content

Commit c2ef24e

Browse files
committed
Use correct environment for val definitions
1 parent f423ed1 commit c2ef24e

File tree

2 files changed

+27
-9
lines changed

2 files changed

+27
-9
lines changed

compiler/src/dotty/tools/dotc/transform/init/Objects.scala

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,8 @@ object Objects:
234234

235235
def of(ddef: DefDef, args: List[Value], outer: Data)(using Context): Data =
236236
val params = ddef.termParamss.flatten.map(_.symbol)
237-
assert(args.size == params.size && (ddef.symbol.owner.isClass ^ (outer != NoEnv)), "arguments = " + args.size + ", params = " + params.size)
237+
assert(args.size == params.size, "arguments = " + args.size + ", params = " + params.size)
238+
assert(ddef.symbol.owner.isClass ^ (outer != NoEnv), "ddef.owner = " + ddef.symbol.owner.show + ", outer = " + outer + ", " + ddef.source)
238239
new LocalEnv(params.zip(args).toMap, ddef.symbol, outer)
239240

240241
def setLocalVal(x: Symbol, value: Value)(using data: Data, ctx: Context): Unit =
@@ -247,10 +248,10 @@ object Objects:
247248
throw new RuntimeException("Incorrect local environment for initializing " + x.show)
248249

249250
/**
250-
* Resolve the environment owned by the given symbol.
251+
* Resolve the environment owned by the given method.
251252
*
252-
* The owner (e.g., method) could be located in outer scope with intermixed classes between its
253-
* definition site and usage site.
253+
* The method could be located in outer scope with intermixed classes between its definition
254+
* site and usage site.
254255
*
255256
* Due to widening, the corresponding environment might not exist. As a result reading the local
256257
* variable will return `Cold` and it's forbidden to write to the local variable.
@@ -272,6 +273,8 @@ object Objects:
272273
case _ =>
273274
None
274275
end resolveEnv
276+
277+
def withEnv[T](env: Data)(fn: Data ?=> T): T = fn(using env)
275278
end Env
276279

277280
/** Abstract heap for mutable fields
@@ -435,7 +438,7 @@ object Objects:
435438
if meth.owner.isClass then
436439
(ref, Env.NoEnv)
437440
else
438-
Env.resolveEnv(meth.owner, ref, summon[Env.Data]).getOrElse(Cold -> Env.NoEnv)
441+
Env.resolveEnv(meth.owner.enclosingMethod, ref, summon[Env.Data]).getOrElse(Cold -> Env.NoEnv)
439442

440443
val env2 = Env.of(ddef, args.map(_.value), outerEnv)
441444
extendTrace(ddef) {
@@ -579,7 +582,7 @@ object Objects:
579582
if klass.owner.isClass then
580583
(outer.widen(1), Env.NoEnv)
581584
else
582-
Env.resolveEnv(klass.owner, outer, summon[Env.Data]).getOrElse(Cold -> Env.NoEnv)
585+
Env.resolveEnv(klass.enclosingMethod, outer, summon[Env.Data]).getOrElse(Cold -> Env.NoEnv)
583586

584587
val instance = OfClass(klass, outerWidened, ctor, args.map(_.value), envWidened, State.currentObject)
585588
callConstructor(instance, ctor, args)
@@ -598,7 +601,7 @@ object Objects:
598601
}
599602

600603
def readLocal(thisV: Value, sym: Symbol): Contextual[Value] = log("reading local " + sym.show, printer, (_: Value).show) {
601-
Env.resolveEnv(sym.owner, thisV, summon[Env.Data]) match
604+
Env.resolveEnv(sym.enclosingMethod, thisV, summon[Env.Data]) match
602605
case Some(thisV -> env) =>
603606
if sym.is(Flags.Mutable) then
604607
thisV match
@@ -620,7 +623,7 @@ object Objects:
620623

621624
assert(sym.is(Flags.Mutable), "Writing to immutable variable " + sym.show)
622625

623-
Env.resolveEnv(sym.owner, thisV, summon[Env.Data]) match
626+
Env.resolveEnv(sym.enclosingMethod, thisV, summon[Env.Data]) match
624627
case Some(thisV -> env) =>
625628
thisV match
626629
case ref: Ref =>
@@ -649,7 +652,7 @@ object Objects:
649652
count += 1
650653

651654
given Trace = Trace.empty.add(tpl.constr)
652-
given env: Env.Data = Env.NoEnv
655+
given env: Env.Data = Env.emptyEnv(tpl.constr.symbol)
653656

654657
log("Iteration " + count) {
655658
init(tpl, ObjectRef(classSym), classSym)

tests/init/pos/global-val-owner.scala

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
object Test:
2+
val n = {
3+
def fact(x: Int): Int = if x == 0 then 1 else x * fact(x - 1)
4+
fact(5)
5+
}
6+
7+
def foo() =
8+
val n = {
9+
def fact(x: Int): Int = if x == 0 then 1 else x * fact(x - 1)
10+
fact(5)
11+
}
12+
n
13+
14+
val x = foo()
15+

0 commit comments

Comments
 (0)