diff --git a/compiler/src/dotty/tools/dotc/core/NameOps.scala b/compiler/src/dotty/tools/dotc/core/NameOps.scala index 3c88917d29c9..98fcf0d9e303 100644 --- a/compiler/src/dotty/tools/dotc/core/NameOps.scala +++ b/compiler/src/dotty/tools/dotc/core/NameOps.scala @@ -146,7 +146,9 @@ object NameOps { /** Revert the expanded name. */ def unexpandedName: N = likeSpacedN { - name.replace { case ExpandedName(_, unexp) => unexp } + name.replaceDeep { + case ExpandedName(_, unexp) => unexp + } } def errorName: N = likeSpacedN(name ++ nme.ERROR) diff --git a/compiler/src/dotty/tools/dotc/core/Names.scala b/compiler/src/dotty/tools/dotc/core/Names.scala index 4cf7d17c17db..f13c3a184bf9 100644 --- a/compiler/src/dotty/tools/dotc/core/Names.scala +++ b/compiler/src/dotty/tools/dotc/core/Names.scala @@ -69,11 +69,18 @@ object Names { /** Apply rewrite rule given by `f` to some part of this name, skipping and rewrapping * other decorators. - * Stops at derived names whose kind has `definesNewName = true`. + * Stops at DerivedNames with infos of kind QualifiedInfo. * If `f` does not apply to any part, return name unchanged. */ def replace(f: PartialFunction[Name, Name]): ThisName + /** Same as replace, but does not stop at DerivedNames with infos of kind QualifiedInfo. */ + def replaceDeep(f: PartialFunction[Name, Name]): ThisName = + replace(f.orElse { + case DerivedName(underlying, info: QualifiedInfo) => + underlying.replaceDeep(f).derived(info) + }) + /** If partial function `f` is defined for some part of this name, apply it * in a Some, otherwise None. * Stops at derived names whose kind has `definesNewName = true`. diff --git a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala index 54ef207759aa..a1752ccc0976 100644 --- a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala @@ -486,11 +486,10 @@ object SymDenotations { def qualify(n: SimpleName) = val qn = kind(prefix.toTermName, if (filler.isEmpty) n else termName(filler + n)) if kind == FlatName && !encl.is(JavaDefined) then qn.compactified else qn - val fn = name replace { - case name: SimpleName => qualify(name) - case name @ AnyQualifiedName(_, _) => qualify(name.toSimpleName) + val fn = name.replaceDeep { + case n: SimpleName => qualify(n) } - if (name.isTypeName) fn.toTypeName else fn.toTermName + if name.isTypeName then fn.toTypeName else fn.toTermName } /** The encoded flat name of this denotation, where joined names are separated by `separator` characters. */ diff --git a/compiler/src/dotty/tools/dotc/transform/Mixin.scala b/compiler/src/dotty/tools/dotc/transform/Mixin.scala index b6aeb7c21511..5ca09dd6188f 100644 --- a/compiler/src/dotty/tools/dotc/transform/Mixin.scala +++ b/compiler/src/dotty/tools/dotc/transform/Mixin.scala @@ -23,7 +23,11 @@ object Mixin { val description: String = "expand trait fields and trait initializers" def traitSetterName(getter: TermSymbol)(using Context): TermName = + extension (name: Name) def qualifiedToSimple = name.replace { + case n @ AnyQualifiedName(_, _) => n.toSimpleName + } getter.ensureNotPrivate.name + .qualifiedToSimple // TODO: Find out why TraitSetterNames can't be defined over QualifiedNames .expandedName(getter.owner, TraitSetterName) .asTermName.syntheticSetterName } diff --git a/tests/run/i15702.check b/tests/run/i15702.check new file mode 100644 index 000000000000..9db2ce96ae1c --- /dev/null +++ b/tests/run/i15702.check @@ -0,0 +1,3 @@ +10 +20 +200 diff --git a/tests/run/i15702.scala b/tests/run/i15702.scala new file mode 100644 index 000000000000..87559219b321 --- /dev/null +++ b/tests/run/i15702.scala @@ -0,0 +1,29 @@ +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 Inner: + println(N.super[A].foo()) + println(N.super.foo()) + println(foo()) + +object C extends A with M with N: + val a = 10 + val b = 10 + val m = 10 + val n = 10 + new Inner() + +@main def Test = C \ No newline at end of file