From 90b0c78e3b29279c95793af46ef9606dd10ebd0a Mon Sep 17 00:00:00 2001 From: Fengyun Liu Date: Mon, 18 Jul 2022 11:18:15 +0200 Subject: [PATCH 1/3] Handle SuperAccessorName --- .../tools/dotc/transform/init/Semantic.scala | 24 ++++--------- tests/init/neg/super-resolution.check | 36 +++++++++++++++++++ tests/init/neg/super-resolution.scala | 23 ++++++++++++ 3 files changed, 66 insertions(+), 17 deletions(-) create mode 100644 tests/init/neg/super-resolution.check create mode 100644 tests/init/neg/super-resolution.scala diff --git a/compiler/src/dotty/tools/dotc/transform/init/Semantic.scala b/compiler/src/dotty/tools/dotc/transform/init/Semantic.scala index 4765066d571f..2f456c387e62 100644 --- a/compiler/src/dotty/tools/dotc/transform/init/Semantic.scala +++ b/compiler/src/dotty/tools/dotc/transform/init/Semantic.scala @@ -8,6 +8,8 @@ import Symbols.* import Types.* import StdNames.* import NameKinds.OuterSelectName +import NameKinds.SuperAccessorName +import NameOps.unexpandedName import ast.tpd.* import config.Printers.init as printer @@ -788,7 +790,9 @@ object Semantic: if !needResolve then meth else if superType.exists then - resolveSuper(ref.klass, superType, meth) + meth + else if meth.name.is(SuperAccessorName) then + ResolveSuper.rebindSuper(ref.klass, meth) else resolve(ref.klass, meth) @@ -829,7 +833,7 @@ object Semantic: value.select(target, receiver, needResolve = false) else if ref.klass.isSubClass(receiver.widenSingleton.classSymbol) then - report.error("Unexpected resolution failure: ref.klass = " + ref.klass.show + ", meth = " + meth.show + Trace.show, Trace.position) + report.error("[Internal error] Unexpected resolution failure: ref.klass = " + ref.klass.show + ", meth = " + meth.show + Trace.show, Trace.position) Hot else // This is possible due to incorrect type cast. @@ -1175,9 +1179,8 @@ object Semantic: // Note that a parameterized trait may only get parameters from the class that extends the trait. // A trait may not supply constructor arguments to another trait. if !klass.is(Flags.Trait) then - for parent <- klass.parentSyms if parent.hasSource do doPromote(parent.asClass, klass, isHotSegment) - // We still need to handle indirectly extended traits via traits, which are not in the parent list. val superCls = klass.superClass + if superCls.hasSource then doPromote(superCls.asClass, klass, isHotSegment) val mixins = klass.baseClasses.tail.takeWhile(_ != superCls) for mixin <- mixins if mixin.hasSource do doPromote(mixin.asClass, klass, isHotSegment) end doPromote @@ -1768,16 +1771,3 @@ object Semantic: if (sym.isEffectivelyFinal || sym.isConstructor) sym else sym.matchingMember(cls.appliedRef) } - - def resolveSuper(cls: ClassSymbol, superType: Type, sym: Symbol)(using Context): Symbol = - import annotation.tailrec - @tailrec def loop(bcs: List[ClassSymbol]): Symbol = bcs match { - case bc :: bcs1 => - val cand = sym.matchingDecl(bcs.head, cls.thisType) - .suchThat(alt => !alt.is(Flags.Deferred)).symbol - if (cand.exists) cand else loop(bcs.tail) - case _ => - NoSymbol - } - loop(cls.info.baseClasses.dropWhile(sym.owner != _)) - diff --git a/tests/init/neg/super-resolution.check b/tests/init/neg/super-resolution.check new file mode 100644 index 000000000000..d5fdd2a3e59e --- /dev/null +++ b/tests/init/neg/super-resolution.check @@ -0,0 +1,36 @@ +-- Error: tests/init/neg/super-resolution.scala:21:6 ------------------------------------------------------------------- +21 | val m = 30 // error + | ^ + | Access non-initialized value m. Calling trace: + | -> class C extends A with M with N: [ super-resolution.scala:17 ] + | ^ + | -> foo() [ super-resolution.scala:18 ] + | ^^^^^ + | -> override def foo(): Int = b * super.foo() [ super-resolution.scala:15 ] + | ^^^^^^^^^^^ + | -> override def foo(): Int = a + super.foo() [ super-resolution.scala:11 ] + | ^^^^^^^^^^^ + | -> def foo(): Int = m [ super-resolution.scala:7 ] + | ^ +-- Error: tests/init/neg/super-resolution.scala:19:6 ------------------------------------------------------------------- +19 | val a = 10 // error + | ^ + | Access non-initialized value a. Calling trace: + | -> class C extends A with M with N: [ super-resolution.scala:17 ] + | ^ + | -> foo() [ super-resolution.scala:18 ] + | ^^^^^ + | -> override def foo(): Int = b * super.foo() [ super-resolution.scala:15 ] + | ^^^^^^^^^^^ + | -> override def foo(): Int = a + super.foo() [ super-resolution.scala:11 ] + | ^ +-- Error: tests/init/neg/super-resolution.scala:20:6 ------------------------------------------------------------------- +20 | val b = 20 // error + | ^ + | Access non-initialized value b. Calling trace: + | -> class C extends A with M with N: [ super-resolution.scala:17 ] + | ^ + | -> foo() [ super-resolution.scala:18 ] + | ^^^^^ + | -> override def foo(): Int = b * super.foo() [ super-resolution.scala:15 ] + | ^ diff --git a/tests/init/neg/super-resolution.scala b/tests/init/neg/super-resolution.scala new file mode 100644 index 000000000000..d2674bc597e1 --- /dev/null +++ b/tests/init/neg/super-resolution.scala @@ -0,0 +1,23 @@ +abstract class A: + val n: Int + def foo(): Int = n + +trait B: + val m: Int + def foo(): Int = m + +trait M extends A with B: + val a: Int + override def foo(): Int = a + super.foo() + +trait N extends A with B: + val b: Int + override def foo(): Int = b * super.foo() + +class C extends A with M with N: + foo() + val a = 10 // error + val b = 20 // error + val m = 30 // error + val n = 40 + From a6822525901808d4dae84c296403450354750e24 Mon Sep 17 00:00:00 2001 From: Fengyun Liu Date: Mon, 18 Jul 2022 12:06:05 +0200 Subject: [PATCH 2/3] Add test --- tests/init/neg/super-resolution2.check | 28 ++++++++++++++++++++++++++ tests/init/neg/super-resolution2.scala | 19 +++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 tests/init/neg/super-resolution2.check create mode 100644 tests/init/neg/super-resolution2.scala diff --git a/tests/init/neg/super-resolution2.check b/tests/init/neg/super-resolution2.check new file mode 100644 index 000000000000..f852c519e922 --- /dev/null +++ b/tests/init/neg/super-resolution2.check @@ -0,0 +1,28 @@ +-- Error: tests/init/neg/super-resolution2.scala:19:6 ------------------------------------------------------------------ +19 | val n = 40 // error + | ^ + | Access non-initialized value n. Calling trace: + | -> class N extends A with B: [ super-resolution2.scala:9 ] + | ^ + | -> new Inner [ super-resolution2.scala:16 ] + | ^^^^^^^^^ + | -> class Inner: [ super-resolution2.scala:12 ] + | ^ + | -> N.super[A].foo() [ super-resolution2.scala:13 ] + | ^^^^^^^^^^^^^^^^ + | -> def foo(): Int = n [ super-resolution2.scala:3 ] + | ^ +-- Error: tests/init/neg/super-resolution2.scala:18:6 ------------------------------------------------------------------ +18 | val m = 30 // error + | ^ + | Access non-initialized value m. Calling trace: + | -> class N extends A with B: [ super-resolution2.scala:9 ] + | ^ + | -> new Inner [ super-resolution2.scala:16 ] + | ^^^^^^^^^ + | -> class Inner: [ super-resolution2.scala:12 ] + | ^ + | -> N.super.foo() [ super-resolution2.scala:14 ] + | ^^^^^^^^^^^^^ + | -> def foo(): Int = m [ super-resolution2.scala:7 ] + | ^ diff --git a/tests/init/neg/super-resolution2.scala b/tests/init/neg/super-resolution2.scala new file mode 100644 index 000000000000..879798e01058 --- /dev/null +++ b/tests/init/neg/super-resolution2.scala @@ -0,0 +1,19 @@ +abstract class A: + val n: Int + def foo(): Int = n + +trait B: + val m: Int + def foo(): Int = m + +class N extends A with B: + override def foo(): Int = 10 * super.foo() + + class Inner: + N.super[A].foo() + N.super.foo() + + new Inner + + val m = 30 // error + val n = 40 // error From f98b23b882d0149c0ca3be3e6b62dc500f290e29 Mon Sep 17 00:00:00 2001 From: Fengyun Liu Date: Tue, 19 Jul 2022 20:57:49 +0200 Subject: [PATCH 3/3] Address review --- compiler/src/dotty/tools/dotc/transform/init/Semantic.scala | 1 - tests/init/neg/super-resolution2.scala | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/init/Semantic.scala b/compiler/src/dotty/tools/dotc/transform/init/Semantic.scala index 2f456c387e62..f9dbea1f4c1d 100644 --- a/compiler/src/dotty/tools/dotc/transform/init/Semantic.scala +++ b/compiler/src/dotty/tools/dotc/transform/init/Semantic.scala @@ -9,7 +9,6 @@ import Types.* import StdNames.* import NameKinds.OuterSelectName import NameKinds.SuperAccessorName -import NameOps.unexpandedName import ast.tpd.* import config.Printers.init as printer diff --git a/tests/init/neg/super-resolution2.scala b/tests/init/neg/super-resolution2.scala index 879798e01058..283fb25a467d 100644 --- a/tests/init/neg/super-resolution2.scala +++ b/tests/init/neg/super-resolution2.scala @@ -7,7 +7,7 @@ trait B: def foo(): Int = m class N extends A with B: - override def foo(): Int = 10 * super.foo() + override def foo(): Int = a * super.foo() class Inner: N.super[A].foo() @@ -17,3 +17,4 @@ class N extends A with B: val m = 30 // error val n = 40 // error + val a = 50