Skip to content

Commit f58c158

Browse files
authored
Merge pull request #15467 from dotty-staging/fix-scala-js-init
Try promotion while widening arguments
2 parents 13d9359 + 4969b26 commit f58c158

File tree

3 files changed

+40
-8
lines changed

3 files changed

+40
-8
lines changed

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

+16-8
Original file line numberDiff line numberDiff line change
@@ -479,10 +479,16 @@ object Semantic:
479479
RefSet(refs1 ++ diff)
480480

481481
/** Conservatively approximate the value with `Cold` or `Hot` */
482-
def widenArg: Value =
482+
def widenArg: Contextual[Value] =
483483
a match
484-
case _: Ref | _: Fun => Cold
485-
case RefSet(refs) => refs.map(_.widenArg).join
484+
case _: Ref | _: Fun =>
485+
val errors = Reporter.stopEarly { a.promote("Argument cannot be promoted to hot") }
486+
if errors.isEmpty then Hot
487+
else Cold
488+
489+
case RefSet(refs) =>
490+
refs.map(_.widenArg).join
491+
486492
case _ => a
487493

488494

@@ -491,7 +497,7 @@ object Semantic:
491497
if values.isEmpty then Hot
492498
else values.reduce { (v1, v2) => v1.join(v2) }
493499

494-
def widenArgs: List[Value] = values.map(_.widenArg).toList
500+
def widenArgs: Contextual[List[Value]] = values.map(_.widenArg).toList
495501

496502

497503
extension (ref: Ref)
@@ -738,12 +744,13 @@ object Semantic:
738744
if ctor.hasSource then
739745
val cls = ctor.owner.enclosingClass.asClass
740746
val ddef = ctor.defTree.asInstanceOf[DefDef]
741-
given Env = Env(ddef, args.map(_.value).widenArgs)
747+
val env2 = Env(ddef, args.map(_.value).widenArgs)
742748
if ctor.isPrimaryConstructor then
749+
given Env = env2
743750
val tpl = cls.defTree.asInstanceOf[TypeDef].rhs.asInstanceOf[Template]
744751
extendTrace(cls.defTree) { init(tpl, ref, cls) }
745752
else
746-
addParamsAsFields(env, ref, ddef)
753+
addParamsAsFields(env2, ref, ddef)
747754
val initCall = ddef.rhs match
748755
case Block(call :: _, _) => call
749756
case call => call
@@ -756,13 +763,14 @@ object Semantic:
756763
if ctor.hasSource then
757764
val cls = ctor.owner.enclosingClass.asClass
758765
val ddef = ctor.defTree.asInstanceOf[DefDef]
759-
given Env = Env(ddef, args.map(_.value).widenArgs)
766+
val env2 = Env(ddef, args.map(_.value).widenArgs)
760767
if ctor.isPrimaryConstructor then
768+
given Env = env2
761769
val tpl = cls.defTree.asInstanceOf[TypeDef].rhs.asInstanceOf[Template]
762770
extendTrace(cls.defTree) { eval(tpl, ref, cls, cacheResult = true) }
763771
ref
764772
else
765-
addParamsAsFields(env, ref, ddef)
773+
addParamsAsFields(env2, ref, ddef)
766774
extendTrace(ddef) { eval(ddef.rhs, ref, cls, cacheResult = true) }
767775
else if ref.canIgnoreMethodCall(ctor) then
768776
Hot

tests/init/neg/promote-warm.scala

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
class PromoteWarm:
2+
class A:
3+
def foo() = PromoteWarm.this.foo()
4+
5+
class B(a: A):
6+
a.foo()
7+
8+
val a = new A
9+
val b = new B(a) // error
10+
val n = 10
11+
12+
def foo() = println(n)

tests/init/pos/promote-warm.scala

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
class PromoteWarm:
2+
class A:
3+
def foo() = PromoteWarm.this.foo()
4+
5+
class B(a: A):
6+
a.foo()
7+
8+
val n = 10
9+
val a = new A
10+
val b = new B(a)
11+
12+
def foo() = println(n)

0 commit comments

Comments
 (0)