Skip to content

Commit

Permalink
Make eraseInfo work for classes with EmptyScopes
Browse files Browse the repository at this point in the history
  • Loading branch information
odersky committed Jan 27, 2024
1 parent 1716bcd commit 8d9af0c
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 19 deletions.
26 changes: 17 additions & 9 deletions compiler/src/dotty/tools/dotc/core/Scopes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -159,19 +159,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

Expand Down
18 changes: 9 additions & 9 deletions compiler/src/dotty/tools/dotc/core/TypeErasure.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion tests/neg/i19506.scala
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//> using options "-source:3.4-migration",
//> using options -source 3.4-migration

trait Reader[T]
def read[T: Reader](s: String, trace: Boolean = false): T = ???
Expand Down
3 changes: 3 additions & 0 deletions tests/pos/i19530.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
object A {
def x = classOf[scala.Singleton]
}

0 comments on commit 8d9af0c

Please sign in to comment.