Skip to content

Commit 8336a0d

Browse files
committed
Merge pull request #264 from dotty-staging/fix/trait-erasure
Fix erasure of trait info
2 parents 86eb1bb + 8ee6e18 commit 8336a0d

File tree

4 files changed

+41
-24
lines changed

4 files changed

+41
-24
lines changed

src/dotty/tools/dotc/TypeErasure.scala

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,13 @@ class TypeErasure(isJava: Boolean, isSemi: Boolean, isConstructor: Boolean, wild
319319
def eraseTypeRef(p: TypeRef) = this(p).asInstanceOf[TypeRef]
320320
val parents: List[TypeRef] =
321321
if ((cls eq defn.ObjectClass) || cls.isPrimitiveValueClass) Nil
322-
else removeLaterObjects(classParents.mapConserve(eraseTypeRef))
322+
else classParents.mapConserve(eraseTypeRef) match {
323+
case tr :: trs1 =>
324+
assert(!tr.classSymbol.is(Trait), cls)
325+
val tr1 = if (cls is Trait) defn.ObjectClass.typeRef else tr
326+
tr1 :: trs1.filterNot(_ isRef defn.ObjectClass)
327+
case nil => nil
328+
}
323329
val erasedDecls = decls.filteredScope(d => !d.isType || d.isClass)
324330
tp.derivedClassInfo(NoPrefix, parents, erasedDecls, erasedRef(tp.selfType))
325331
// can't replace selftype by NoType because this would lose the sourceModule link
@@ -376,11 +382,6 @@ class TypeErasure(isJava: Boolean, isSemi: Boolean, isConstructor: Boolean, wild
376382
cls
377383
}
378384

379-
private def removeLaterObjects(trs: List[TypeRef])(implicit ctx: Context): List[TypeRef] = trs match {
380-
case tr :: trs1 => tr :: trs1.filterNot(_ isRef defn.ObjectClass)
381-
case nil => nil
382-
}
383-
384385
/** The name of the type as it is used in `Signature`s.
385386
* Need to ensure correspondence with erasure!
386387
*/

src/dotty/tools/dotc/core/Definitions.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ class Definitions {
262262
lazy val ByNameParamClass2x = specialPolyClass(tpnme.BYNAME_PARAM_CLASS, Covariant, AnyType)
263263
lazy val EqualsPatternClass = specialPolyClass(tpnme.EQUALS_PATTERN, EmptyFlags, AnyType)
264264

265-
lazy val RepeatedParamClass = specialPolyClass(tpnme.REPEATED_PARAM_CLASS, Covariant, SeqType)
265+
lazy val RepeatedParamClass = specialPolyClass(tpnme.REPEATED_PARAM_CLASS, Covariant, ObjectType, SeqType)
266266

267267
// fundamental classes
268268
lazy val StringClass = ctx.requiredClass("java.lang.String")

src/dotty/tools/dotc/parsing/Parsers.scala

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1777,23 +1777,23 @@ object Parsers {
17771777
}
17781778
}
17791779

1780-
/** TmplDef ::= ([`case'] `class' | `trait') ClassDef
1780+
/** TmplDef ::= ([`case'] `class' | `trait') ClassDef
17811781
* | [`case'] `object' ObjectDef
17821782
*/
17831783
def tmplDef(start: Int, mods: Modifiers): Tree = in.token match {
17841784
case TRAIT =>
17851785
classDef(posMods(start, mods | Trait))
1786-
case CLASS =>
1787-
classDef(posMods(start, mods))
1788-
case CASECLASS =>
1789-
classDef(posMods(start, mods | Case))
1790-
case OBJECT =>
1791-
objectDef(posMods(start, mods | Module))
1792-
case CASEOBJECT =>
1793-
objectDef(posMods(start, mods | Case | Module))
1794-
case _ =>
1795-
syntaxErrorOrIncomplete("expected start of definition")
1796-
EmptyTree
1786+
case CLASS =>
1787+
classDef(posMods(start, mods))
1788+
case CASECLASS =>
1789+
classDef(posMods(start, mods | Case))
1790+
case OBJECT =>
1791+
objectDef(posMods(start, mods | Module))
1792+
case CASEOBJECT =>
1793+
objectDef(posMods(start, mods | Case | Module))
1794+
case _ =>
1795+
syntaxErrorOrIncomplete("expected start of definition")
1796+
EmptyTree
17971797
}
17981798

17991799
/** ClassDef ::= Id [ClsTypeParamClause]

src/dotty/tools/dotc/transform/Erasure.scala

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,18 @@ object Erasure extends TypeTestsCasts{
293293
else
294294
assignType(untpd.cpy.Select(tree)(qual, tree.name.primitiveArrayOp), qual)
295295

296+
def adaptIfSuper(qual: Tree): Tree = qual match {
297+
case Super(thisQual, tpnme.EMPTY) =>
298+
val SuperType(thisType, supType) = qual.tpe
299+
if (sym.owner is Flags.Trait)
300+
cpy.Super(qual)(thisQual, sym.owner.asClass.name)
301+
.withType(SuperType(thisType, sym.owner.typeRef))
302+
else
303+
qual.withType(SuperType(thisType, thisType.firstParent))
304+
case _ =>
305+
qual
306+
}
307+
296308
def recur(qual: Tree): Tree = {
297309
val qualIsPrimitive = qual.tpe.widen.isPrimitiveValueType
298310
val symIsPrimitive = sym.owner.isPrimitiveValueClass
@@ -306,10 +318,13 @@ object Erasure extends TypeTestsCasts{
306318
recur(unbox(qual, sym.owner.typeRef))
307319
else if (sym.owner eq defn.ArrayClass)
308320
selectArrayMember(qual, erasure(tree.qualifier.typeOpt.widen.finalResultType))
309-
else if (qual.tpe.derivesFrom(sym.owner) || qual.isInstanceOf[Super])
310-
select(qual, sym)
311-
else
312-
recur(cast(qual, sym.owner.typeRef))
321+
else {
322+
val qual1 = adaptIfSuper(qual)
323+
if (qual1.tpe.derivesFrom(sym.owner) || qual1.isInstanceOf[Super])
324+
select(qual1, sym)
325+
else
326+
recur(cast(qual1, sym.owner.typeRef))
327+
}
313328
}
314329

315330
recur(typed(tree.qualifier, AnySelectionProto))
@@ -416,7 +431,8 @@ object Erasure extends TypeTestsCasts{
416431
s"${oldSymbol.name(beforeCtx)} bridging with ${newSymbol.name}")
417432
val newOverridden = oldSymbol.denot.allOverriddenSymbols.toSet // TODO: clarify new <-> old in a comment; symbols are swapped here
418433
val oldOverridden = newSymbol.allOverriddenSymbols(beforeCtx).toSet // TODO: can we find a more efficient impl? newOverridden does not have to be a set!
419-
val neededBridges = oldOverridden -- newOverridden
434+
def stillInBaseClass(sym: Symbol) = ctx.owner derivesFrom sym.owner
435+
val neededBridges = (oldOverridden -- newOverridden).filter(stillInBaseClass)
420436

421437
var minimalSet = Set[Symbol]()
422438
// compute minimal set of bridges that are needed:

0 commit comments

Comments
 (0)