Skip to content

Make Array.apply an intrinsic #18537

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Sep 21, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 17 additions & 13 deletions compiler/src/dotty/tools/dotc/transform/init/Objects.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder about the name change. Is the Union intended to convey that we update the heap with the join? In that case, I suggest writeJoin rather than writeUnion for consistency.

heap.get(addr) match
case None =>
heap = heap.updated(addr, value)
Expand All @@ -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 =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without braces, it's hard to see which methods are part of class MutableData and which come after. Suggest an end line to indicate the end of MutableData.

mutable.writeUnion(addr, value)

def localVarAddr(regions: Regions.Data, sym: Symbol, owner: ClassSymbol): Addr =
LocalVarAddr(regions, sym, owner)
Expand Down Expand Up @@ -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)
Expand All @@ -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
Expand All @@ -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.writeUnion(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
Expand Down Expand Up @@ -842,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
Expand All @@ -867,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`.
Expand Down Expand Up @@ -903,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)
}
Expand Down Expand Up @@ -964,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
Expand All @@ -974,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)

Expand Down Expand Up @@ -1537,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)
Expand Down Expand Up @@ -1632,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)

Expand Down
8 changes: 8 additions & 0 deletions tests/init-global/neg/mutable-array.scala
Original file line number Diff line number Diff line change
@@ -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