Skip to content

Commit bfaef00

Browse files
committed
Handle new expression with only cold args
1 parent 748edc1 commit bfaef00

File tree

2 files changed

+23
-6
lines changed

2 files changed

+23
-6
lines changed

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

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,9 @@ class Semantic {
145145
* Invariant: fields are immutable and only set once from `init`
146146
*/
147147
def updateField(field: Symbol, value: Value): Contextual[Unit] =
148-
heap(ref).fields(field) = value
148+
val fields = heap(ref).fields
149+
assert(!fields.contains(field), field.show + " already init, new = " + value + ", ref =" + ref)
150+
fields(field) = value
149151

150152
/** Update the immediate outer of the given `klass` of the abstract object
151153
*
@@ -400,7 +402,8 @@ class Semantic {
400402
if target.isPrimaryConstructor then
401403
given Env = env2
402404
val tpl = cls.defTree.asInstanceOf[TypeDef].rhs.asInstanceOf[Template]
403-
eval(tpl, addr, cls, cacheResult = true)
405+
val res = eval(tpl, addr, cls, cacheResult = true)
406+
Result(addr, res.errors)
404407
else if target.isConstructor then
405408
given Env = env2
406409
eval(ddef.rhs, addr, cls, cacheResult = true)
@@ -441,7 +444,21 @@ class Semantic {
441444
val trace1 = trace.add(source)
442445
value match {
443446
case Hot =>
444-
Result(Hot, Errors.empty)
447+
val buffer = new mutable.ArrayBuffer[Error]
448+
val args2 = args.map { arg =>
449+
val errors = arg.promote("May only use initialized value as arguments", arg.source)
450+
buffer ++= errors
451+
if errors.isEmpty then Hot
452+
else arg.widen
453+
}
454+
if buffer.isEmpty then Result(Hot, Errors.empty)
455+
else
456+
val value = Warm(klass, Hot, ctor, args2)
457+
if !heap.contains(value) then
458+
val obj = Objekt(klass, fields = mutable.Map.empty, outers = mutable.Map(klass -> Hot))
459+
heap.update(value, obj)
460+
val res = value.call(ctor, args, superType = NoType, source)
461+
Result(res.value, res.errors)
445462

446463
case Cold =>
447464
val error = CallCold(ctor, source, trace1.toVector)
@@ -990,7 +1007,7 @@ class Semantic {
9901007

9911008
// class body
9921009
tpl.body.foreach {
993-
case vdef : ValDef if !vdef.symbol.is(Flags.Lazy) =>
1010+
case vdef : ValDef if !vdef.symbol.is(Flags.Lazy) && !vdef.rhs.isEmpty =>
9941011
given Env = Env.empty
9951012
val res = eval(vdef.rhs, thisV, klass, cacheResult = true)
9961013
errorBuffer ++= res.errors

tests/init/neg/soundness6.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
class C(c: C) {
2-
println(c.n)
3-
val c2 = new C(this) // error
2+
println(c.n) // error
3+
val c2 = new C(this)
44
val n = 10
55
}

0 commit comments

Comments
 (0)