Skip to content

Commit 9bea086

Browse files
committed
Refactoring accessLocal
Further refactor accessLocal
1 parent 4887b89 commit 9bea086

File tree

4 files changed

+58
-43
lines changed

4 files changed

+58
-43
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,13 @@ class Checker extends Phase {
3737

3838
val traverser = new TreeTraverser {
3939
override def traverse(tree: Tree)(using Context): Unit =
40+
traverseChildren(tree)
4041
tree match {
4142
case tdef: MemberDef =>
4243
// self-type annotation ValDef has no symbol
4344
if tdef.name != nme.WILDCARD then
4445
tdef.symbol.defTree = tree
4546
case _ =>
46-
traverseChildren(tree)
4747
}
4848
}
4949

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

Lines changed: 45 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,6 @@ class Semantic {
406406
given Trace = trace1
407407
val cls = target.owner.enclosingClass.asClass
408408
val ddef = target.defTree.asInstanceOf[DefDef]
409-
// try early promotion here; if returns error, returns cold
410409
val env2 = Env(ddef, args.map(_.value).widenArgs)
411410
if target.isPrimaryConstructor then
412411
given Env = env2
@@ -497,6 +496,48 @@ class Semantic {
497496
Result(value2, errors)
498497
}
499498
}
499+
500+
def accessLocal(tmref: TermRef, klass: ClassSymbol, source: Tree): Contextual[Result] =
501+
val sym = tmref.symbol
502+
503+
def default() = Result(Hot, Nil)
504+
505+
if sym.is(Flags.Param) && sym.owner.isConstructor then
506+
// instances of local classes inside secondary constructors cannot
507+
// reach here, as those values are abstracted by Cold instead of Warm.
508+
// This enables us to simplify the domain without sacrificing
509+
// expressiveness nor soundess, as local classes inside secondary
510+
// constructors are uncommon.
511+
if sym.isContainedIn(klass) then
512+
Result(env.lookup(sym), Nil)
513+
else
514+
// We don't know much about secondary constructor parameters in outer scope.
515+
// It's always safe to approximate them with `Cold`.
516+
Result(Cold, Nil)
517+
else if sym.is(Flags.Param) then
518+
default()
519+
else
520+
sym.defTree match {
521+
case vdef: ValDef =>
522+
// resolve this for local variable
523+
val enclosingClass = sym.owner.enclosingClass.asClass
524+
val thisValue2 = resolveThis(enclosingClass, value, klass, source)
525+
thisValue2 match {
526+
case Hot => Result(Hot, Errors.empty)
527+
528+
case Cold => Result(Cold, Nil)
529+
530+
case addr: Addr =>
531+
val res = eval(vdef.rhs, addr, klass)
532+
if res.value.promote("Try promote", source).isEmpty then Result(Hot, Errors.empty) else res
533+
534+
case _ =>
535+
report.error("unexpected defTree when accessing local variable, sym = " + sym.show + ", defTree = " + sym.defTree.show, source)
536+
default()
537+
}
538+
539+
case _ => default()
540+
}
500541
end extension
501542

502543
// ----- Promotion ----------------------------------------------------
@@ -694,7 +735,7 @@ class Semantic {
694735
}
695736

696737
/** Evaluate a list of expressions */
697-
def eval(exprs: List[Tree], thisV: Addr, klass: ClassSymbol): Contextual[List[Result]] =
738+
def eval(exprs: List[Tree], thisV: Addr, klass: ClassSymbol): Contextual[List[Result]] =
698739
exprs.map { expr => eval(expr, thisV, klass) }
699740

700741
/** Evaluate arguments of methods */
@@ -857,8 +898,7 @@ class Semantic {
857898
case vdef : ValDef =>
858899
// local val definition
859900
// TODO: support explicit @cold annotation for local definitions
860-
eval(vdef.rhs, thisV, klass, true)
861-
// .ensureHot("Local definitions may only hold initialized values", vdef)
901+
eval(vdef.rhs, thisV, klass, cacheResult = true)
862902

863903
case ddef : DefDef =>
864904
// local method
@@ -886,43 +926,7 @@ class Semantic {
886926
Result(Hot, Errors.empty)
887927

888928
case tmref: TermRef if tmref.prefix == NoPrefix =>
889-
val sym = tmref.symbol
890-
891-
def default() = Result(Hot, Nil)
892-
893-
if sym.is(Flags.Param) && sym.owner.isConstructor then
894-
// instances of local classes inside secondary constructors cannot
895-
// reach here, as those values are abstracted by Cold instead of Warm.
896-
// This enables us to simplify the domain without sacrificing
897-
// expressiveness nor soundess, as local classes inside secondary
898-
// constructors are uncommon.
899-
if sym.isContainedIn(klass) then
900-
Result(env.lookup(sym), Nil)
901-
else
902-
// We don't know much about secondary constructor parameters in outer scope.
903-
// It's always safe to approximate them with `Cold`.
904-
Result(Cold, Nil)
905-
else
906-
sym.defTree match {
907-
case vdef: ValDef => {
908-
// resolve this for local variable
909-
val enclosingClass = sym.owner.enclosingClass.asClass
910-
val thisValue2 = resolveThis(enclosingClass, thisV, klass, source)
911-
thisValue2 match {
912-
case Hot => Result(Hot, Errors.empty)
913-
case Cold => {
914-
val error = AccessCold(sym, source, trace.toVector)
915-
Result(Hot, error :: Nil)
916-
}
917-
case addr: Addr => {
918-
val res = eval(vdef.rhs, addr, klass)
919-
if res.value.promote("Try promote", source).isEmpty then Result(Hot, Errors.empty) else res
920-
}
921-
case _ => ???
922-
}
923-
}
924-
case _ => default()
925-
}
929+
thisV.accessLocal(tmref, klass, source)
926930

927931
case tmref: TermRef =>
928932
cases(tmref.prefix, thisV, klass, source).select(tmref.symbol, source)

tests/init/neg/access-argument.scala

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
class A {
2+
def foo(b: B): A = {
3+
val temp = b
4+
temp.bar(this) // error
5+
}
6+
val x = foo(new B)
7+
}
8+
9+
class B {
10+
def bar(a: A): A = a.x
11+
}

tests/init/neg/secondary-ctor2.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ class A(b: B, x: Int) {
77
Inner().foo()
88

99
val f = () => new A(b, 3)
10-
f() // ok
10+
f()
1111
}
1212
}
1313

0 commit comments

Comments
 (0)