From 8bfc293138f814afbeab3be99016bc94bf6470b3 Mon Sep 17 00:00:00 2001 From: Fengyun Liu Date: Mon, 11 Sep 2023 16:30:35 +0200 Subject: [PATCH 1/3] Make Array.apply an intrinsic --- .../src/dotty/tools/dotc/transform/init/Objects.scala | 8 ++++++-- tests/init-global/neg/mutable-array.scala | 8 ++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 tests/init-global/neg/mutable-array.scala diff --git a/compiler/src/dotty/tools/dotc/transform/init/Objects.scala b/compiler/src/dotty/tools/dotc/transform/init/Objects.scala index 3d01b6a93b08..c29fa3fb2c81 100644 --- a/compiler/src/dotty/tools/dotc/transform/init/Objects.scala +++ b/compiler/src/dotty/tools/dotc/transform/init/Objects.scala @@ -616,7 +616,7 @@ object Objects: * @param superType The type of the super in a super call. NoType for non-super calls. * @param needResolve Whether the target of the call needs resolution? */ - def call(value: Value, meth: Symbol, args: List[ArgInfo], receiver: Type, superType: Type, needResolve: Boolean = true): Contextual[Value] = log("call " + meth.show + ", args = " + args.map(_.value.show), printer, (_: Value).show) { + def call(value: Value, meth: Symbol, args: List[ArgInfo], receiver: Type, superType: Type, needResolve: Boolean = true): Contextual[Value] = log("call " + meth.show + ", this = " + value.show + ", args = " + args.map(_.value.show), printer, (_: Value).show) { value match case Cold => report.warning("Using cold alias. Calling trace:\n" + Trace.show, Trace.position) @@ -658,7 +658,11 @@ object Objects: resolve(ref.klass, meth) if target.isOneOf(Flags.Method) then - if target.hasSource then + if target.owner == defn.ArrayModuleClass && target.name == nme.apply then + val arr = OfArray(State.currentObject, summon[Regions.Data]) + Heap.write(arr.addr, args.map(_.value).join) + arr + else if target.hasSource then val cls = target.owner.enclosingClass.asClass val ddef = target.defTree.asInstanceOf[DefDef] val meth = ddef.symbol diff --git a/tests/init-global/neg/mutable-array.scala b/tests/init-global/neg/mutable-array.scala new file mode 100644 index 000000000000..3cbc23a5e127 --- /dev/null +++ b/tests/init-global/neg/mutable-array.scala @@ -0,0 +1,8 @@ +object A: + class Box(var value: Int) + val box: Box = new Box(0) + +object B: + val boxes: Array[A.Box] = Array(A.box) + val box: A.Box = boxes(0) + val x: Int = box.value // error From 1e5f66111d6199343031c835029f9374b673cbd3 Mon Sep 17 00:00:00 2001 From: Fengyun Liu Date: Mon, 11 Sep 2023 16:49:13 +0200 Subject: [PATCH 2/3] Rename Heap.write to Heap.writeUnion --- .../tools/dotc/transform/init/Objects.scala | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/init/Objects.scala b/compiler/src/dotty/tools/dotc/transform/init/Objects.scala index c29fa3fb2c81..0c116cc29d5c 100644 --- a/compiler/src/dotty/tools/dotc/transform/init/Objects.scala +++ b/compiler/src/dotty/tools/dotc/transform/init/Objects.scala @@ -470,7 +470,7 @@ object Objects: /** Store the heap as a mutable field to avoid threading it through the program. */ class MutableData(private[Heap] var heap: Data): - private[Heap] def update(addr: Addr, value: Value): Unit = + private[Heap] def writeUnion(addr: Addr, value: Value): Unit = heap.get(addr) match case None => heap = heap.updated(addr, value) @@ -489,8 +489,8 @@ object Objects: def read(addr: Addr)(using mutable: MutableData): Value = mutable.heap(addr) - def write(addr: Addr, value: Value)(using mutable: MutableData): Unit = - mutable.update(addr, value) + def writeUnion(addr: Addr, value: Value)(using mutable: MutableData): Unit = + mutable.writeUnion(addr, value) def localVarAddr(regions: Regions.Data, sym: Symbol, owner: ClassSymbol): Addr = LocalVarAddr(regions, sym, owner) @@ -639,7 +639,7 @@ object Objects: if arr.addr.owner != State.currentObject then errorMutateOtherStaticObject(State.currentObject, arr.addr.owner) else - Heap.write(arr.addr, args.tail.head.value) + Heap.writeUnion(arr.addr, args.tail.head.value) Bottom else // Array.length is OK @@ -660,7 +660,7 @@ object Objects: if target.isOneOf(Flags.Method) then if target.owner == defn.ArrayModuleClass && target.name == nme.apply then val arr = OfArray(State.currentObject, summon[Regions.Data]) - Heap.write(arr.addr, args.map(_.value).join) + Heap.writeUnion(arr.addr, args.map(_.value).join) arr else if target.hasSource then val cls = target.owner.enclosingClass.asClass @@ -846,7 +846,7 @@ object Objects: if addr.owner != State.currentObject then errorMutateOtherStaticObject(State.currentObject, addr.owner) else - Heap.write(addr, rhs) + Heap.writeUnion(addr, rhs) else report.warning("Mutating a field before its initialization: " + field.show + ". Calling trace:\n" + Trace.show, Trace.position) end match @@ -871,7 +871,7 @@ object Objects: case outer: (Ref | Cold.type | Bottom.type) => if klass == defn.ArrayClass then val arr = OfArray(State.currentObject, summon[Regions.Data]) - Heap.write(arr.addr, Bottom) + Heap.writeUnion(arr.addr, Bottom) arr else // Widen the outer to finitize the domain. Arguments already widened in `evalArgs`. @@ -907,7 +907,7 @@ object Objects: if sym.is(Flags.Mutable) then val addr = Heap.localVarAddr(summon[Regions.Data], sym, State.currentObject) Env.setLocalVar(sym, addr) - Heap.write(addr, value) + Heap.writeUnion(addr, value) else Env.setLocalVal(sym, value) } @@ -968,8 +968,8 @@ object Objects: * @param value The value of the rhs of the assignment. */ def writeLocal(thisV: ThisValue, sym: Symbol, value: Value): Contextual[Value] = log("write local " + sym.show + " with " + value.show, printer, (_: Value).show) { - assert(sym.is(Flags.Mutable), "Writing to immutable variable " + sym.show) + Env.resolveEnv(sym.enclosingMethod, thisV, summon[Env.Data]) match case Some(thisV -> env) => given Env.Data = env @@ -978,7 +978,7 @@ object Objects: if addr.owner != State.currentObject then errorMutateOtherStaticObject(State.currentObject, addr.owner) else - Heap.write(addr, value) + Heap.writeUnion(addr, value) case _ => report.warning("[Internal error] Variable not found " + sym.show + "\nenv = " + env.show + ". Calling trace:\n" + Trace.show, Trace.position) @@ -1541,7 +1541,7 @@ object Objects: if acc.is(Flags.Mutable) then val addr = Heap.fieldVarAddr(summon[Regions.Data], acc, State.currentObject) thisV.initVar(acc, addr) - Heap.write(addr, value) + Heap.writeUnion(addr, value) else thisV.initVal(acc, value) printer.println(acc.show + " initialized with " + value) @@ -1636,7 +1636,7 @@ object Objects: if sym.is(Flags.Mutable) then val addr = Heap.fieldVarAddr(summon[Regions.Data], sym, State.currentObject) thisV.initVar(sym, addr) - Heap.write(addr, res) + Heap.writeUnion(addr, res) else thisV.initVal(sym, res) From 9e80e941f4f5314466837cef5fa2e190636b713b Mon Sep 17 00:00:00 2001 From: Fengyun Liu Date: Wed, 20 Sep 2023 19:40:36 +0200 Subject: [PATCH 3/3] Address review: Better names --- .../tools/dotc/transform/init/Objects.scala | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/init/Objects.scala b/compiler/src/dotty/tools/dotc/transform/init/Objects.scala index 0c116cc29d5c..836218f302bc 100644 --- a/compiler/src/dotty/tools/dotc/transform/init/Objects.scala +++ b/compiler/src/dotty/tools/dotc/transform/init/Objects.scala @@ -470,7 +470,7 @@ object Objects: /** Store the heap as a mutable field to avoid threading it through the program. */ class MutableData(private[Heap] var heap: Data): - private[Heap] def writeUnion(addr: Addr, value: Value): Unit = + private[Heap] def writeJoin(addr: Addr, value: Value): Unit = heap.get(addr) match case None => heap = heap.updated(addr, value) @@ -479,7 +479,7 @@ object Objects: val value2 = value.join(current) if value2 != current then heap = heap.updated(addr, value2) - + end MutableData def empty(): MutableData = new MutableData(Map.empty) @@ -489,8 +489,8 @@ object Objects: def read(addr: Addr)(using mutable: MutableData): Value = mutable.heap(addr) - def writeUnion(addr: Addr, value: Value)(using mutable: MutableData): Unit = - mutable.writeUnion(addr, value) + def writeJoin(addr: Addr, value: Value)(using mutable: MutableData): Unit = + mutable.writeJoin(addr, value) def localVarAddr(regions: Regions.Data, sym: Symbol, owner: ClassSymbol): Addr = LocalVarAddr(regions, sym, owner) @@ -639,7 +639,7 @@ object Objects: if arr.addr.owner != State.currentObject then errorMutateOtherStaticObject(State.currentObject, arr.addr.owner) else - Heap.writeUnion(arr.addr, args.tail.head.value) + Heap.writeJoin(arr.addr, args.tail.head.value) Bottom else // Array.length is OK @@ -660,7 +660,7 @@ object Objects: if target.isOneOf(Flags.Method) then if target.owner == defn.ArrayModuleClass && target.name == nme.apply then val arr = OfArray(State.currentObject, summon[Regions.Data]) - Heap.writeUnion(arr.addr, args.map(_.value).join) + Heap.writeJoin(arr.addr, args.map(_.value).join) arr else if target.hasSource then val cls = target.owner.enclosingClass.asClass @@ -846,7 +846,7 @@ object Objects: if addr.owner != State.currentObject then errorMutateOtherStaticObject(State.currentObject, addr.owner) else - Heap.writeUnion(addr, rhs) + Heap.writeJoin(addr, rhs) else report.warning("Mutating a field before its initialization: " + field.show + ". Calling trace:\n" + Trace.show, Trace.position) end match @@ -871,7 +871,7 @@ object Objects: case outer: (Ref | Cold.type | Bottom.type) => if klass == defn.ArrayClass then val arr = OfArray(State.currentObject, summon[Regions.Data]) - Heap.writeUnion(arr.addr, Bottom) + Heap.writeJoin(arr.addr, Bottom) arr else // Widen the outer to finitize the domain. Arguments already widened in `evalArgs`. @@ -907,7 +907,7 @@ object Objects: if sym.is(Flags.Mutable) then val addr = Heap.localVarAddr(summon[Regions.Data], sym, State.currentObject) Env.setLocalVar(sym, addr) - Heap.writeUnion(addr, value) + Heap.writeJoin(addr, value) else Env.setLocalVal(sym, value) } @@ -978,7 +978,7 @@ object Objects: if addr.owner != State.currentObject then errorMutateOtherStaticObject(State.currentObject, addr.owner) else - Heap.writeUnion(addr, value) + Heap.writeJoin(addr, value) case _ => report.warning("[Internal error] Variable not found " + sym.show + "\nenv = " + env.show + ". Calling trace:\n" + Trace.show, Trace.position) @@ -1541,7 +1541,7 @@ object Objects: if acc.is(Flags.Mutable) then val addr = Heap.fieldVarAddr(summon[Regions.Data], acc, State.currentObject) thisV.initVar(acc, addr) - Heap.writeUnion(addr, value) + Heap.writeJoin(addr, value) else thisV.initVal(acc, value) printer.println(acc.show + " initialized with " + value) @@ -1636,7 +1636,7 @@ object Objects: if sym.is(Flags.Mutable) then val addr = Heap.fieldVarAddr(summon[Regions.Data], sym, State.currentObject) thisV.initVar(sym, addr) - Heap.writeUnion(addr, res) + Heap.writeJoin(addr, res) else thisV.initVal(sym, res)