Skip to content

Commit 8253eb1

Browse files
committed
Fix expansion and unexpansion of mixin qualified names
A mixin qualifier foo$A is a qualified name. Previously these were flattened to SimpleNames when expanding with a trait prefix. But then ResolveSuper cannot decompose the name anymore. To fix this, we now treat QualifiedNames specially in the replace calls for SymDenotations#fullNameSeparated and NameOps#unexpanded. Qualifiers are preserved and the replacement proceeds recursively to their underlying part. For some as yet unknown reason we can't do this for TraitSetterNames. It seems these need to be flattened. Fixes #15702
1 parent 6c7acf9 commit 8253eb1

File tree

5 files changed

+47
-4
lines changed

5 files changed

+47
-4
lines changed

compiler/src/dotty/tools/dotc/core/NameOps.scala

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,10 @@ object NameOps {
146146

147147
/** Revert the expanded name. */
148148
def unexpandedName: N = likeSpacedN {
149-
name.replace { case ExpandedName(_, unexp) => unexp }
149+
name.replace {
150+
case ExpandedName(_, unexp) => unexp
151+
case DerivedName(qual, info: QualifiedInfo) => qual.unexpandedName.derived(info)
152+
}
150153
}
151154

152155
def errorName: N = likeSpacedN(name ++ nme.ERROR)

compiler/src/dotty/tools/dotc/core/Names.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ object Names {
6969

7070
/** Apply rewrite rule given by `f` to some part of this name, skipping and rewrapping
7171
* other decorators.
72-
* Stops at derived names whose kind has `definesNewName = true`.
72+
* Stops at `DerivedName`s with infos of kind `QualifiedInfo`.
7373
* If `f` does not apply to any part, return name unchanged.
7474
*/
7575
def replace(f: PartialFunction[Name, Name]): ThisName

compiler/src/dotty/tools/dotc/core/SymDenotations.scala

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -486,10 +486,18 @@ object SymDenotations {
486486
def qualify(n: SimpleName) =
487487
val qn = kind(prefix.toTermName, if (filler.isEmpty) n else termName(filler + n))
488488
if kind == FlatName && !encl.is(JavaDefined) then qn.compactified else qn
489-
val fn = name replace {
489+
def expand(name: Name): Name = name.replace {
490490
case name: SimpleName => qualify(name)
491-
case name @ AnyQualifiedName(_, _) => qualify(name.toSimpleName)
491+
case name @ DerivedName(qual, info: QualifiedInfo) =>
492+
if kind == TraitSetterName then
493+
qualify(name.toSimpleName)
494+
// TODO: Find out why TraitSetterNames can't be kept as QualifiedNames
495+
else
496+
expand(qual).derived(info)
497+
// In all other cases, keep the qualified name, so that it can be recovered later.
498+
// An example where this matters is run/i15702.scala
492499
}
500+
val fn = expand(name)
493501
if (name.isTypeName) fn.toTypeName else fn.toTermName
494502
}
495503

tests/run/i15702.check

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
10
2+
20
3+
200

tests/run/i15702.scala

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
abstract class A:
2+
val n: Int
3+
def foo(): Int = n
4+
5+
trait B:
6+
val m: Int
7+
def foo(): Int = m
8+
9+
trait M extends A with B:
10+
val a: Int
11+
override def foo(): Int = a + super.foo()
12+
13+
trait N extends A with B:
14+
val b: Int
15+
override def foo(): Int = b * super.foo()
16+
17+
class Inner:
18+
println(N.super[A].foo())
19+
println(N.super.foo())
20+
println(foo())
21+
22+
object C extends A with M with N:
23+
val a = 10
24+
val b = 10
25+
val m = 10
26+
val n = 10
27+
new Inner()
28+
29+
@main def Test = C

0 commit comments

Comments
 (0)