Skip to content

Fix #2964: Refresh names for anonymous classes #2999

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Sep 5, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion compiler/src/dotty/tools/dotc/Compiler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ class Compiler {
new ElimStaticThis, // Replace `this` references to static objects by global identifiers
new Flatten, // Lift all inner classes to package scope
new RestoreScopes), // Repair scopes rendered invalid by moving definitions in prior phases of the group
List(new TransformWildcards, // Replace wildcards with default values
List(new RenameLifted, // Renames lifted classes to local numbering scheme
new TransformWildcards, // Replace wildcards with default values
new MoveStatics, // Move static methods to companion classes
new ExpandPrivate, // Widen private definitions accessed from nested classes
new SelectStatic, // get rid of selects that would be compiled into GetStatic
Expand Down
46 changes: 46 additions & 0 deletions compiler/src/dotty/tools/dotc/transform/RenameLifted.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package dotty.tools.dotc.transform

import dotty.tools.dotc.core.Contexts.Context
import dotty.tools.dotc.core.Decorators._
import dotty.tools.dotc.core.DenotTransformers.SymTransformer
import dotty.tools.dotc.core.Flags._
import dotty.tools.dotc.core.NameKinds._
import dotty.tools.dotc.core.Names._
import dotty.tools.dotc.core.Phases
import dotty.tools.dotc.core.SymDenotations.SymDenotation
import dotty.tools.dotc.core.Symbols._
import dotty.tools.dotc.transform.TreeTransforms.MiniPhaseTransform

/** Renames lifted classes to local numbering scheme */
class RenameLifted extends MiniPhaseTransform with SymTransformer { thisTransformer =>

override def phaseName = "renameLifted"

override def runsAfterGroupsOf: Set[Class[_ <: Phases.Phase]] = Set(classOf[RestoreScopes])

def transformSym(ref: SymDenotation)(implicit ctx: Context): SymDenotation =
if (needsRefresh(ref.symbol)) ref.copySymDenotation(name = refreshedName(ref.symbol))
else ref

/** If the name of the symbol with a unique name needs to be refreshed
* - if it is a lifted class
* - if it is a lifted method
*/
private def needsRefresh(sym: Symbol)(implicit ctx: Context): Boolean =
(sym.isClass || sym.is(Private | Method | JavaStatic)) && sym.name.is(UniqueName)

/** Refreshes the number of the name based on the full name of the symbol */
private def refreshedName(sym: Symbol)(implicit ctx: Context): Name = {
def rewriteUnique: PartialFunction[Name, Name] = {
case name: DerivedName if name.info.kind == UniqueName =>
val fullName = (sym.owner.fullName.toString + name.underlying).toTermName
val freshName = UniqueName.fresh(fullName)
val info = freshName.asInstanceOf[DerivedName].info
DerivedName(name.underlying.rewrite(rewriteUnique), info)
case DerivedName(underlying, info: QualifiedInfo) =>
underlying.rewrite(rewriteUnique).derived(info)
}

sym.name.rewrite(rewriteUnique)
}
}
8 changes: 4 additions & 4 deletions tests/run/i2738.check
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
foo
bar$1
foo
bar$2
foo
bar$1
baz
Test$qux$2$
Test$qux$1$
baz
Test$qux$4$
Test$qux$2$
4 changes: 4 additions & 0 deletions tests/run/i2964.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
class Foo$$anon$1
class Bar$$anon$1
class Bar$$anon$2
class Baz$$anon$1
27 changes: 27 additions & 0 deletions tests/run/i2964.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@

object Test {
def main(args: Array[String]): Unit = {
new Foo
new Bar
new Baz
}
}

class Foo {
new Object {
println(this.getClass) // Foo$$anon$1
}
}
class Bar {
new Object {
println(this.getClass) // Bar$$anon$1
}
new Object {
println(this.getClass) // Bar$$anon$2
}
}
class Baz {
new Object {
println(this.getClass) // Baz$$anon$1
}
}
4 changes: 4 additions & 0 deletions tests/run/i2964b.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
class Foo$$anon$1
class Bar$$anon$1
class Bar$$anon$2
class Baz$$anon$1
27 changes: 27 additions & 0 deletions tests/run/i2964b.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@

object Test {
def main(args: Array[String]): Unit = {
Foo
Bar
Baz
}
}

object Foo {
new Object {
println(this.getClass) // Foo$$anon$1
}
}
object Bar {
new Object {
println(this.getClass) // Bar$$anon$1
}
new Object {
println(this.getClass) // Bar$$anon$2
}
}
object Baz {
new Object {
println(this.getClass) // Baz$$anon$1
}
}
4 changes: 4 additions & 0 deletions tests/run/i2964c.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
class Foo$Inner$1
class Bar$Inner$1
class Bar$Inner$2
class Baz$Inner$1
41 changes: 41 additions & 0 deletions tests/run/i2964c.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@

object Test {
def main(args: Array[String]): Unit = {
new Foo().foo
new Bar().bar
new Bar().bar2
new Baz().baz
}
}

class Foo {
def foo: Unit = {
class Inner {
println(this.getClass)
}
new Inner
}
}
class Bar {
def bar: Unit = {
class Inner {
println(this.getClass)
}
new Inner
}

def bar2: Unit = {
class Inner {
println(this.getClass)
}
new Inner
}
}
class Baz {
def baz: Unit = {
class Inner {
println(this.getClass)
}
new Inner
}
}
4 changes: 4 additions & 0 deletions tests/run/i2964d.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
class Foo$Inner$1$
class Bar$Inner$1$
class Bar$Inner$2$
class Baz$Inner$1$
41 changes: 41 additions & 0 deletions tests/run/i2964d.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@

object Test {
def main(args: Array[String]): Unit = {
new Foo().foo
new Bar().bar
new Bar().bar2
new Baz().baz
}
}

class Foo {
def foo: Unit = {
object Inner {
println(this.getClass)
}
Inner
}
}
class Bar {
def bar: Unit = {
object Inner {
println(this.getClass)
}
Inner
}

def bar2: Unit = {
object Inner {
println(this.getClass)
}
Inner
}
}
class Baz {
def baz: Unit = {
object Inner {
println(this.getClass)
}
Inner
}
}
4 changes: 4 additions & 0 deletions tests/run/i2964e.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
class foo.bar.Foo$$anon$1
class foo.bar.Foo$$anon$2
class foo.Foo$$anon$1
class Foo$$anon$1
32 changes: 32 additions & 0 deletions tests/run/i2964e.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@

object Test {
def main(args: Array[String]): Unit = {
new foo.bar.Foo
new foo.Foo
new Foo
}
}

package foo {
package bar {
class Foo {
new Object {
println(this.getClass) // Foo$$anon$1
}
new Object {
println(this.getClass) // Foo$$anon$2
}
}
}
class Foo {
new Object {
println(this.getClass) // Foo$$anon$1
}
}
}

class Foo {
new Object {
println(this.getClass) // Foo$$anon$1
}
}
2 changes: 1 addition & 1 deletion tests/run/i3000b.check
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
Foo$$anon$1
bar.Bar$$anon$2
bar.Bar$$anon$1
5 changes: 5 additions & 0 deletions tests/run/i3006.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
f$3
f$2
f$1
f$2
f$1
35 changes: 35 additions & 0 deletions tests/run/i3006.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
class Foo {
def foo() = {
def f() = println(Thread.currentThread.getStackTrace.apply(1).getMethodName)
f()
}
def bar() = {
def f() = println(Thread.currentThread.getStackTrace.apply(1).getMethodName)
f()
}
def baz() = {
def f() = println(Thread.currentThread.getStackTrace.apply(1).getMethodName)
f()
}
}

class Bar {
def foo() = {
def f() = println(Thread.currentThread.getStackTrace.apply(1).getMethodName)
f()
}
def bar() = {
def f() = println(Thread.currentThread.getStackTrace.apply(1).getMethodName)
f()
}
}

object Test {
def main(args: Array[String]): Unit = {
new Foo().foo()
new Foo().bar()
new Foo().baz()
new Bar().foo()
new Bar().bar()
}
}
3 changes: 3 additions & 0 deletions tests/run/i3006b.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Foo$$init$$$bar$2
Foo$$init$$$bar$1
Bar$$init$$$bar$1
35 changes: 35 additions & 0 deletions tests/run/i3006b.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
class Foo(i: Int) {
def this() = this({
def bar() = {
println(Thread.currentThread.getStackTrace.apply(1).getMethodName)
5
}
bar()
})

def this(i: String) = this({
def bar() = {
println(Thread.currentThread.getStackTrace.apply(1).getMethodName)
5
}
bar()
})
}

class Bar(i: Int) {
def this() = this({
def bar() = {
println(Thread.currentThread.getStackTrace.apply(1).getMethodName)
5
}
bar()
})
}

object Test {
def main(args: Array[String]): Unit = {
new Foo()
new Foo("")
new Bar()
}
}