diff --git a/compiler/src/dotty/tools/dotc/Compiler.scala b/compiler/src/dotty/tools/dotc/Compiler.scala index a6555cdcd50e..d31035f83a25 100644 --- a/compiler/src/dotty/tools/dotc/Compiler.scala +++ b/compiler/src/dotty/tools/dotc/Compiler.scala @@ -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 diff --git a/compiler/src/dotty/tools/dotc/transform/RenameLifted.scala b/compiler/src/dotty/tools/dotc/transform/RenameLifted.scala new file mode 100644 index 000000000000..fca24d71b8cf --- /dev/null +++ b/compiler/src/dotty/tools/dotc/transform/RenameLifted.scala @@ -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) + } +} diff --git a/tests/run/i2738.check b/tests/run/i2738.check index 1261ac914586..e4d27e3fc332 100644 --- a/tests/run/i2738.check +++ b/tests/run/i2738.check @@ -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$ diff --git a/tests/run/i2964.check b/tests/run/i2964.check new file mode 100644 index 000000000000..748b2a47faf1 --- /dev/null +++ b/tests/run/i2964.check @@ -0,0 +1,4 @@ +class Foo$$anon$1 +class Bar$$anon$1 +class Bar$$anon$2 +class Baz$$anon$1 diff --git a/tests/run/i2964.scala b/tests/run/i2964.scala new file mode 100644 index 000000000000..8b76c5e05da2 --- /dev/null +++ b/tests/run/i2964.scala @@ -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 + } +} diff --git a/tests/run/i2964b.check b/tests/run/i2964b.check new file mode 100644 index 000000000000..748b2a47faf1 --- /dev/null +++ b/tests/run/i2964b.check @@ -0,0 +1,4 @@ +class Foo$$anon$1 +class Bar$$anon$1 +class Bar$$anon$2 +class Baz$$anon$1 diff --git a/tests/run/i2964b.scala b/tests/run/i2964b.scala new file mode 100644 index 000000000000..26177b85d993 --- /dev/null +++ b/tests/run/i2964b.scala @@ -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 + } +} diff --git a/tests/run/i2964c.check b/tests/run/i2964c.check new file mode 100644 index 000000000000..f7cc0f12df69 --- /dev/null +++ b/tests/run/i2964c.check @@ -0,0 +1,4 @@ +class Foo$Inner$1 +class Bar$Inner$1 +class Bar$Inner$2 +class Baz$Inner$1 diff --git a/tests/run/i2964c.scala b/tests/run/i2964c.scala new file mode 100644 index 000000000000..3683823764c6 --- /dev/null +++ b/tests/run/i2964c.scala @@ -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 + } +} diff --git a/tests/run/i2964d.check b/tests/run/i2964d.check new file mode 100644 index 000000000000..f1a0e8bb51c4 --- /dev/null +++ b/tests/run/i2964d.check @@ -0,0 +1,4 @@ +class Foo$Inner$1$ +class Bar$Inner$1$ +class Bar$Inner$2$ +class Baz$Inner$1$ diff --git a/tests/run/i2964d.scala b/tests/run/i2964d.scala new file mode 100644 index 000000000000..4090bfc084f7 --- /dev/null +++ b/tests/run/i2964d.scala @@ -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 + } +} diff --git a/tests/run/i2964e.check b/tests/run/i2964e.check new file mode 100644 index 000000000000..a42348b97b00 --- /dev/null +++ b/tests/run/i2964e.check @@ -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 diff --git a/tests/run/i2964e.scala b/tests/run/i2964e.scala new file mode 100644 index 000000000000..2c6b0d1d4542 --- /dev/null +++ b/tests/run/i2964e.scala @@ -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 + } +} diff --git a/tests/run/i3000b.check b/tests/run/i3000b.check index 605021c9b2c0..c5980c545f33 100644 --- a/tests/run/i3000b.check +++ b/tests/run/i3000b.check @@ -1,2 +1,2 @@ Foo$$anon$1 -bar.Bar$$anon$2 +bar.Bar$$anon$1 diff --git a/tests/run/i3006.check b/tests/run/i3006.check new file mode 100644 index 000000000000..4fc525c0d632 --- /dev/null +++ b/tests/run/i3006.check @@ -0,0 +1,5 @@ +f$3 +f$2 +f$1 +f$2 +f$1 diff --git a/tests/run/i3006.scala b/tests/run/i3006.scala new file mode 100644 index 000000000000..199fd29194d8 --- /dev/null +++ b/tests/run/i3006.scala @@ -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() + } +} diff --git a/tests/run/i3006b.check b/tests/run/i3006b.check new file mode 100644 index 000000000000..e0e763177e0c --- /dev/null +++ b/tests/run/i3006b.check @@ -0,0 +1,3 @@ +Foo$$init$$$bar$2 +Foo$$init$$$bar$1 +Bar$$init$$$bar$1 diff --git a/tests/run/i3006b.scala b/tests/run/i3006b.scala new file mode 100644 index 000000000000..051a06f266c8 --- /dev/null +++ b/tests/run/i3006b.scala @@ -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() + } +}