@@ -406,7 +406,6 @@ class Semantic {
406
406
given Trace = trace1
407
407
val cls = target.owner.enclosingClass.asClass
408
408
val ddef = target.defTree.asInstanceOf [DefDef ]
409
- // try early promotion here; if returns error, returns cold
410
409
val env2 = Env (ddef, args.map(_.value).widenArgs)
411
410
if target.isPrimaryConstructor then
412
411
given Env = env2
@@ -497,6 +496,46 @@ class Semantic {
497
496
Result (value2, errors)
498
497
}
499
498
}
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
+ }
500
539
end extension
501
540
502
541
// ----- Promotion ----------------------------------------------------
@@ -685,7 +724,7 @@ class Semantic {
685
724
}
686
725
687
726
/** 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 ]] =
689
728
exprs.map { expr => eval(expr, thisV, klass) }
690
729
691
730
/** Evaluate arguments of methods */
@@ -848,8 +887,7 @@ class Semantic {
848
887
case vdef : ValDef =>
849
888
// local val definition
850
889
// 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 )
853
891
854
892
case ddef : DefDef =>
855
893
// local method
@@ -877,44 +915,8 @@ class Semantic {
877
915
Result (Hot , Errors .empty)
878
916
879
917
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
+
918
920
case tmref : TermRef =>
919
921
cases(tmref.prefix, thisV, klass, source).select(tmref.symbol, source)
920
922
0 commit comments