Skip to content

Commit c10505f

Browse files
committed
Some cleanup and fix test case
1 parent 33a5836 commit c10505f

File tree

3 files changed

+31
-27
lines changed

3 files changed

+31
-27
lines changed

Diff for: compiler/src/dotty/tools/dotc/transform/init/Objects.scala

+27-23
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,6 @@ class Objects(using Context @constructorOnly):
410410
new LocalEnv(argMap, meth, outer)(valsMap = mutable.Map.empty, varsMap = mutable.Map.empty)
411411

412412
def ofDefDef(ddef: DefDef, args: List[Value], outer: Data)(using Context): Data =
413-
// println(ddef.show)
414413
val params = ddef.termParamss.flatten.map(_.symbol)
415414
assert(args.size == params.size, "arguments = " + args.size + ", params = " + params.size)
416415
assert(ddef.symbol.owner.isClass ^ (outer != NoEnv), "ddef.owner = " + ddef.symbol.owner.show + ", outer = " + outer + ", " + ddef.source)
@@ -439,47 +438,54 @@ class Objects(using Context @constructorOnly):
439438
throw new RuntimeException("Incorrect local environment for initializing " + x.show)
440439

441440
/**
442-
* Resolve the environment owned by the given method.
441+
* Resolve the environment by searching for a given symbol.
443442
*
444-
* The method could be located in outer scope with intermixed classes between its definition
445-
* site and usage site.
443+
* Searches for the environment that owns `target`, starting from `env` as the innermost.
446444
*
447445
* Due to widening, the corresponding environment might not exist. As a result reading the local
448446
* variable will return `Cold` and it's forbidden to write to the local variable.
449447
*
450-
* @param meth The method which owns the environment
448+
* @param target The symbol to search for.
451449
* @param thisV The value for `this` of the enclosing class where the local variable is referenced.
452450
* @param env The local environment where the local variable is referenced.
453451
*
454-
* @return the environment and value for `this` owned by the given method.
452+
* @return the environment that owns the `target` and value for `this` owned by the given method.
455453
*/
456-
def _resolveEnvByValue(target: Symbol, thisV: ThisValue, env: Data)(using Context): Option[(ThisValue, Data)] = log("Resolving env for " + target.show + ", this = " + thisV.show + ", env = " + env.show, printer) {
454+
def resolveEnvByValue(target: Symbol, thisV: ThisValue, env: Data)(using Context): Option[(ThisValue, Data)] = log("Resolving env by value for " + target.show + ", this = " + thisV.show + ", env = " + env.show, printer) {
457455
env match
458456
case localEnv: LocalEnv =>
459457
if localEnv.getVal(target).isDefined then Some(thisV -> localEnv)
460458
else if localEnv.getVar(target).isDefined then Some(thisV -> localEnv)
461-
else _resolveEnvByValue(target, thisV, localEnv.outer)
459+
else resolveEnvByValue(target, thisV, localEnv.outer)
462460
case NoEnv =>
463461
thisV match
464462
case ref: OfClass =>
465463
ref.outer match
466464
case outer : ThisValue =>
467-
_resolveEnvByValue(target, outer, ref.env)
465+
resolveEnvByValue(target, outer, ref.env)
468466
case _ =>
469467
// TODO: properly handle the case where ref.outer is ValueSet
470468
None
471469
case _ =>
472470
None
473471
}
474472

475-
def resolveEnvByValue(target: Symbol, thisV: ThisValue, env: Data)(using Context): Option[(ThisValue, Data)] =
476-
// println("the target: " + target.show + "its owner: " + target.owner.show + " the env: " + env.show)
477-
val e = _resolveEnvByValue(target, thisV, env)
478-
if e.isDefined then println(e.get._2.show)
479-
else println("NONE")
480-
e
481-
482-
def resolveEnvByOwner(meth: Symbol, thisV: ThisValue, env: Data)(using Context): Option[(ThisValue, Data)] = log("Resolving env for " + meth.show + ", this = " + thisV.show + ", env = " + env.show, printer) {
473+
/**
474+
* Resolve the environment owned by the given method.
475+
*
476+
* The method could be located in outer scope with intermixed classes between its definition
477+
* site and usage site.
478+
*
479+
* Due to widening, the corresponding environment might not exist. As a result reading the local
480+
* variable will return `Cold` and it's forbidden to write to the local variable.
481+
*
482+
* @param meth The method which owns the environment
483+
* @param thisV The value for `this` of the enclosing class where the local variable is referenced.
484+
* @param env The local environment where the local variable is referenced.
485+
*
486+
* @return the environment and value for `this` owned by the given method.
487+
*/
488+
def resolveEnvByOwner(meth: Symbol, thisV: ThisValue, env: Data)(using Context): Option[(ThisValue, Data)] = log("Resolving env by owner for " + meth.show + ", this = " + thisV.show + ", env = " + env.show, printer) {
483489
env match
484490
case localEnv: LocalEnv =>
485491
if localEnv.meth == meth then Some(thisV -> env)
@@ -752,7 +758,6 @@ class Objects(using Context @constructorOnly):
752758
if meth.owner.isClass then
753759
(ref, Env.NoEnv)
754760
else
755-
// println("1: " + meth.show + " env : " + summon[Env.Data].show)
756761
Env.resolveEnvByOwner(meth.owner.enclosingMethod, ref, summon[Env.Data]).getOrElse(Cold -> Env.NoEnv)
757762

758763
val env2 = Env.ofDefDef(ddef, args.map(_.value), outerEnv)
@@ -991,7 +996,6 @@ class Objects(using Context @constructorOnly):
991996
(thisV.widenRefOrCold(1), Env.NoEnv)
992997
else
993998
// klass.enclosingMethod returns its primary constructor
994-
// println("callsite 2: " + klass.show + " env : " + summon[Env.Data].show)
995999
Env.resolveEnvByOwner(klass.owner.enclosingMethod, thisV, summon[Env.Data]).getOrElse(Cold -> Env.NoEnv)
9961000

9971001
val instance = OfClass(klass, outerWidened, ctor, args.map(_.value), envWidened)
@@ -1022,7 +1026,8 @@ class Objects(using Context @constructorOnly):
10221026
*/
10231027
def readLocal(thisV: ThisValue, sym: Symbol): Contextual[Value] = log("reading local " + sym.show, printer, (_: Value).show) {
10241028
def isByNameParam(sym: Symbol) = sym.is(Flags.Param) && sym.info.isInstanceOf[ExprType]
1025-
// println("callsite 3: " + sym.show + " env : " + summon[Env.Data].show)
1029+
// Can't use enclosingMethod here because values defined in a by-name closure will have the wrong enclosingMethod,
1030+
// since our phase is before elimByName.
10261031
Env.resolveEnvByValue(sym, thisV, summon[Env.Data]) match
10271032
case Some(thisV -> env) =>
10281033
if sym.is(Flags.Mutable) then
@@ -1078,7 +1083,8 @@ class Objects(using Context @constructorOnly):
10781083
*/
10791084
def writeLocal(thisV: ThisValue, sym: Symbol, value: Value): Contextual[Value] = log("write local " + sym.show + " with " + value.show, printer, (_: Value).show) {
10801085
assert(sym.is(Flags.Mutable), "Writing to immutable variable " + sym.show)
1081-
// println("callsite 4: " + sym.show + " env : " + summon[Env.Data].show)
1086+
// Can't use enclosingMethod here because values defined in a by-name closure will have the wrong enclosingMethod,
1087+
// since our phase is before elimByName.
10821088
Env.resolveEnvByValue(sym, thisV, summon[Env.Data]) match
10831089
case Some(thisV -> env) =>
10841090
given Env.Data = env
@@ -1215,7 +1221,6 @@ class Objects(using Context @constructorOnly):
12151221
withTrace(trace2) { call(receiver, ref.symbol, args, receiver = qual.tpe, superType = NoType) }
12161222

12171223
case id: Ident =>
1218-
// println("ID : " + id.show)
12191224
id.tpe match
12201225
case TermRef(NoPrefix, _) =>
12211226
// resolve this for the local method
@@ -1285,7 +1290,6 @@ class Objects(using Context @constructorOnly):
12851290
Fun(ddef, thisV, klass, summon[Env.Data])
12861291

12871292
case Block(stats, expr) =>
1288-
// println("BLOCK DATA : " + expr.show)
12891293
evalExprs(stats, thisV, klass)
12901294
eval(expr, thisV, klass)
12911295

Diff for: tests/init/pos/byname.scala renamed to tests/init-global/pos/byname.scala

+3-3
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@ class A extends T:
55
override def bar(i: => Int): Int = i + 1
66

77
class B extends T:
8-
override def bar(i: => Int): Int = i + 2
8+
override def bar(i: => Int): Int = i
99

1010
object A:
1111
val a: T = if ??? then new A else new B
12-
def foo(b: List[Int]) = a.bar(b match {
13-
case x :: xs => 1
12+
def foo(b: List[Int]): Int = a.bar(b match {
13+
case head :: rest => head + foo(rest) + a.bar(head)
1414
case Nil => 0
1515
})
1616

Diff for: tests/init-global/warn/lazy-local-val.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,5 @@ object B:
1515
lazy val b = a
1616
Box(b)
1717

18-
val box = f(n) // warn
18+
val box = f(n)
1919
val n = 10

0 commit comments

Comments
 (0)