Skip to content

Commit d8a788e

Browse files
authored
Merge pull request #11475 from dotty-staging/classParents
Refactor class parents handling
2 parents ce1e2a2 + 1d0c7ed commit d8a788e

16 files changed

+75
-76
lines changed

compiler/src/dotty/tools/dotc/core/SymDenotations.scala

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1539,7 +1539,7 @@ object SymDenotations {
15391539
info2 match {
15401540
case info2: ClassInfo =>
15411541
info1 match {
1542-
case info1: ClassInfo => info1.classParents ne info2.classParents
1542+
case info1: ClassInfo => info1.declaredParents ne info2.declaredParents
15431543
case _ => completersMatter
15441544
}
15451545
case _ => completersMatter
@@ -1730,16 +1730,16 @@ object SymDenotations {
17301730
super.info_=(tp)
17311731
}
17321732

1733-
def classParents(using Context): List[Type] = info match {
1734-
case classInfo: ClassInfo => classInfo.parents
1733+
/** The symbols of the parent classes. */
1734+
def parentSyms(using Context): List[Symbol] = info match {
1735+
case classInfo: ClassInfo => classInfo.declaredParents.map(_.classSymbol)
17351736
case _ => Nil
17361737
}
17371738

17381739
/** The symbol of the superclass, NoSymbol if no superclass exists */
1739-
def superClass(using Context): Symbol = classParents match {
1740+
def superClass(using Context): Symbol = parentSyms match {
17401741
case parent :: _ =>
1741-
val cls = parent.classSymbol
1742-
if (cls.is(Trait)) NoSymbol else cls
1742+
if (parent.is(Trait)) NoSymbol else parent
17431743
case _ =>
17441744
NoSymbol
17451745
}
@@ -1799,19 +1799,20 @@ object SymDenotations {
17991799
def computeBaseData(implicit onBehalf: BaseData, ctx: Context): (List[ClassSymbol], BaseClassSet) = {
18001800
def emptyParentsExpected =
18011801
is(Package) || (symbol == defn.AnyClass) || ctx.erasedTypes && (symbol == defn.ObjectClass)
1802-
if (classParents.isEmpty && !emptyParentsExpected)
1802+
val psyms = parentSyms
1803+
if (psyms.isEmpty && !emptyParentsExpected)
18031804
onBehalf.signalProvisional()
18041805
val builder = new BaseDataBuilder
1805-
def traverse(parents: List[Type]): Unit = parents match {
1806+
def traverse(parents: List[Symbol]): Unit = parents match {
18061807
case p :: parents1 =>
1807-
p.classSymbol match {
1808+
p match {
18081809
case pcls: ClassSymbol => builder.addAll(pcls.baseClasses)
18091810
case _ => assert(isRefinementClass || p.isError || ctx.mode.is(Mode.Interactive), s"$this has non-class parent: $p")
18101811
}
18111812
traverse(parents1)
18121813
case nil =>
18131814
}
1814-
traverse(classParents)
1815+
traverse(psyms)
18151816
(classSymbol :: builder.baseClasses, builder.baseClassSet)
18161817
}
18171818

@@ -1959,7 +1960,7 @@ object SymDenotations {
19591960
denots1
19601961
case nil => denots
19611962
if name.isConstructorName then ownDenots
1962-
else collect(ownDenots, classParents)
1963+
else collect(ownDenots, info.parents)
19631964

19641965
override final def findMember(name: Name, pre: Type, required: FlagSet, excluded: FlagSet)(using Context): Denotation =
19651966
val raw = if excluded.is(Private) then nonPrivateMembersNamed(name) else membersNamed(name)
@@ -2028,7 +2029,7 @@ object SymDenotations {
20282029
else if (isOwnThis)
20292030
if (clsd.baseClassSet.contains(symbol))
20302031
if (symbol.isStatic && symbol.typeParams.isEmpty) symbol.typeRef
2031-
else foldGlb(NoType, clsd.classParents)
2032+
else foldGlb(NoType, clsd.info.parents)
20322033
else NoType
20332034
else
20342035
recur(clsd.typeRef).asSeenFrom(prefix, clsd.owner)
@@ -2134,8 +2135,8 @@ object SymDenotations {
21342135
var names = Set[Name]()
21352136
def maybeAdd(name: Name) = if (keepOnly(thisType, name)) names += name
21362137
try {
2137-
for (p <- classParents if p.classSymbol.isClass)
2138-
for (name <- p.classSymbol.asClass.memberNames(keepOnly))
2138+
for (p <- parentSyms if p.isClass)
2139+
for (name <- p.asClass.memberNames(keepOnly))
21392140
maybeAdd(name)
21402141
val ownSyms =
21412142
if (keepOnly eq implicitFilter)

compiler/src/dotty/tools/dotc/core/Types.scala

Lines changed: 28 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4528,20 +4528,21 @@ object Types {
45284528
type TypeOrSymbol = Type | Symbol
45294529

45304530
/** Roughly: the info of a class during a period.
4531-
* @param prefix The prefix on which parents, decls, and selfType need to be rebased.
4532-
* @param cls The class symbol.
4533-
* @param classParents The parent types of this class.
4534-
* These are all normalized to be TypeRefs by moving any refinements
4535-
* to be member definitions of the class itself.
4536-
* @param decls The symbols defined directly in this class.
4537-
* @param selfInfo The type of `this` in this class, if explicitly given,
4538-
* NoType otherwise. If class is compiled from source, can also
4539-
* be a reference to the self symbol containing the type.
4531+
* @param prefix The prefix on which parents, decls, and selfType need to be rebased.
4532+
* @param cls The class symbol.
4533+
* @param declaredParents The parent types of this class.
4534+
* These are all normalized to be TypeRefs by moving any refinements
4535+
* to be member definitions of the class itself.
4536+
* Unlike `parents`, the types are not seen as seen from `prefix`.
4537+
* @param decls The symbols defined directly in this class.
4538+
* @param selfInfo The type of `this` in this class, if explicitly given,
4539+
* NoType otherwise. If class is compiled from source, can also
4540+
* be a reference to the self symbol containing the type.
45404541
*/
45414542
abstract case class ClassInfo(
45424543
prefix: Type,
45434544
cls: ClassSymbol,
4544-
classParents: List[Type],
4545+
declaredParents: List[Type],
45454546
decls: Scope,
45464547
selfInfo: TypeOrSymbol) extends CachedGroundType with TypeType {
45474548

@@ -4577,20 +4578,20 @@ object Types {
45774578

45784579
override def parents(using Context): List[Type] = {
45794580
if (parentsCache == null)
4580-
parentsCache = classParents.mapConserve(_.asSeenFrom(prefix, cls.owner))
4581+
parentsCache = declaredParents.mapConserve(_.asSeenFrom(prefix, cls.owner))
45814582
parentsCache
45824583
}
45834584

4584-
protected def newLikeThis(prefix: Type, classParents: List[Type], decls: Scope, selfInfo: TypeOrSymbol)(using Context): ClassInfo =
4585-
ClassInfo(prefix, cls, classParents, decls, selfInfo)
4585+
protected def newLikeThis(prefix: Type, declaredParents: List[Type], decls: Scope, selfInfo: TypeOrSymbol)(using Context): ClassInfo =
4586+
ClassInfo(prefix, cls, declaredParents, decls, selfInfo)
45864587

45874588
def derivedClassInfo(prefix: Type)(using Context): ClassInfo =
45884589
if (prefix eq this.prefix) this
4589-
else newLikeThis(prefix, classParents, decls, selfInfo)
4590+
else newLikeThis(prefix, declaredParents, decls, selfInfo)
45904591

4591-
def derivedClassInfo(prefix: Type = this.prefix, classParents: List[Type] = this.classParents, decls: Scope = this.decls, selfInfo: TypeOrSymbol = this.selfInfo)(using Context): ClassInfo =
4592-
if ((prefix eq this.prefix) && (classParents eq this.classParents) && (decls eq this.decls) && (selfInfo eq this.selfInfo)) this
4593-
else newLikeThis(prefix, classParents, decls, selfInfo)
4592+
def derivedClassInfo(prefix: Type = this.prefix, declaredParents: List[Type] = this.declaredParents, decls: Scope = this.decls, selfInfo: TypeOrSymbol = this.selfInfo)(using Context): ClassInfo =
4593+
if ((prefix eq this.prefix) && (declaredParents eq this.declaredParents) && (decls eq this.decls) && (selfInfo eq this.selfInfo)) this
4594+
else newLikeThis(prefix, declaredParents, decls, selfInfo)
45944595

45954596
/** If this class has opaque type alias members, a new class info
45964597
* with their aliases added as refinements to the self type of the class.
@@ -4626,13 +4627,13 @@ object Types {
46264627
}
46274628

46284629
override def computeHash(bs: Binders): Int = doHash(bs, cls, prefix)
4629-
override def hashIsStable: Boolean = prefix.hashIsStable && classParents.hashIsStable
4630+
override def hashIsStable: Boolean = prefix.hashIsStable && declaredParents.hashIsStable
46304631

46314632
override def eql(that: Type): Boolean = that match {
46324633
case that: ClassInfo =>
46334634
prefix.eq(that.prefix) &&
46344635
cls.eq(that.cls) &&
4635-
classParents.eqElements(that.classParents) &&
4636+
declaredParents.eqElements(that.declaredParents) &&
46364637
decls.eq(that.decls) &&
46374638
selfInfo.eq(that.selfInfo)
46384639
case _ => false
@@ -4644,17 +4645,17 @@ object Types {
46444645
case that: ClassInfo =>
46454646
prefix.equals(that.prefix, bs) &&
46464647
cls.eq(that.cls) &&
4647-
classParents.equalElements(that.classParents, bs) &&
4648+
declaredParents.equalElements(that.declaredParents, bs) &&
46484649
decls.eq(that.decls) &&
46494650
selfInfo.eq(that.selfInfo)
46504651
case _ => false
46514652
}
46524653

4653-
override def toString: String = s"ClassInfo($prefix, $cls, $classParents)"
4654+
override def toString: String = s"ClassInfo($prefix, $cls, $declaredParents)"
46544655
}
46554656

4656-
class CachedClassInfo(prefix: Type, cls: ClassSymbol, classParents: List[Type], decls: Scope, selfInfo: TypeOrSymbol)
4657-
extends ClassInfo(prefix, cls, classParents, decls, selfInfo)
4657+
class CachedClassInfo(prefix: Type, cls: ClassSymbol, declaredParents: List[Type], decls: Scope, selfInfo: TypeOrSymbol)
4658+
extends ClassInfo(prefix, cls, declaredParents, decls, selfInfo)
46584659

46594660
/** A class for temporary class infos where `parents` are not yet known */
46604661
final class TempClassInfo(prefix: Type, cls: ClassSymbol, decls: Scope, selfInfo: TypeOrSymbol)
@@ -4664,15 +4665,15 @@ object Types {
46644665
def finalized(parents: List[Type])(using Context): ClassInfo =
46654666
ClassInfo(prefix, cls, parents, decls, selfInfo)
46664667

4667-
override def newLikeThis(prefix: Type, classParents: List[Type], decls: Scope, selfInfo: TypeOrSymbol)(using Context): ClassInfo =
4668+
override def newLikeThis(prefix: Type, declaredParents: List[Type], decls: Scope, selfInfo: TypeOrSymbol)(using Context): ClassInfo =
46684669
TempClassInfo(prefix, cls, decls, selfInfo)
46694670

46704671
override def toString: String = s"TempClassInfo($prefix, $cls)"
46714672
}
46724673

46734674
object ClassInfo {
4674-
def apply(prefix: Type, cls: ClassSymbol, classParents: List[Type], decls: Scope, selfInfo: TypeOrSymbol = NoType)(using Context): ClassInfo =
4675-
unique(new CachedClassInfo(prefix, cls, classParents, decls, selfInfo))
4675+
def apply(prefix: Type, cls: ClassSymbol, declaredParents: List[Type], decls: Scope, selfInfo: TypeOrSymbol = NoType)(using Context): ClassInfo =
4676+
unique(new CachedClassInfo(prefix, cls, declaredParents, decls, selfInfo))
46764677
}
46774678

46784679
/** Type bounds >: lo <: hi */
@@ -5276,7 +5277,7 @@ object Types {
52765277
protected def mapFullClassInfo(tp: ClassInfo): ClassInfo =
52775278
tp.derivedClassInfo(
52785279
prefix = this(tp.prefix),
5279-
classParents = tp.classParents.mapConserve(this),
5280+
declaredParents = tp.declaredParents.mapConserve(this),
52805281
selfInfo = tp.selfInfo match {
52815282
case tp: Type => this(tp)
52825283
case sym => sym

compiler/src/dotty/tools/dotc/quoted/PickledQuotes.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ object PickledQuotes {
140140
class ReplaceSplicedTyped extends TypeMap() {
141141
override def apply(tp: Type): Type = tp match {
142142
case tp: ClassInfo =>
143-
tp.derivedClassInfo(classParents = tp.classParents.map(apply))
143+
tp.derivedClassInfo(declaredParents = tp.declaredParents.map(apply))
144144
case tp: TypeRef =>
145145
typeSpliceMap.get(tp.symbol) match
146146
case Some(t) if tp.typeSymbol.hasAnnotation(defn.QuotedRuntime_SplicedTypeAnnot) => mapOver(t)

compiler/src/dotty/tools/dotc/quoted/reflect/FromSymbol.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ object FromSymbol {
3131
newSymbol(cls, nme.CONSTRUCTOR, EmptyFlags, NoType)
3232
)
3333
val constr = tpd.DefDef(constrSym.asTerm)
34-
val parents = cls.classParents.map(tpd.TypeTree(_))
34+
val parents = cls.info.parents.map(tpd.TypeTree(_))
3535
val body = cls.unforcedDecls.filter(!_.isPrimaryConstructor).map(s => definitionFromSym(s))
3636
tpd.ClassDefWithParents(cls, constr, parents, body)
3737
}

compiler/src/dotty/tools/dotc/transform/CheckReentrant.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,8 @@ class CheckReentrant extends MiniPhase {
7373
scanning(sym) {
7474
sym.info.widenExpr.classSymbols.foreach(addVars)
7575
}
76-
for (parent <- cls.classInfo.classParents)
77-
addVars(parent.classSymbol.asClass)
76+
for (parent <- cls.parentSyms)
77+
addVars(parent.asClass)
7878
}
7979
}
8080

compiler/src/dotty/tools/dotc/transform/ElimPolyFunction.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,13 @@ class ElimPolyFunction extends MiniPhase with DenotTransformer {
3232
case ref: ClassDenotation if ref.symbol != defn.PolyFunctionClass && ref.derivesFrom(defn.PolyFunctionClass) =>
3333
val cinfo = ref.classInfo
3434
val newParent = functionTypeOfPoly(cinfo)
35-
val newParents = cinfo.classParents.map(parent =>
35+
val newParents = cinfo.declaredParents.map(parent =>
3636
if (parent.typeSymbol == defn.PolyFunctionClass)
3737
newParent
3838
else
3939
parent
4040
)
41-
ref.copySymDenotation(info = cinfo.derivedClassInfo(classParents = newParents))
41+
ref.copySymDenotation(info = cinfo.derivedClassInfo(declaredParents = newParents))
4242
case _ =>
4343
ref
4444
}

compiler/src/dotty/tools/dotc/transform/PickleQuotes.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,7 @@ class PickleQuotes extends MacroTransform {
455455
apply(tp.dealias)
456456
case tp @ TypeRef(pre, _) if pre == NoPrefix || pre.termSymbol.isLocal =>
457457
val hiBound = tp.typeSymbol.info match
458-
case info @ ClassInfo(_, _, classParents, _, _) => classParents.reduce(_ & _)
458+
case info: ClassInfo => info.parents.reduce(_ & _)
459459
case info => info.hiBound
460460
apply(hiBound)
461461
case tp =>

compiler/src/dotty/tools/dotc/transform/SyntheticMembers.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
9292
lazy val accessors =
9393
if (isDerivedValueClass(clazz)) clazz.paramAccessors.take(1) // Tail parameters can only be `erased`
9494
else clazz.caseAccessors
95-
val isEnumValue = clazz.isAnonymousClass && clazz.classParents.head.classSymbol.is(Enum)
95+
val isEnumValue = clazz.isAnonymousClass && clazz.info.parents.head.classSymbol.is(Enum)
9696
val isSimpleEnumValue = isEnumValue && !clazz.owner.isAllOf(EnumCase)
9797
val isJavaEnumValue = isEnumValue && clazz.derivesFrom(defn.JavaEnumClass)
9898
val isNonJavaEnumValue = isEnumValue && !isJavaEnumValue
@@ -428,7 +428,7 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
428428

429429
/** Is this an anonymous class deriving from an enum definition? */
430430
extension (cls: ClassSymbol) private def isEnumValueImplementation(using Context): Boolean =
431-
cls.isAnonymousClass && cls.classParents.head.typeSymbol.is(Enum) // asserted in Typer
431+
cls.isAnonymousClass && cls.info.parents.head.typeSymbol.is(Enum) // asserted in Typer
432432

433433
/** If this is the class backing a serializable singleton enum value with base class `MyEnum`,
434434
* and not deriving from `java.lang.Enum` add the method:
@@ -546,7 +546,7 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
546546
newParents = newParents :+ TypeTree(parent)
547547
val oldClassInfo = clazz.classInfo
548548
val newClassInfo = oldClassInfo.derivedClassInfo(
549-
classParents = oldClassInfo.classParents :+ parent)
549+
declaredParents = oldClassInfo.declaredParents :+ parent)
550550
clazz.copySymDenotation(info = newClassInfo).installAfter(thisPhase)
551551
}
552552
def addMethod(name: TermName, info: Type, cls: Symbol, body: (Symbol, Tree) => Context ?=> Tree): Unit = {

compiler/src/dotty/tools/dotc/transform/init/Summarization.scala

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -335,16 +335,13 @@ object Summarization {
335335
}
336336

337337
if (cls.defTree.isEmpty)
338-
cls.info match {
339-
case cinfo: ClassInfo =>
340-
val source = {
341-
implicit val ctx2: Context = theCtx.withSource(cls.source(using theCtx))
342-
TypeTree(cls.typeRef).withSpan(cls.span)
343-
}
338+
val source = {
339+
implicit val ctx2: Context = theCtx.withSource(cls.source(using theCtx))
340+
TypeTree(cls.typeRef).withSpan(cls.span)
341+
}
344342

345-
val parentOuter = cinfo.classParents.map { extractParentOuters(_, source) }.toMap
346-
ClassSummary(cls, parentOuter)
347-
}
343+
val parentOuter = cls.info.parents.map { extractParentOuters(_, source) }.toMap
344+
ClassSummary(cls, parentOuter)
348345
else {
349346
val tpl = cls.defTree.asInstanceOf[TypeDef]
350347
val parents = tpl.rhs.asInstanceOf[Template].parents

compiler/src/dotty/tools/dotc/transform/sjs/PrepJSInterop.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ class PrepJSInterop extends MacroTransform with IdentityDenotTransformer { thisP
291291

292292
/** Performs checks and rewrites specific to classes / objects extending `js.Any`. */
293293
private def transformJSClassDef(classDef: TypeDef)(using Context): Tree = {
294-
val sym = classDef.symbol
294+
val sym = classDef.symbol.asClass
295295
val isJSNative = sym.hasAnnotation(jsdefn.JSNativeAnnot)
296296

297297
sym.addAnnotation(jsdefn.JSTypeAnnot)
@@ -315,8 +315,8 @@ class PrepJSInterop extends MacroTransform with IdentityDenotTransformer { thisP
315315
}
316316

317317
// Check the parents
318-
for (parent <- sym.info.parents) {
319-
parent.typeSymbol match {
318+
for (parentSym <- sym.parentSyms) {
319+
parentSym match {
320320
case parentSym if parentSym == defn.ObjectClass =>
321321
// AnyRef is valid, except for non-native JS classes and objects
322322
if (!isJSNative && !sym.is(Trait)) {

compiler/src/dotty/tools/dotc/typer/Checking.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -576,8 +576,8 @@ object Checking {
576576
}
577577
tp.derivedClassInfo(
578578
prefix = apply(tp.prefix),
579-
classParents =
580-
tp.parents.map(p => transformedParent(apply(p)))
579+
declaredParents =
580+
tp.declaredParents.map(p => transformedParent(apply(p)))
581581
)
582582
case _ =>
583583
mapOver(tp)
@@ -1180,7 +1180,7 @@ trait Checking {
11801180
report.error(i"enum case does not extend its enum $enumCls", enumCase.srcPos)
11811181
cls.info match
11821182
case info: ClassInfo =>
1183-
cls.info = info.derivedClassInfo(classParents = enumCls.typeRefApplied :: info.classParents)
1183+
cls.info = info.derivedClassInfo(declaredParents = enumCls.typeRefApplied :: info.declaredParents)
11841184
case _ =>
11851185

11861186
val enumCase =

compiler/src/dotty/tools/dotc/typer/Namer.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -774,7 +774,7 @@ class Namer { typer: Typer =>
774774
alt != denot.symbol && alt.info.matchesLoosely(denot.info))
775775

776776
def inheritsConcreteMember =
777-
denot.owner.asClass.classParents.exists(parent =>
777+
denot.owner.asClass.info.parents.exists(parent =>
778778
parent.member(denot.name).hasAltWith(sd =>
779779
!sd.symbol.is(Deferred) && sd.matches(denot)))
780780

@@ -809,7 +809,7 @@ class Namer { typer: Typer =>
809809

810810
if denot.isClass && !sym.isEnumAnonymClass && !sym.isRefinementClass then
811811
val child = if (denot.is(Module)) denot.sourceModule else denot.symbol
812-
denot.asClass.classParents.foreach { parent => register(child, parent.classSymbol.asClass) }
812+
denot.info.parents.foreach { parent => register(child, parent.classSymbol.asClass) }
813813
else if denot.is(CaseVal, butNot = Method | Module) then
814814
assert(denot.is(Enum), denot)
815815
denot.info.classSymbols.foreach { parent => register(denot.symbol, parent) }

compiler/src/dotty/tools/dotc/typer/RefChecks.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,14 +104,14 @@ object RefChecks {
104104
report.error(DoesNotConformToSelfType(category, cinfo.selfType, cls, otherSelf, relation, other),
105105
cls.srcPos)
106106
}
107-
val parents = cinfo.classParents
108-
for (parent <- parents)
109-
checkSelfConforms(parent.classSymbol.asClass, "illegal inheritance", "parent")
107+
val psyms = cls.asClass.parentSyms
108+
for (psym <- psyms)
109+
checkSelfConforms(psym.asClass, "illegal inheritance", "parent")
110110
for (reqd <- cinfo.cls.givenSelfType.classSymbols)
111111
checkSelfConforms(reqd, "missing requirement", "required")
112112

113113
def isClassExtendingJavaEnum =
114-
!cls.isOneOf(Enum | Trait) && parents.exists(_.classSymbol == defn.JavaEnumClass)
114+
!cls.isOneOf(Enum | Trait) && psyms.contains(defn.JavaEnumClass)
115115

116116
// Prevent wrong `extends` of java.lang.Enum
117117
if isClassExtendingJavaEnum then

0 commit comments

Comments
 (0)