Skip to content

Commit 1146598

Browse files
committed
Restore cacheResult option for eval
1 parent 1f72487 commit 1146598

File tree

1 file changed

+28
-24
lines changed

1 file changed

+28
-24
lines changed

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

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ object Semantic {
8282
*/
8383
def updateField(field: Symbol, value: Value)(using Heap, Context): Unit =
8484
val obj = objekt
85-
assert(!obj.hasField(field), field.show + " already init, new = " + value + ", old = " + obj.field(field))
85+
assert(!obj.hasField(field), field.show + " already init, new = " + value + ", old = " + obj.field(field) + ", ref = " + this)
8686
val obj2 = obj.copy(fields = obj.fields.updated(field, value))
8787
heap.update(this, obj2)
8888

@@ -92,7 +92,7 @@ object Semantic {
9292
*/
9393
def updateOuter(klass: ClassSymbol, value: Value)(using Heap, Context): Unit =
9494
val obj = objekt
95-
assert(!obj.hasOuter(klass), klass.show + " already init, new = " + value + ", old = " + obj.outer(klass))
95+
assert(!obj.hasOuter(klass), klass.show + " already has outer, new = " + value + ", old = " + obj.outer(klass) + ", ref = " + this)
9696
val obj2 = obj.copy(outers = obj.outers.updated(klass, value))
9797
heap.update(this, obj2)
9898
}
@@ -292,6 +292,7 @@ object Semantic {
292292
extension (cache: CacheIn | CacheOut)
293293
def contains(value: Value, expr: Tree): Boolean = cache.contains(value) && cache(value).contains(expr)
294294
def get(value: Value, expr: Tree): Value = cache(value)(expr)
295+
def remove(value: Value, expr: Tree) = cache(value).remove(expr)
295296
def put(value: Value, expr: Tree, result: Value): Unit = {
296297
val innerMap = cache.getOrElseUpdate(value, new EqHashMap[Tree, Value])
297298
innerMap(expr) = result
@@ -403,7 +404,7 @@ object Semantic {
403404
if target.is(Flags.Lazy) then
404405
given Trace = trace1
405406
val rhs = target.defTree.asInstanceOf[ValDef].rhs
406-
eval(rhs, ref, target.owner.asClass)
407+
eval(rhs, ref, target.owner.asClass, cacheResult = true)
407408
else
408409
val obj = ref.objekt
409410
if obj.hasField(target) then
@@ -417,7 +418,7 @@ object Semantic {
417418
Result(Hot, Nil)
418419
else if target.hasSource then
419420
val rhs = target.defTree.asInstanceOf[ValOrDefDef].rhs
420-
eval(rhs, ref, target.owner.asClass)
421+
eval(rhs, ref, target.owner.asClass, cacheResult = true)
421422
else
422423
val error = CallUnknown(field, source, trace.toVector)
423424
Result(Hot, error :: Nil)
@@ -469,7 +470,7 @@ object Semantic {
469470
val env2 = Env(ddef, args.map(_.value).widenArgs)
470471
// normal method call
471472
withEnv(if isLocal then env else Env.empty) {
472-
eval(ddef.rhs, ref, cls) ++ checkArgs
473+
eval(ddef.rhs, ref, cls, cacheResult = true) ++ checkArgs
473474
}
474475
else if ref.canIgnoreMethodCall(target) then
475476
Result(Hot, Nil)
@@ -490,7 +491,7 @@ object Semantic {
490491
if meth.name.toString == "tupled" then Result(value, Nil) // a call like `fun.tupled`
491492
else
492493
withEnv(env) {
493-
eval(body, thisV, klass) ++ checkArgs
494+
eval(body, thisV, klass, cacheResult = true) ++ checkArgs
494495
}
495496

496497
case RefSet(refs) =>
@@ -517,11 +518,11 @@ object Semantic {
517518
if ctor.isPrimaryConstructor then
518519
given Env = env2
519520
val tpl = cls.defTree.asInstanceOf[TypeDef].rhs.asInstanceOf[Template]
520-
val res = withTrace(trace.add(cls.defTree)) { eval(tpl, ref, cls) }
521+
val res = withTrace(trace.add(cls.defTree)) { eval(tpl, ref, cls, cacheResult = true) }
521522
Result(ref, res.errors)
522523
else
523524
given Env = env2
524-
eval(ddef.rhs, ref, cls)
525+
eval(ddef.rhs, ref, cls, cacheResult = true)
525526
else if ref.canIgnoreMethodCall(ctor) then
526527
Result(Hot, Nil)
527528
else
@@ -770,25 +771,22 @@ object Semantic {
770771
type Task = ThisRef
771772

772773
class WorkList private[Semantic]() {
773-
private var checkedTasks: Set[Task] = Set.empty
774774
private var pendingTasks: List[Task] = Nil
775775

776776
def addTask(task: Task): Unit =
777-
if !checkedTasks.contains(task) then pendingTasks = task :: pendingTasks
777+
pendingTasks = task :: pendingTasks
778778

779779
/** Process the worklist until done */
780780
@tailrec
781781
final def work()(using State, Context): Unit =
782782
pendingTasks match
783783
case task :: rest =>
784+
val heapBefore = heap.snapshot()
784785
val res = doTask(task)
785786
res.errors.foreach(_.issue)
786787

787-
val heapBefore = heap.snapshot()
788-
789-
if res.errors.nonEmpty then
788+
if res.errors.nonEmpty || !cache.changed then
790789
pendingTasks = rest
791-
checkedTasks = checkedTasks + task
792790
else
793791
// discard heap changes and copy cache.out to cache.in
794792
cache.update()
@@ -811,7 +809,7 @@ object Semantic {
811809
given Trace = Trace.empty
812810
given Env = Env(paramValues)
813811

814-
init(tpl, thisRef, thisRef.klass)
812+
eval(tpl, thisRef, thisRef.klass)
815813
}
816814
}
817815
inline def workList(using wl: WorkList): WorkList = wl
@@ -862,15 +860,17 @@ object Semantic {
862860
*
863861
* This method only handles cache logic and delegates the work to `cases`.
864862
*/
865-
def eval(expr: Tree, thisV: Ref, klass: ClassSymbol): Contextual[Result] = log("evaluating " + expr.show + ", this = " + thisV.show, printer, res => res.asInstanceOf[Result].show) {
863+
def eval(expr: Tree, thisV: Ref, klass: ClassSymbol, cacheResult: Boolean = false): Contextual[Result] = log("evaluating " + expr.show + ", this = " + thisV.show, printer, res => res.asInstanceOf[Result].show) {
866864
if (cache.out.contains(thisV, expr)) Result(cache.out.get(thisV, expr), Errors.empty)
867865
else {
868866
val assumeValue = if (cache.in.contains(thisV, expr)) cache.in.get(thisV, expr) else Hot
869867
cache.out.put(thisV, expr, assumeValue)
870868
val res = cases(expr, thisV, klass)
871869
if res.value != assumeValue then
872870
cache.changed = true
873-
cache.out.put(thisV, expr, res.value)
871+
cache.out.put(thisV, expr, res.value) // must put in cache for termination
872+
else
873+
if !cacheResult then cache.out.remove(thisV, expr)
874874
res
875875
}
876876
}
@@ -1058,6 +1058,9 @@ object Semantic {
10581058
if tdef.isClassDef then Result(Hot, Errors.empty)
10591059
else Result(Hot, checkTermUsage(tdef.rhs, thisV, klass))
10601060

1061+
case tpl: Template =>
1062+
init(tpl, thisV, klass)
1063+
10611064
case _: Import | _: Export =>
10621065
Result(Hot, Errors.empty)
10631066

@@ -1102,17 +1105,15 @@ object Semantic {
11021105
else
11031106
thisV match
11041107
case Hot => Hot
1105-
case thisRef: ThisRef =>
1106-
val obj = thisRef.objekt
1108+
case ref: Ref =>
1109+
val obj = ref.objekt
11071110
val outerCls = klass.owner.lexicallyEnclosingClass.asClass
11081111
if !obj.hasOuter(klass) then
11091112
val error = PromoteError("outer not yet initialized, target = " + target + ", klass = " + klass, source, trace.toVector)
11101113
report.error(error.show + error.stacktrace, source)
11111114
Hot
11121115
else
11131116
resolveThis(target, obj.outer(klass), outerCls, source)
1114-
case warm: Warm =>
1115-
???
11161117
case RefSet(refs) =>
11171118
refs.map(ref => resolveThis(target, ref, klass, source)).join
11181119
case fun: Fun =>
@@ -1168,7 +1169,7 @@ object Semantic {
11681169
else cases(tref.prefix, thisV, klass, source)
11691170

11701171
/** Initialize part of an abstract object in `klass` of the inheritance chain */
1171-
def init(tpl: Template, thisV: ThisRef, klass: ClassSymbol): Contextual[Result] = log("init " + klass.show, printer, res => res.asInstanceOf[Result].show) {
1172+
def init(tpl: Template, thisV: Ref, klass: ClassSymbol): Contextual[Result] = log("init " + klass.show, printer, res => res.asInstanceOf[Result].show) {
11721173
val errorBuffer = new mutable.ArrayBuffer[Error]
11731174

11741175
val paramsMap = tpl.constr.termParamss.flatten.map { vdef =>
@@ -1275,8 +1276,11 @@ object Semantic {
12751276
case _: MemberDef =>
12761277

12771278
case tree =>
1278-
if fieldsChanged then thisV.tryPromoteCurrentObject
1279-
fieldsChanged = false
1279+
thisV match
1280+
case thisRef: ThisRef =>
1281+
if fieldsChanged then thisRef.tryPromoteCurrentObject
1282+
fieldsChanged = false
1283+
case _ =>
12801284

12811285
given Env = Env.empty
12821286
errorBuffer ++= eval(tree, thisV, klass).errors

0 commit comments

Comments
 (0)