Skip to content

Commit

Permalink
Fix expansion and unexpansion of mixin qualified names
Browse files Browse the repository at this point in the history
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
  • Loading branch information
odersky committed Jul 20, 2022
1 parent 6c7acf9 commit 8253eb1
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 4 deletions.
5 changes: 4 additions & 1 deletion compiler/src/dotty/tools/dotc/core/NameOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,10 @@ object NameOps {

/** Revert the expanded name. */
def unexpandedName: N = likeSpacedN {
name.replace { case ExpandedName(_, unexp) => unexp }
name.replace {
case ExpandedName(_, unexp) => unexp
case DerivedName(qual, info: QualifiedInfo) => qual.unexpandedName.derived(info)
}
}

def errorName: N = likeSpacedN(name ++ nme.ERROR)
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/core/Names.scala
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ 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 `DerivedName`s with infos of kind `QualifiedInfo`.
* If `f` does not apply to any part, return name unchanged.
*/
def replace(f: PartialFunction[Name, Name]): ThisName
Expand Down
12 changes: 10 additions & 2 deletions compiler/src/dotty/tools/dotc/core/SymDenotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -486,10 +486,18 @@ 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 {
def expand(name: Name): Name = name.replace {
case name: SimpleName => qualify(name)
case name @ AnyQualifiedName(_, _) => qualify(name.toSimpleName)
case name @ DerivedName(qual, info: QualifiedInfo) =>
if kind == TraitSetterName then
qualify(name.toSimpleName)
// TODO: Find out why TraitSetterNames can't be kept as QualifiedNames
else
expand(qual).derived(info)
// In all other cases, keep the qualified name, so that it can be recovered later.
// An example where this matters is run/i15702.scala
}
val fn = expand(name)
if (name.isTypeName) fn.toTypeName else fn.toTermName
}

Expand Down
3 changes: 3 additions & 0 deletions tests/run/i15702.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
10
20
200
29 changes: 29 additions & 0 deletions tests/run/i15702.scala
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 8253eb1

Please sign in to comment.