From a08f4c183e533aa31ae1e073f4c7b23b1282dc6f Mon Sep 17 00:00:00 2001 From: odersky Date: Sat, 14 Sep 2024 19:48:23 +0200 Subject: [PATCH] Fix treatment of separately compiled @native methods in FirstTransform We need to use a SymTransformer, fixing the method in the tree is not enough. [Cherry-picked 066101a1a748091daa0f1b9fff466fb0276d250b] --- .../src/dotty/tools/dotc/core/Flags.scala | 1 + .../tools/dotc/transform/FirstTransform.scala | 26 +++++++++++-------- tests/pos/i20588/Baz_2.scala | 1 + tests/pos/i20588/Foo_1.scala | 3 +++ 4 files changed, 20 insertions(+), 11 deletions(-) create mode 100644 tests/pos/i20588/Baz_2.scala create mode 100644 tests/pos/i20588/Foo_1.scala diff --git a/compiler/src/dotty/tools/dotc/core/Flags.scala b/compiler/src/dotty/tools/dotc/core/Flags.scala index 56b85d49e7d3..799f0924cda3 100644 --- a/compiler/src/dotty/tools/dotc/core/Flags.scala +++ b/compiler/src/dotty/tools/dotc/core/Flags.scala @@ -568,6 +568,7 @@ object Flags { val ConstructorProxyModule: FlagSet = ConstructorProxy | Module val DefaultParameter: FlagSet = HasDefault | Param // A Scala 2x default parameter val DeferredInline: FlagSet = Deferred | Inline + val DeferredMethod: FlagSet = Deferred | Method val DeferredOrLazy: FlagSet = Deferred | Lazy val DeferredOrLazyOrMethod: FlagSet = Deferred | Lazy | Method val DeferredOrTermParamOrAccessor: FlagSet = Deferred | ParamAccessor | TermParam // term symbols without right-hand sides diff --git a/compiler/src/dotty/tools/dotc/transform/FirstTransform.scala b/compiler/src/dotty/tools/dotc/transform/FirstTransform.scala index b5bc43ee762c..c66e6b9471cb 100644 --- a/compiler/src/dotty/tools/dotc/transform/FirstTransform.scala +++ b/compiler/src/dotty/tools/dotc/transform/FirstTransform.scala @@ -14,6 +14,7 @@ import Decorators.* import scala.collection.mutable import DenotTransformers.* import NameOps.* +import SymDenotations.SymDenotation import NameKinds.OuterSelectName import StdNames.* import config.Feature @@ -35,22 +36,26 @@ object FirstTransform { * if (true) A else B ==> A * if (false) A else B ==> B */ -class FirstTransform extends MiniPhase with InfoTransformer { thisPhase => +class FirstTransform extends MiniPhase with SymTransformer { thisPhase => import ast.tpd.* override def phaseName: String = FirstTransform.name override def description: String = FirstTransform.description - /** eliminate self symbol in ClassInfo */ - override def transformInfo(tp: Type, sym: Symbol)(using Context): Type = tp match { - case tp @ ClassInfo(_, _, _, _, self: Symbol) => - tp.derivedClassInfo(selfInfo = self.info) - case _ => - tp - } - - override protected def infoMayChange(sym: Symbol)(using Context): Boolean = sym.isClass + /** eliminate self symbol in ClassInfo, reset Deferred for @native methods */ + override def transformSym(sym: SymDenotation)(using Context): SymDenotation = + if sym.isClass then + sym.info match + case tp @ ClassInfo(_, _, _, _, self: Symbol) => + val info1 = tp.derivedClassInfo(selfInfo = self.info) + sym.copySymDenotation(info = info1).copyCaches(sym, ctx.phase.next) + case _ => + sym + else if sym.isAllOf(DeferredMethod) && sym.hasAnnotation(defn.NativeAnnot) then + sym.copySymDenotation(initFlags = sym.flags &~ Deferred) + else + sym override def checkPostCondition(tree: Tree)(using Context): Unit = tree match { @@ -121,7 +126,6 @@ class FirstTransform extends MiniPhase with InfoTransformer { thisPhase => override def transformDefDef(ddef: DefDef)(using Context): Tree = val meth = ddef.symbol.asTerm if meth.hasAnnotation(defn.NativeAnnot) then - meth.resetFlag(Deferred) DefDef(meth, _ => ref(defn.Sys_error.termRef).withSpan(ddef.span) .appliedTo(Literal(Constant(s"native method stub")))) diff --git a/tests/pos/i20588/Baz_2.scala b/tests/pos/i20588/Baz_2.scala new file mode 100644 index 000000000000..7dbb038d38da --- /dev/null +++ b/tests/pos/i20588/Baz_2.scala @@ -0,0 +1 @@ +class Baz extends Foo diff --git a/tests/pos/i20588/Foo_1.scala b/tests/pos/i20588/Foo_1.scala new file mode 100644 index 000000000000..1f99cba7ff1c --- /dev/null +++ b/tests/pos/i20588/Foo_1.scala @@ -0,0 +1,3 @@ +class Foo { + @native def test(): Unit +}