From f9d1ab8e7dc9e575f9f3f3057f3b1ebfe3b221a3 Mon Sep 17 00:00:00 2001 From: Wojciech Mazur Date: Fri, 28 Jun 2024 18:24:17 +0200 Subject: [PATCH 1/5] Make eraseInfo work for classes with EmptyScopes Fixes #19506 [Cherry-picked 8d9af0cd6778f10ca85ef2e80d29ee018ac6f8cb][modified] --- .../src/dotty/tools/dotc/core/Scopes.scala | 26 ++++++++++++------- .../dotty/tools/dotc/core/TypeErasure.scala | 18 ++++++------- tests/pos/i19530.scala | 3 +++ 3 files changed, 29 insertions(+), 18 deletions(-) create mode 100644 tests/pos/i19530.scala diff --git a/compiler/src/dotty/tools/dotc/core/Scopes.scala b/compiler/src/dotty/tools/dotc/core/Scopes.scala index a5c6ee94338e..138098f2ce3b 100644 --- a/compiler/src/dotty/tools/dotc/core/Scopes.scala +++ b/compiler/src/dotty/tools/dotc/core/Scopes.scala @@ -158,19 +158,27 @@ object Scopes { } /** The scope that keeps only those symbols from this scope that match the - * given predicates. If all symbols match, returns the scope itself, otherwise - * a copy with the matching symbols. + * given predicates, renamed with the given rename function. + * If all symbols match and none are renamed, returns the scope itself, otherwise + * a copy with the matching and renamed symbols. */ - final def filteredScope(p: Symbol => Boolean)(using Context): Scope = { + final def filteredScope( + keep: Symbol => Boolean, + rename: (Symbol, Name) => Name = (_, name) => name)(using Context): Scope = var result: MutableScope | Null = null - for (sym <- iterator) - if (!p(sym)) { - if (result == null) result = cloneScope + for sym <- iterator do + def drop() = + if result == null then result = cloneScope result.nn.unlink(sym) - } + if keep(sym) then + val newName = rename(sym, sym.name) + if newName ne sym.name then + drop() + result.nn.enter(newName, sym) + else + drop() // TODO: improve flow typing to handle this case - if (result == null) this else result.uncheckedNN - } + if result == null then this else result.uncheckedNN def implicitDecls(using Context): List[TermRef] = Nil diff --git a/compiler/src/dotty/tools/dotc/core/TypeErasure.scala b/compiler/src/dotty/tools/dotc/core/TypeErasure.scala index c24375ebdf5a..924fdf851cd4 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeErasure.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeErasure.scala @@ -725,14 +725,13 @@ class TypeErasure(sourceLanguage: SourceLanguage, semiEraseVCs: Boolean, isConst tr1 :: trs1.filterNot(_.isAnyRef) case nil => nil } - var erasedDecls = decls.filteredScope(sym => !sym.isType || sym.isClass).openForMutations - for dcl <- erasedDecls.iterator do - if dcl.lastKnownDenotation.unforcedAnnotation(defn.TargetNameAnnot).isDefined - && dcl.targetName != dcl.name - then - if erasedDecls eq decls then erasedDecls = erasedDecls.cloneScope - erasedDecls.unlink(dcl) - erasedDecls.enter(dcl.targetName, dcl) + val erasedDecls = decls.filteredScope( + keep = sym => !sym.isType || sym.isClass, + rename = (sym, name) => + if sym.lastKnownDenotation.unforcedAnnotation(defn.TargetNameAnnot).isDefined + then sym.targetName + else name + ) val selfType1 = if cls.is(Module) then cls.sourceModule.termRef else NoType tp.derivedClassInfo(NoPrefix, erasedParents, erasedDecls, selfType1) // can't replace selftype by NoType because this would lose the sourceModule link @@ -814,7 +813,8 @@ class TypeErasure(sourceLanguage: SourceLanguage, semiEraseVCs: Boolean, isConst eraseResult(tp1.resultType) match case rt: MethodType => rt case rt => MethodType(Nil, Nil, rt) - case tp1 => this(tp1) + case tp1 => + this(tp1) private def eraseDerivedValueClass(tp: Type)(using Context): Type = { val cls = tp.classSymbol.asClass diff --git a/tests/pos/i19530.scala b/tests/pos/i19530.scala new file mode 100644 index 000000000000..01c3cc50a12d --- /dev/null +++ b/tests/pos/i19530.scala @@ -0,0 +1,3 @@ +object A { + def x = classOf[scala.Singleton] +} \ No newline at end of file From 0e4fc333828f26fe4a840eaeef230ee812dc35cd Mon Sep 17 00:00:00 2001 From: odersky Date: Sun, 28 Jan 2024 20:29:46 +0100 Subject: [PATCH 2/5] Update compiler/src/dotty/tools/dotc/core/Scopes.scala [Cherry-picked 7fd99b689506f42d0ee34f9093d211e504b4afee] --- compiler/src/dotty/tools/dotc/core/Scopes.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/core/Scopes.scala b/compiler/src/dotty/tools/dotc/core/Scopes.scala index 138098f2ce3b..a08cc8161099 100644 --- a/compiler/src/dotty/tools/dotc/core/Scopes.scala +++ b/compiler/src/dotty/tools/dotc/core/Scopes.scala @@ -172,7 +172,7 @@ object Scopes { result.nn.unlink(sym) if keep(sym) then val newName = rename(sym, sym.name) - if newName ne sym.name then + if newName != sym.name then drop() result.nn.enter(newName, sym) else From 9564161ee9a8ca78d96e1cdbfc5b4f48a5163a53 Mon Sep 17 00:00:00 2001 From: noti0na1 Date: Mon, 29 Jan 2024 14:34:53 +0100 Subject: [PATCH 3/5] Do not use the name of a symbol when not needed. [Cherry-picked cb1d50fd2c1bbbfabb94ac362a66625ff3f40507] --- compiler/src/dotty/tools/dotc/core/Scopes.scala | 6 +++--- compiler/src/dotty/tools/dotc/core/TypeErasure.scala | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Scopes.scala b/compiler/src/dotty/tools/dotc/core/Scopes.scala index a08cc8161099..0be9547218b2 100644 --- a/compiler/src/dotty/tools/dotc/core/Scopes.scala +++ b/compiler/src/dotty/tools/dotc/core/Scopes.scala @@ -164,15 +164,15 @@ object Scopes { */ final def filteredScope( keep: Symbol => Boolean, - rename: (Symbol, Name) => Name = (_, name) => name)(using Context): Scope = + rename: Symbol => Name | Null = _ => null)(using Context): Scope = var result: MutableScope | Null = null for sym <- iterator do def drop() = if result == null then result = cloneScope result.nn.unlink(sym) if keep(sym) then - val newName = rename(sym, sym.name) - if newName != sym.name then + val newName = rename(sym) + if newName != null then drop() result.nn.enter(newName, sym) else diff --git a/compiler/src/dotty/tools/dotc/core/TypeErasure.scala b/compiler/src/dotty/tools/dotc/core/TypeErasure.scala index 924fdf851cd4..65f95ee3c107 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeErasure.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeErasure.scala @@ -727,10 +727,10 @@ class TypeErasure(sourceLanguage: SourceLanguage, semiEraseVCs: Boolean, isConst } val erasedDecls = decls.filteredScope( keep = sym => !sym.isType || sym.isClass, - rename = (sym, name) => + rename = sym => if sym.lastKnownDenotation.unforcedAnnotation(defn.TargetNameAnnot).isDefined then sym.targetName - else name + else null ) val selfType1 = if cls.is(Module) then cls.sourceModule.termRef else NoType tp.derivedClassInfo(NoPrefix, erasedParents, erasedDecls, selfType1) From 989cf1bf3f3db3e695efdd80a7841b252bed7277 Mon Sep 17 00:00:00 2001 From: noti0na1 Date: Mon, 29 Jan 2024 16:23:49 +0100 Subject: [PATCH 4/5] Add a missing condition back. [Cherry-picked 64319eb19b0be91835bde14f5081cc078a9437bf] --- compiler/src/dotty/tools/dotc/core/TypeErasure.scala | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/src/dotty/tools/dotc/core/TypeErasure.scala b/compiler/src/dotty/tools/dotc/core/TypeErasure.scala index 65f95ee3c107..1b08f0b42348 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeErasure.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeErasure.scala @@ -729,6 +729,7 @@ class TypeErasure(sourceLanguage: SourceLanguage, semiEraseVCs: Boolean, isConst keep = sym => !sym.isType || sym.isClass, rename = sym => if sym.lastKnownDenotation.unforcedAnnotation(defn.TargetNameAnnot).isDefined + && sym.targetName != sym.name then sym.targetName else null ) From 2c8480d84c8cacd24d86afff0ac85c3c4d34574f Mon Sep 17 00:00:00 2001 From: noti0na1 Date: Mon, 29 Jan 2024 16:29:24 +0100 Subject: [PATCH 5/5] Add a comment for the default value of the rename function. [Cherry-picked b23da16699b389abd8059d78466b13e35192419e] --- compiler/src/dotty/tools/dotc/core/Scopes.scala | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/src/dotty/tools/dotc/core/Scopes.scala b/compiler/src/dotty/tools/dotc/core/Scopes.scala index 0be9547218b2..17e737777d1c 100644 --- a/compiler/src/dotty/tools/dotc/core/Scopes.scala +++ b/compiler/src/dotty/tools/dotc/core/Scopes.scala @@ -159,6 +159,7 @@ object Scopes { /** The scope that keeps only those symbols from this scope that match the * given predicates, renamed with the given rename function. + * If renaming is not needed for a symbol, the rename function should return `null`. * If all symbols match and none are renamed, returns the scope itself, otherwise * a copy with the matching and renamed symbols. */