@@ -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,46 @@ 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 => eval(vdef.rhs, addr, klass)
531+
532+ case _ =>
533+ report.error(" unexpected defTree when accessing local variable, sym = " + sym.show + " , defTree = " + sym.defTree.show, source)
534+ default()
535+ }
536+
537+ case _ => default()
538+ }
500539 end extension
501540
502541// ----- Promotion ----------------------------------------------------
@@ -685,7 +724,7 @@ class Semantic {
685724 }
686725
687726 /** Evaluate a list of expressions */
688- def eval (exprs : List [Tree ], thisV : Addr , klass : ClassSymbol ): Contextual [List [Result ]] =
727+ def eval (exprs : List [Tree ], thisV : Addr , klass : ClassSymbol ): Contextual [List [Result ]] =
689728 exprs.map { expr => eval(expr, thisV, klass) }
690729
691730 /** Evaluate arguments of methods */
@@ -848,8 +887,7 @@ class Semantic {
848887 case vdef : ValDef =>
849888 // local val definition
850889 // TODO: support explicit @cold annotation for local definitions
851- eval(vdef.rhs, thisV, klass, true )
852- // .ensureHot("Local definitions may only hold initialized values", vdef)
890+ eval(vdef.rhs, thisV, klass, cacheResult = true )
853891
854892 case ddef : DefDef =>
855893 // local method
@@ -877,44 +915,8 @@ class Semantic {
877915 Result (Hot , Errors .empty)
878916
879917 case tmref : TermRef if tmref.prefix == NoPrefix =>
880- val sym = tmref.symbol
881-
882- def default () = Result (Hot , Nil )
883-
884- if sym.is(Flags .Param ) && sym.owner.isConstructor then
885- // instances of local classes inside secondary constructors cannot
886- // reach here, as those values are abstracted by Cold instead of Warm.
887- // This enables us to simplify the domain without sacrificing
888- // expressiveness nor soundess, as local classes inside secondary
889- // constructors are uncommon.
890- if sym.isContainedIn(klass) then
891- Result (env.lookup(sym), Nil )
892- else
893- // We don't know much about secondary constructor parameters in outer scope.
894- // It's always safe to approximate them with `Cold`.
895- Result (Cold , Nil )
896- else
897- sym.defTree match {
898- case vdef : ValDef => {
899- // resolve this for local variable
900- val enclosingClass = sym.owner.enclosingClass.asClass
901- val thisValue2 = resolveThis(enclosingClass, thisV, klass, source)
902- thisValue2 match {
903- case Hot => Result (Hot , Errors .empty)
904- case Cold => {
905- val error = AccessCold (sym, source, trace.toVector)
906- Result (Hot , error :: Nil )
907- }
908- case addr : Addr => {
909- val res = eval(vdef.rhs, addr, klass)
910- if res.value.promote(" Try promote" , source).isEmpty then Result (Hot , Errors .empty) else res
911- }
912- case _ => ???
913- }
914- }
915- case _ => default()
916- }
917-
918+ thisV.accessLocal(tmref, klass, source)
919+
918920 case tmref : TermRef =>
919921 cases(tmref.prefix, thisV, klass, source).select(tmref.symbol, source)
920922
0 commit comments