diff --git a/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala b/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala index 297f7e0f8934..aacee60668ff 100644 --- a/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala +++ b/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala @@ -889,7 +889,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma // to inner symbols of DefDef // todo: somehow handle. - def parents: List[Type] = tp.parents + def parents: List[Type] = tp.parentsNEW } diff --git a/compiler/src/dotty/tools/dotc/ast/tpd.scala b/compiler/src/dotty/tools/dotc/ast/tpd.scala index 016db8e2c01b..4ee30af5ede1 100644 --- a/compiler/src/dotty/tools/dotc/ast/tpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/tpd.scala @@ -213,7 +213,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { ta.assignType(untpd.TypeDef(sym.name, TypeTree(sym.info)), sym) def ClassDef(cls: ClassSymbol, constr: DefDef, body: List[Tree], superArgs: List[Tree] = Nil)(implicit ctx: Context): TypeDef = { - val firstParentRef :: otherParentRefs = cls.info.parents + val firstParentRef :: otherParentRefs = cls.info.parentRefs val firstParent = cls.typeRef.baseTypeWithArgs(firstParentRef.symbol) val superRef = if (cls is Trait) TypeTree(firstParent) @@ -261,7 +261,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { def AnonClass(parents: List[Type], fns: List[TermSymbol], methNames: List[TermName])(implicit ctx: Context): Block = { val owner = fns.head.owner val parents1 = - if (parents.head.classSymbol.is(Trait)) parents.head.parents.head :: parents + if (parents.head.classSymbol.is(Trait)) parents.head.parentRefs.head :: parents else parents val cls = ctx.newNormalizedClassSymbol(owner, tpnme.ANON_FUN, Synthetic, parents1, coord = fns.map(_.pos).reduceLeft(_ union _)) diff --git a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala index bfaa12729090..54d7d41d3206 100644 --- a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala @@ -699,7 +699,7 @@ object SymDenotations { | is not a subclass of ${owner.showLocated} where target is defined""") else if ( !( isType // allow accesses to types from arbitrary subclasses fixes #4737 - || pre.baseTypeRef(cls).exists // ??? why not use derivesFrom ??? + || pre.derivesFrom(cls) || isConstructor || (owner is ModuleClass) // don't perform this check for static members )) @@ -1266,10 +1266,10 @@ object SymDenotations { private[this] var myMemberCache: LRUCache[Name, PreDenotation] = null private[this] var myMemberCachePeriod: Period = Nowhere - /** A cache from types T to baseTypeRef(T, C) */ - type BaseTypeRefMap = java.util.HashMap[CachedType, Type] - private[this] var myBaseTypeRefCache: BaseTypeRefMap = null - private[this] var myBaseTypeRefCachePeriod: Period = Nowhere + /** A cache from types T to baseType(T, C) */ + type BaseTypeMap = java.util.HashMap[CachedType, Type] + private[this] var myBaseTypeCache: BaseTypeMap = null + private[this] var myBaseTypeCachePeriod: Period = Nowhere private var baseDataCache: BaseData = BaseData.None private var memberNamesCache: MemberNames = MemberNames.None @@ -1282,14 +1282,14 @@ object SymDenotations { myMemberCache } - private def baseTypeRefCache(implicit ctx: Context): BaseTypeRefMap = { - if (myBaseTypeRefCachePeriod != ctx.period && - (myBaseTypeRefCachePeriod.runId != ctx.runId || - ctx.phases(myBaseTypeRefCachePeriod.phaseId).sameParentsStartId != ctx.phase.sameParentsStartId)) { - myBaseTypeRefCache = new BaseTypeRefMap - myBaseTypeRefCachePeriod = ctx.period + private def baseTypeCache(implicit ctx: Context): BaseTypeMap = { + if (myBaseTypeCachePeriod != ctx.period && + (myBaseTypeCachePeriod.runId != ctx.runId || + ctx.phases(myBaseTypeCachePeriod.phaseId).sameParentsStartId != ctx.phase.sameParentsStartId)) { + myBaseTypeCache = new BaseTypeMap + myBaseTypeCachePeriod = ctx.period } - myBaseTypeRefCache + myBaseTypeCache } private def invalidateBaseDataCache() = { @@ -1302,9 +1302,9 @@ object SymDenotations { memberNamesCache = MemberNames.None } - def invalidateBaseTypeRefCache() = { - myBaseTypeRefCache = null - myBaseTypeRefCachePeriod = Nowhere + def invalidateBaseTypeCache() = { + myBaseTypeCache = null + myBaseTypeCachePeriod = Nowhere } override def copyCaches(from: SymDenotation, phase: Phase)(implicit ctx: Context): this.type = { @@ -1313,7 +1313,7 @@ object SymDenotations { if (from.memberNamesCache.isValidAt(phase)) memberNamesCache = from.memberNamesCache if (from.baseDataCache.isValidAt(phase)) { baseDataCache = from.baseDataCache - myBaseTypeRefCache = from.baseTypeRefCache + myBaseTypeCache = from.baseTypeCache } case _ => } @@ -1379,6 +1379,14 @@ object SymDenotations { NoSymbol } + /** The explicitly given self type (self types of modules are assumed to be + * explcitly given here). + */ + def givenSelfType(implicit ctx: Context) = classInfo.selfInfo match { + case tp: Type => tp + case self: Symbol => self.info + } + // ------ class-specific operations ----------------------------------- private[this] var myThisType: Type = null @@ -1581,11 +1589,11 @@ object SymDenotations { raw.filterExcluded(excluded).asSeenFrom(pre).toDenot(pre) } - /** Compute tp.baseTypeRef(this) */ - final def baseTypeRefOf(tp: Type)(implicit ctx: Context): Type = { + /** Compute tp.baseType(this) */ + final def baseTypeOf(tp: Type)(implicit ctx: Context): Type = { def foldGlb(bt: Type, ps: List[Type]): Type = ps match { - case p :: ps1 => foldGlb(bt & baseTypeRefOf(p), ps1) + case p :: ps1 => foldGlb(bt & baseTypeOf(p), ps1) case _ => bt } @@ -1597,7 +1605,7 @@ object SymDenotations { * and this changes subtyping relations. As a shortcut, we do not * cache ErasedValueType at all. */ - def isCachable(tp: Type, btrCache: BaseTypeRefMap): Boolean = { + def isCachable(tp: Type, btrCache: BaseTypeMap): Boolean = { def inCache(tp: Type) = btrCache.containsKey(tp) tp match { case _: TypeErasure.ErasedValueType => false @@ -1609,28 +1617,28 @@ object SymDenotations { } } - def computeBaseTypeRefOf(tp: Type): Type = { + def computeBaseTypeOf(tp: Type): Type = { Stats.record("computeBaseTypeOf") - if (symbol.isStatic && tp.derivesFrom(symbol)) + if (symbol.isStatic && tp.derivesFrom(symbol) && symbol.typeParams.isEmpty) symbol.typeRef else tp match { - case tp: TypeRef => + case tp: RefType => val subcls = tp.symbol if (subcls eq symbol) tp else subcls.denot match { case cdenot: ClassDenotation => - if (cdenot.baseClassSet contains symbol) foldGlb(NoType, tp.parents) + if (cdenot.baseClassSet contains symbol) foldGlb(NoType, tp.parentsNEW) // !!! change to parents else NoType case _ => - baseTypeRefOf(tp.superType) + baseTypeOf(tp.superType) } case tp: TypeProxy => - baseTypeRefOf(tp.superType) + baseTypeOf(tp.superType) case AndType(tp1, tp2) => - baseTypeRefOf(tp1) & baseTypeRefOf(tp2) + baseTypeOf(tp1) & baseTypeOf(tp2) case OrType(tp1, tp2) => - baseTypeRefOf(tp1) | baseTypeRefOf(tp2) + baseTypeOf(tp1) | baseTypeOf(tp2) case JavaArrayType(_) if symbol == defn.ObjectClass => this.typeRef case _ => @@ -1638,16 +1646,16 @@ object SymDenotations { } } - /*>|>*/ ctx.debugTraceIndented(s"$tp.baseTypeRef($this)") /*<|<*/ { + /*>|>*/ ctx.debugTraceIndented(s"$tp.baseType($this)") /*<|<*/ { tp match { case tp: CachedType => - val btrCache = baseTypeRefCache + val btrCache = baseTypeCache try { var basetp = btrCache get tp if (basetp == null) { btrCache.put(tp, NoPrefix) - basetp = computeBaseTypeRefOf(tp) - if (isCachable(tp, baseTypeRefCache)) btrCache.put(tp, basetp) + basetp = computeBaseTypeOf(tp) + if (isCachable(tp, baseTypeCache)) btrCache.put(tp, basetp) else btrCache.remove(tp) } else if (basetp == NoPrefix) throw CyclicReference(this) @@ -1659,7 +1667,7 @@ object SymDenotations { throw ex } case _ => - computeBaseTypeRefOf(tp) + computeBaseTypeOf(tp) } } } diff --git a/compiler/src/dotty/tools/dotc/core/TypeApplications.scala b/compiler/src/dotty/tools/dotc/core/TypeApplications.scala index fb2300ff1829..c12eaed6a0b0 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeApplications.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeApplications.scala @@ -76,7 +76,7 @@ object TypeApplications { } def unapply(tp: Type)(implicit ctx: Context): Option[TypeRef] = tp match { - case tp @ HKTypeLambda(tparams, AppliedType(fn: TypeRef, args)) if (args == tparams.map(_.toArg)) => Some(fn) + case tp @ HKTypeLambda(tparams, AnyAppliedType(fn: TypeRef, args)) if (args == tparams.map(_.toArg)) => Some(fn) case _ => None } } @@ -87,7 +87,7 @@ object TypeApplications { * * where v_i, p_i are the variances and names of the type parameters of T. */ - object AppliedType { + object AnyAppliedType { def apply(tp: Type, args: List[Type])(implicit ctx: Context): Type = tp.appliedTo(args) def unapply(tp: Type)(implicit ctx: Context): Option[(Type, List[Type])] = tp match { @@ -111,6 +111,8 @@ object TypeApplications { None } collectArgs(tycon.typeParams, refinements, new mutable.ListBuffer[Type]) + case AppliedType(tycon, args) => + Some((tycon, args)) case HKApply(tycon, args) => Some((tycon, args)) case _ => @@ -408,7 +410,7 @@ class TypeApplications(val self: Type) extends AnyVal { if (!args.exists(_.isInstanceOf[TypeBounds])) { val followAlias = Config.simplifyApplications && { dealiased.resType match { - case AppliedType(tyconBody, dealiasedArgs) => + case AnyAppliedType(tyconBody, dealiasedArgs) => // Reduction should not affect type inference when it's // just eta-reduction (ignoring variance annotations). // See i2201*.scala for examples where more aggressive @@ -421,7 +423,7 @@ class TypeApplications(val self: Type) extends AnyVal { else HKApply(self, args) } else dealiased.resType match { - case AppliedType(tycon, args1) if tycon.safeDealias ne tycon => + case AnyAppliedType(tycon, args1) if tycon.safeDealias ne tycon => // In this case we should always dealias since we cannot handle // higher-kinded applications to wildcard arguments. dealiased @@ -521,7 +523,7 @@ class TypeApplications(val self: Type) extends AnyVal { * Existential types in arguments are returned as TypeBounds instances. */ final def baseTypeWithArgs(base: Symbol)(implicit ctx: Context): Type = ctx.traceIndented(s"btwa ${self.show} wrt $base", core, show = true) { - def default = self.baseTypeRef(base).appliedTo(baseArgInfos(base)) + def default = self.baseTypeTycon(base).appliedTo(baseArgInfos(base)) def isExpandedTypeParam(sym: Symbol) = sym.is(TypeParam) && sym.name.is(ExpandedName) self match { case tp: TypeRef => @@ -573,7 +575,7 @@ class TypeApplications(val self: Type) extends AnyVal { * Existential types in arguments are returned as TypeBounds instances. */ final def argInfos(implicit ctx: Context): List[Type] = self match { - case AppliedType(tycon, args) => args + case AnyAppliedType(tycon, args) => args case _ => Nil } diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index 4e911eed5bf4..80bf3be04aad 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -368,7 +368,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { case _ => val cls2 = tp2.symbol if (cls2.isClass) { - val base = tp1.baseTypeRef(cls2) + val base = tp1.baseType(cls2) if (base.exists && (base ne tp1)) return isSubType(base, tp2) if (cls2 == defn.SingletonClass && tp1.isStable) return true } @@ -713,7 +713,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { def liftToBase(bcs: List[ClassSymbol]): Boolean = bcs match { case bc :: bcs1 => classBounds.exists(bc.derivesFrom) && - tyconOK(tp1w.baseTypeRef(bc), tp1w.baseArgInfos(bc)) || + tyconOK(tp1w.baseTypeTycon(bc), tp1w.baseArgInfos(bc)) || liftToBase(bcs1) case _ => false @@ -771,7 +771,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { tycon1 match { case param1: TypeParamRef => def canInstantiate = tp2 match { - case AppliedType(tycon2, args2) => + case AnyAppliedType(tycon2, args2) => tryInstantiate(param1, tycon2.ensureHK) && isSubArgs(args1, args2, tycon2.typeParams) case _ => false @@ -810,7 +810,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { val classBounds = tp2.classSymbols def recur(bcs: List[ClassSymbol]): Boolean = bcs match { case bc :: bcs1 => - val baseRef = tp1.baseTypeRef(bc) + val baseRef = tp1.baseTypeTycon(bc) (classBounds.exists(bc.derivesFrom) && variancesConform(baseRef.typeParams, tparams) && p(baseRef.appliedTo(tp1.baseArgInfos(bc))) diff --git a/compiler/src/dotty/tools/dotc/core/TypeOps.scala b/compiler/src/dotty/tools/dotc/core/TypeOps.scala index 829b5acec00c..73f57131646f 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeOps.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeOps.scala @@ -66,7 +66,7 @@ trait TypeOps { this: Context => // TODO: Make standalone object. else pre match { case pre: SuperType => toPrefix(pre.thistpe, cls, thiscls) case _ => - if (thiscls.derivesFrom(cls) && pre.baseTypeRef(thiscls).exists) { + if (thiscls.derivesFrom(cls) && pre.baseType(thiscls).exists) { // ??? why not derivesFrom ??? if (theMap != null && theMap.currentVariance <= 0 && !isLegalPrefix(pre)) { ctx.base.unsafeNonvariant = ctx.runId pre match { @@ -79,7 +79,7 @@ trait TypeOps { this: Context => // TODO: Make standalone object. else if ((pre.termSymbol is Package) && !(thiscls is Package)) toPrefix(pre.select(nme.PACKAGE), cls, thiscls) else - toPrefix(pre.baseTypeRef(cls).normalizedPrefix, cls.owner, thiscls) + toPrefix(pre.baseType(cls).normalizedPrefix, cls.owner, thiscls) } } @@ -256,7 +256,7 @@ trait TypeOps { this: Context => // TODO: Make standalone object. val doms = dominators(commonBaseClasses, Nil) def baseTp(cls: ClassSymbol): Type = { val base = - if (tp1.typeParams.nonEmpty) tp.baseTypeRef(cls) + if (tp1.typeParams.nonEmpty) tp.baseTypeTycon(cls) else tp.baseTypeWithArgs(cls) base.mapReduceOr(identity)(mergeRefined) } diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 40fbc80f85f0..683ae0a0d08f 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -129,9 +129,10 @@ object Types { case TypeAlias(tp) => assert((tp ne this) && (tp ne this1), s"$tp / $this") tp.isRef(sym) - case _ => this1.symbol eq sym + case _ => this1.symbol eq sym } case this1: RefinedOrRecType => this1.parent.isRef(sym) + case this1: AppliedType => this1.underlying.isRef(sym) case this1: HKApply => this1.superType.isRef(sym) case _ => false } @@ -210,7 +211,7 @@ object Types { */ private final def phantomLatticeType(implicit ctx: Context): Type = widen match { case tp: ClassInfo if defn.isPhantomTerminalClass(tp.classSymbol) => tp.prefix - case tp: TypeProxy if tp.superType ne this => tp.underlying.phantomLatticeType + case tp: TypeProxy if tp.superType ne this => tp.underlying.phantomLatticeType // ??? guard needed ??? case tp: AndOrType => tp.tp1.phantomLatticeType case _ => NoType } @@ -483,6 +484,8 @@ object Types { }) case tp: TypeRef => tp.denot.findMember(name, pre, excluded) + case tp: AppliedType => + goApplied(tp) case tp: ThisType => goThis(tp) case tp: RefinedType => @@ -494,7 +497,7 @@ object Types { case tp: SuperType => goSuper(tp) case tp: HKApply => - goApply(tp) + goHKApply(tp) case tp: TypeProxy => go(tp.underlying) case tp: ClassInfo => @@ -566,6 +569,7 @@ object Types { try pdenot.info & rinfo catch { case ex: CyclicReference => + // ??? can this still happen? ??? // happens for tests/pos/sets.scala. findMember is called from baseTypeRef. // The & causes a subtype check which calls baseTypeRef again with the same // superclass. In the observed case, the superclass was Any, and @@ -583,7 +587,15 @@ object Types { } } - def goApply(tp: HKApply) = tp.tycon match { + def goApplied(tp: AppliedType) = tp.tycon match { + case tl: HKTypeLambda => + go(tl.resType).mapInfo(info => + tl.derivedLambdaAbstraction(tl.paramNames, tl.paramInfos, info).appliedTo(tp.args)) + case _ => + go(tp.superType) + } + + def goHKApply(tp: HKApply) = tp.tycon match { case tl: HKTypeLambda => go(tl.resType).mapInfo(info => tl.derivedLambdaAbstraction(tl.paramNames, tl.paramInfos, info).appliedTo(tp.args)) @@ -826,13 +838,17 @@ object Types { /** The basetype TypeRef of this type with given class symbol, * but without including any type arguments */ - final def baseTypeRef(base: Symbol)(implicit ctx: Context): Type = /*ctx.traceIndented(s"$this baseTypeRef $base")*/ /*>|>*/ track("baseTypeRef") /*<|<*/ { + final def baseType(base: Symbol)(implicit ctx: Context): Type = /*ctx.traceIndented(s"$this baseType $base")*/ /*>|>*/ track("baseType") /*<|<*/ { base.denot match { - case classd: ClassDenotation => classd.baseTypeRefOf(this) + case classd: ClassDenotation => classd.baseTypeOf(this) case _ => NoType } } + /** Temporary replacement for baseTypeRef */ + final def baseTypeTycon(base: Symbol)(implicit ctx: Context): Type = + baseType(base).typeConstructor + def & (that: Type)(implicit ctx: Context): Type = track("&") { ctx.typeComparer.glb(this, that) } @@ -958,6 +974,14 @@ object Types { case TypeAlias(tp) => tp.dealias(keepAnnots): @tailrec case _ => tp } + case app @ AppliedType(tycon, args) => + val tycon1 = tycon.dealias(keepAnnots) + if (tycon1 ne tycon) app.superType.dealias(keepAnnots): @tailrec + else this + case app @ HKApply(tycon, args) => + val tycon1 = tycon.dealias(keepAnnots) + if (tycon1 ne tycon) app.superType.dealias(keepAnnots): @tailrec + else this case tp: TypeVar => val tp1 = tp.instanceOpt if (tp1.exists) tp1.dealias(keepAnnots): @tailrec else tp @@ -966,10 +990,6 @@ object Types { if (keepAnnots) tp.derivedAnnotatedType(tp1, tp.annot) else tp1 case tp: LazyRef => tp.ref.dealias(keepAnnots): @tailrec - case app @ HKApply(tycon, args) => - val tycon1 = tycon.dealias(keepAnnots) - if (tycon1 ne tycon) app.superType.dealias(keepAnnots): @tailrec - else this case _ => this } @@ -1001,6 +1021,12 @@ object Types { case _ => this } + /** The type constructor of an applied type, otherwise the type itself */ + final def typeConstructor(implicit ctx: Context): Type = this match { + case AppliedType(tycon, _) => tycon + case _ => this + } + /** If this is a (possibly aliased, annotated, and/or parameterized) reference to * a class, the class type ref, otherwise NoType. * @param refinementOK If `true` we also skip non-parameter refinements. @@ -1010,6 +1036,8 @@ object Types { if (tp.symbol.isClass) tp else if (tp.symbol.isAliasType) tp.underlying.underlyingClassRef(refinementOK) else NoType + case tp: AppliedType => + tp.superType.underlyingClassRef(refinementOK) case tp: AnnotatedType => tp.underlying.underlyingClassRef(refinementOK) case tp: RefinedType => @@ -1147,29 +1175,35 @@ object Types { * Inherited by all type proxies. Empty for all other types. * Overwritten in ClassInfo, where parents is cached. */ - def parents(implicit ctx: Context): List[TypeRef] = this match { - case tp: TypeProxy => tp.underlying.parents - case _ => List() + def parentRefs(implicit ctx: Context): List[TypeRef] = this match { + case tp: TypeProxy => tp.underlying.parentRefs + case _ => Nil } /** The full parent types, including all type arguments */ def parentsWithArgs(implicit ctx: Context): List[Type] = this match { case tp: TypeProxy => tp.superType.parentsWithArgs - case _ => List() + case _ => Nil + } + + /** The full parent types, including (in new scheme) all type arguments */ + def parentsNEW(implicit ctx: Context): List[Type] = this match { + case AppliedType(tycon: HKTypeLambda, args) => // TODO: can be eliminated once ClassInfo is changed, also: cache? + tycon.resType.parentsWithArgs.map(_.substParams(tycon, args)) + case tp: TypeProxy => tp.superType.parentsNEW + case _ => Nil } /** The first parent of this type, AnyRef if list of parents is empty */ - def firstParent(implicit ctx: Context): TypeRef = parents match { + def firstParentRef(implicit ctx: Context): TypeRef = parentRefs match { case p :: _ => p case _ => defn.AnyType } - /** the self type of the underlying classtype */ - def givenSelfType(implicit ctx: Context): Type = this match { - case tp: RefinedType => tp.wrapIfMember(tp.parent.givenSelfType) - case tp: ThisType => tp.tref.givenSelfType - case tp: TypeProxy => tp.superType.givenSelfType - case _ => NoType + /** The first parent of this type, AnyRef if list of parents is empty */ + def firstParentNEW(implicit ctx: Context): Type = parentsNEW match { + case p :: _ => p + case _ => defn.AnyType } /** The parameter types of a PolyType or MethodType, Empty list for others */ @@ -1435,6 +1469,11 @@ object Types { /** A marker trait for types that can be types of values or that are higher-kinded */ trait ValueType extends ValueTypeOrProto with ValueTypeOrWildcard + /** A common base trait of NamedType and AppliedType */ + trait RefType extends CachedProxyType with ValueType { + def symbol(implicit ctx: Context): Symbol + } + /** A marker trait for types that are guaranteed to contain only a * single non-null value (they might contain null in addition). */ @@ -1466,7 +1505,7 @@ object Types { // --- NamedTypes ------------------------------------------------------------------ /** A NamedType of the form Prefix # name */ - abstract class NamedType extends CachedProxyType with ValueType { + abstract class NamedType extends CachedProxyType with RefType { val prefix: Type val name: Name @@ -1595,10 +1634,8 @@ object Types { } private def checkSymAssign(sym: Symbol)(implicit ctx: Context) = { - def selfTypeOf(sym: Symbol) = sym.owner.info match { - case info: ClassInfo => info.givenSelfType - case _ => NoType - } + def selfTypeOf(sym: Symbol) = + if (sym.isClass) sym.asClass.givenSelfType else NoType assert( (lastSymbol eq sym) || @@ -2197,7 +2234,7 @@ object Types { if ((parent eq this.parent) && (refinedName eq this.refinedName) && (refinedInfo eq this.refinedInfo)) this else RefinedType(parent, refinedName, refinedInfo) - /** Add this refinement to `parent`, provided If `refinedName` is a member of `parent`. */ + /** Add this refinement to `parent`, provided `refinedName` is a member of `parent`. */ def wrapIfMember(parent: Type)(implicit ctx: Context): Type = if (parent.member(refinedName).exists) derivedRefinedType(parent, refinedName, refinedInfo) else parent @@ -2994,6 +3031,87 @@ object Types { def paramRef(implicit ctx: Context): Type = TypeParamRef(tl, n) } + /** A type application `C[T_1, ..., T_n]` */ + abstract case class AppliedType(tycon: Type, args: List[Type]) + extends CachedProxyType with RefType { + + private var validSuper: Period = Nowhere + private var cachedSuper: Type = _ + + override def underlying(implicit ctx: Context): Type = tycon + + override def superType(implicit ctx: Context): Type = { + if (ctx.period != validSuper) { + validSuper = ctx.period + cachedSuper = tycon match { + case tp: HKTypeLambda => defn.AnyType + case tp: TypeVar if !tp.inst.exists => + // supertype not stable, since underlying might change + validSuper = Nowhere + tp.underlying.applyIfParameterized(args) + case tp: TypeProxy => + if (tp.typeSymbol.is(Provisional)) validSuper = Nowhere + tp.superType.applyIfParameterized(args) + case _ => defn.AnyType + } + } + cachedSuper + } + + override def symbol(implicit ctx: Context) = tycon.typeSymbol + + def lowerBound(implicit ctx: Context) = tycon.stripTypeVar match { + case tycon: TypeRef => + tycon.info match { + case TypeBounds(lo, hi) => + if (lo eq hi) superType // optimization, can profit from caching in this case + else lo.applyIfParameterized(args) + case _ => NoType + } + case _ => + NoType + } + + def typeParams(implicit ctx: Context): List[ParamInfo] = { + val tparams = tycon.typeParams + if (tparams.isEmpty) HKTypeLambda.any(args.length).typeParams else tparams + } + + def derivedAppliedType(tycon: Type, args: List[Type])(implicit ctx: Context): Type = + if ((tycon eq this.tycon) && (args eq this.args)) this + else tycon.appliedTo(args) + + override def computeHash = doHash(tycon, args) + + protected def checkInst(implicit ctx: Context): this.type = { + def check(tycon: Type): Unit = tycon.stripTypeVar match { + case tycon: TypeRef => + case _: TypeParamRef | _: ErrorType | _: WildcardType => + case _: TypeLambda => + assert(!args.exists(_.isInstanceOf[TypeBounds]), s"unreduced type apply: $this") + case tycon: AnnotatedType => + check(tycon.underlying) + case _ => + assert(false, s"illegal type constructor in $this") + } + if (Config.checkHKApplications) check(tycon) + this + } + } + + final class CachedAppliedType(tycon: Type, args: List[Type]) extends AppliedType(tycon, args) + + object AppliedType { + def apply(tycon: Type, args: List[Type])(implicit ctx: Context) = + unique(new CachedAppliedType(tycon, args)).checkInst + } + + object ClassRef { + def unapply(tp: RefType)(implicit ctx: Context): Option[RefType] = { // after bootstrap, drop the Option + if (tp.symbol.isClass) Some(tp) else None + } + } + /** A higher kinded type application `C[T_1, ..., T_n]` */ abstract case class HKApply(tycon: Type, args: List[Type]) extends CachedProxyType with ValueType { @@ -3290,7 +3408,7 @@ object Types { if (selfTypeCache == null) selfTypeCache = { def fullRef = fullyAppliedRef - val given = givenSelfType + val given = cls.givenSelfType val raw = if (!given.exists) fullRef else if (cls is Module) given @@ -3301,14 +3419,6 @@ object Types { selfTypeCache } - /** The explicitly given self type (self types of modules are assumed to be - * explcitly given here). - */ - override def givenSelfType(implicit ctx: Context): Type = selfInfo match { - case tp: Type => tp - case self: Symbol => self.info - } - private var selfTypeCache: Type = null private def fullyAppliedRef(base: Type, tparams: List[TypeSymbol])(implicit ctx: Context): Type = tparams match { @@ -3340,7 +3450,7 @@ object Types { private var parentsCache: List[TypeRef] = null /** The parent type refs as seen from the given prefix */ - override def parents(implicit ctx: Context): List[TypeRef] = { + override def parentRefs(implicit ctx: Context): List[TypeRef] = { if (parentsCache == null) parentsCache = cls.classParents.mapConserve(_.asSeenFrom(prefix, cls.owner).asInstanceOf[TypeRef]) parentsCache @@ -3348,7 +3458,7 @@ object Types { /** The parent types with all type arguments */ override def parentsWithArgs(implicit ctx: Context): List[Type] = - parents mapConserve { pref => + parentRefs mapConserve { pref => ((pref: Type) /: pref.classSymbol.typeParams) { (parent, tparam) => val targSym = decls.lookup(tparam.name) if (targSym.exists) RefinedType(parent, targSym.name, targSym.info) @@ -3356,6 +3466,9 @@ object Types { } } + override def parentsNEW(implicit ctx: Context): List[Type] = + parentRefs // !!! TODO: change + def derivedClassInfo(prefix: Type)(implicit ctx: Context) = if (prefix eq this.prefix) this else ClassInfo(prefix, cls, classParents, decls, selfInfo) @@ -3828,12 +3941,12 @@ object Types { abstract class DeepTypeMap(implicit ctx: Context) extends TypeMap { override def mapClassInfo(tp: ClassInfo) = { val prefix1 = this(tp.prefix) - val parents1 = (tp.parents mapConserve this).asInstanceOf[List[TypeRef]] + val parentRefs1 = (tp.parentRefs mapConserve this).asInstanceOf[List[TypeRef]] val selfInfo1 = tp.selfInfo match { case selfInfo: Type => this(selfInfo) case selfInfo => selfInfo } - tp.derivedClassInfo(prefix1, parents1, tp.decls, selfInfo1) + tp.derivedClassInfo(prefix1, parentRefs1, tp.decls, selfInfo1) } } @@ -4144,7 +4257,7 @@ object Types { } private def otherReason(pre: Type)(implicit ctx: Context): String = pre match { - case pre: ThisType if pre.givenSelfType.exists => + case pre: ThisType if pre.cls.givenSelfType.exists => i"\nor the self type of $pre might not contain all transitive dependencies" case _ => "" } diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala index 338a395ab685..3b8789ada24a 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala @@ -139,7 +139,7 @@ class TreePickler(pickler: TastyPickler) { } private def pickleNewType(tpe: Type, richTypes: Boolean)(implicit ctx: Context): Unit = tpe match { - case AppliedType(tycon, args) => + case AnyAppliedType(tycon, args) => writeByte(APPLIEDtype) withLength { pickleType(tycon); args.foreach(pickleType(_)) } case ConstantType(value) => diff --git a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala index 8a10ef60ebbe..cf409a18103b 100644 --- a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala @@ -4,7 +4,7 @@ package printing import core._ import Texts._, Types._, Flags._, Names._, Symbols._, NameOps._, Constants._, Denotations._ import Contexts.Context, Scopes.Scope, Denotations.Denotation, Annotations.Annotation -import TypeApplications.AppliedType +import TypeApplications.AnyAppliedType import StdNames.{nme, tpnme} import ast.Trees._, ast._ import typer.Implicits._ @@ -123,7 +123,7 @@ class PlainPrinter(_ctx: Context) extends Printer { */ private def refinementChain(tp: Type): List[Type] = tp :: (tp match { - case AppliedType(_, _) => Nil + case AnyAppliedType(_, _) => Nil case tp: RefinedType => refinementChain(tp.parent.stripTypeVar) case _ => Nil }) @@ -142,7 +142,7 @@ class PlainPrinter(_ctx: Context) extends Printer { toTextLocal(tp.underlying) ~ "(" ~ toTextRef(tp) ~ ")" case tp: TypeRef => toTextPrefix(tp.prefix) ~ selectionString(tp) - case AppliedType(tycon, args) => + case AnyAppliedType(tycon, args) => (toTextLocal(tycon) ~ "[" ~ Text(args map argText, ", ") ~ "]").close case tp: RefinedType => val parent :: (refined: List[RefinedType @unchecked]) = @@ -323,7 +323,7 @@ class PlainPrinter(_ctx: Context) extends Printer { val declsText = if (trueDecls.isEmpty || !ctx.settings.debug.value) Text() else dclsText(trueDecls) - tparamsText ~ " extends " ~ toTextParents(tp.parents) ~ "{" ~ selfText ~ declsText ~ + tparamsText ~ " extends " ~ toTextParents(tp.parentsNEW) ~ "{" ~ selfText ~ declsText ~ "} at " ~ preText case tp => ": " ~ toTextGlobal(tp) @@ -401,7 +401,7 @@ class PlainPrinter(_ctx: Context) extends Printer { def toText(sym: Symbol): Text = (kindString(sym) ~~ { - if (sym.isAnonymousClass) toText(sym.info.parents, " with ") ~ "{...}" + if (sym.isAnonymousClass) toText(sym.info.parentsNEW, " with ") ~ "{...}" else if (hasMeaninglessName(sym)) simpleNameString(sym.owner) + idString(sym) else nameString(sym) }).close diff --git a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala index c494110201e4..482d8c651cce 100644 --- a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala @@ -126,7 +126,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { } def isInfixType(tp: Type): Boolean = tp match { - case AppliedType(tycon, args) => + case AnyAppliedType(tycon, args) => args.length == 2 && !Character.isUnicodeIdentifierStart(tycon.typeSymbol.name.toString.head) // TODO: Once we use the 2.12 stdlib, also check the @showAsInfix annotation @@ -149,7 +149,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { homogenize(tp) match { case x: ConstantType if homogenizedView => return toText(x.widen) - case AppliedType(tycon, args) => + case AnyAppliedType(tycon, args) => val cls = tycon.typeSymbol if (tycon.isRepeatedParam) return toTextLocal(args.head) ~ "*" if (defn.isFunctionClass(cls)) return toTextFunction(args, cls.name.isImplicitFunction) diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala index af0861ad6bf2..312793035e15 100644 --- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala @@ -1258,7 +1258,7 @@ object messages { val msg = hl"""|$qual does not name a parent of $cls""" val kind = "Reference" - private val parents: Seq[String] = (cls.info.parents map (_.name.show)).sorted + private val parents: Seq[String] = (cls.info.parentRefs map (_.name.show)).sorted val explanation = hl"""|When a qualifier ${"T"} is used in a ${"super"} prefix of the form ${"C.super[T]"}, diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala index 5488d1979649..b34eade299ee 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala @@ -179,7 +179,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder else dt.Module } else dt.ClassDef - val selfType = apiType(sym.classInfo.givenSelfType) + val selfType = apiType(sym.givenSelfType) val name = if (sym.is(ModuleClass)) sym.fullName.sourceModuleName else sym.fullName @@ -370,7 +370,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder else tp.prefix new api.Projection(simpleType(prefix), sym.name.toString) - case TypeApplications.AppliedType(tycon, args) => + case TypeApplications.AnyAppliedType(tycon, args) => def processArg(arg: Type): api.Type = arg match { case arg @ TypeBounds(lo, hi) => // Handle wildcard parameters if (lo.isDirectRef(defn.NothingClass) && hi.isDirectRef(defn.AnyClass)) diff --git a/compiler/src/dotty/tools/dotc/transform/Erasure.scala b/compiler/src/dotty/tools/dotc/transform/Erasure.scala index 5837b2b6904a..25c8c53a37a1 100644 --- a/compiler/src/dotty/tools/dotc/transform/Erasure.scala +++ b/compiler/src/dotty/tools/dotc/transform/Erasure.scala @@ -391,7 +391,7 @@ object Erasure { cpy.Super(qual)(thisQual, untpd.Ident(sym.owner.asClass.name)) .withType(SuperType(thisType, sym.owner.typeRef)) else - qual.withType(SuperType(thisType, thisType.firstParent)) + qual.withType(SuperType(thisType, thisType.firstParentRef)) case _ => qual } diff --git a/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala b/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala index 937490ab060a..8573e1e930d9 100644 --- a/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala +++ b/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala @@ -105,7 +105,7 @@ class ExplicitOuter extends MiniPhaseTransform with InfoTransformer { thisTransf for (parentTrait <- cls.mixins) { if (needsOuterIfReferenced(parentTrait)) { - val parentTp = cls.denot.thisType.baseTypeRef(parentTrait) + val parentTp = cls.denot.thisType.baseType(parentTrait) val outerAccImpl = newOuterAccessor(cls, parentTrait).enteredAfter(thisTransformer) newDefs += DefDef(outerAccImpl, singleton(fixThis(outerPrefix(parentTp)))) } @@ -194,7 +194,7 @@ object ExplicitOuter { needsOuterIfReferenced(cls) && (!hasLocalInstantiation(cls) || // needs outer because we might not know whether outer is referenced or not cls.mixins.exists(needsOuterIfReferenced) || // needs outer for parent traits - cls.classInfo.parents.exists(parent => // needs outer to potentially pass along to parent + cls.info.parentsNEW.exists(parent => // needs outer to potentially pass along to parent needsOuterIfReferenced(parent.classSymbol.asClass))) /** Class is always instantiated in the compilation unit where it is defined */ diff --git a/compiler/src/dotty/tools/dotc/transform/ExplicitSelf.scala b/compiler/src/dotty/tools/dotc/transform/ExplicitSelf.scala index 7bb65e5755b2..3592471823ff 100644 --- a/compiler/src/dotty/tools/dotc/transform/ExplicitSelf.scala +++ b/compiler/src/dotty/tools/dotc/transform/ExplicitSelf.scala @@ -38,9 +38,8 @@ class ExplicitSelf extends MiniPhaseTransform { thisTransform => override def transformSelect(tree: Select)(implicit ctx: Context, info: TransformerInfo): Tree = tree match { case Select(thiz: This, name) if name.isTermName => val cls = thiz.symbol.asClass - val cinfo = cls.classInfo - if (cinfo.givenSelfType.exists && !cls.derivesFrom(tree.symbol.owner)) - cpy.Select(tree)(thiz.asInstance(AndType(cinfo.selfType, thiz.tpe)), name) + if (cls.givenSelfType.exists && !cls.derivesFrom(tree.symbol.owner)) + cpy.Select(tree)(thiz.asInstance(AndType(cls.classInfo.selfType, thiz.tpe)), name) else tree case _ => tree } diff --git a/compiler/src/dotty/tools/dotc/transform/OverridingPairs.scala b/compiler/src/dotty/tools/dotc/transform/OverridingPairs.scala index cbd79d5c50d6..44c17d15178c 100644 --- a/compiler/src/dotty/tools/dotc/transform/OverridingPairs.scala +++ b/compiler/src/dotty/tools/dotc/transform/OverridingPairs.scala @@ -35,7 +35,7 @@ object OverridingPairs { * pair has already been treated in a parent class. * This may be refined in subclasses. @see Bridges for a use case. */ - protected def parents: Array[Symbol] = base.info.parents.toArray map (_.typeSymbol) + protected def parents: Array[Symbol] = base.info.parentsNEW.toArray map (_.typeSymbol) /** Does `sym1` match `sym2` so that it qualifies as overriding. * Types always match. Term symbols match if their membertypes diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index 46640b02c021..be6c2793783d 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -377,12 +377,12 @@ trait Applications extends Compatibility { self: Typer with Dynamic => // default getters for class constructors are found in the companion object val cls = meth.owner val companion = cls.companionModule - receiver.tpe.baseTypeRef(cls) match { - case tp: TypeRef if companion.isTerm => - selectGetter(ref(TermRef(tp.prefix, companion.asTerm))) - case _ => - EmptyTree + if (companion.isTerm) { + val prefix = receiver.tpe.baseType(cls).normalizedPrefix + if (prefix.exists) selectGetter(ref(TermRef(prefix, companion.asTerm))) + else EmptyTree } + else EmptyTree } } } @@ -891,7 +891,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic => def isSubTypeOfParent(subtp: Type, tp: Type)(implicit ctx: Context): Boolean = if (subtp <:< tp) true else tp match { - case tp: TypeRef if tp.symbol.isClass => isSubTypeOfParent(subtp, tp.firstParent) + case tp: TypeRef if tp.symbol.isClass => isSubTypeOfParent(subtp, tp.firstParentNEW) case tp: TypeProxy => isSubTypeOfParent(subtp, tp.superType) case _ => false } diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala index 72ce89a33942..2dfb3f7aadc9 100644 --- a/compiler/src/dotty/tools/dotc/typer/Checking.scala +++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala @@ -133,7 +133,7 @@ object Checking { // Create a synthetic singleton type instance, and check whether // it conforms to the self type of the class as seen from that instance. val stp = SkolemType(tp) - val selfType = tref.givenSelfType.asSeenFrom(stp, cls) + val selfType = cls.asClass.givenSelfType.asSeenFrom(stp, cls) if (selfType.exists && !(stp <:< selfType)) ctx.error(DoesNotConformToSelfTypeCantBeInstantiated(tp, selfType), pos) } diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index 2e84a2389a9f..e2cebaf00777 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -921,7 +921,7 @@ class Namer { typer: Typer => Checking.checkWellFormed(cls) if (isDerivedValueClass(cls)) cls.setFlag(Final) cls.info = avoidPrivateLeaks(cls, cls.pos) - cls.baseClasses.foreach(_.invalidateBaseTypeRefCache()) // we might have looked before and found nothing + cls.baseClasses.foreach(_.invalidateBaseTypeCache()) // we might have looked before and found nothing } } diff --git a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala index 97d50b07e34e..741e174d3ec2 100644 --- a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala +++ b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala @@ -94,16 +94,16 @@ object RefChecks { */ private def checkParents(cls: Symbol)(implicit ctx: Context): Unit = cls.info match { case cinfo: ClassInfo => - def checkSelfConforms(other: TypeRef, category: String, relation: String) = { + def checkSelfConforms(other: ClassSymbol, category: String, relation: String) = { val otherSelf = other.givenSelfType.asSeenFrom(cls.thisType, other.classSymbol) if (otherSelf.exists && !(cinfo.selfType <:< otherSelf)) ctx.error(DoesNotConformToSelfType(category, cinfo.selfType, cls, otherSelf, relation, other.classSymbol), cls.pos) } for (parent <- cinfo.classParents) - checkSelfConforms(parent, "illegal inheritance", "parent") - for (reqd <- cinfo.givenSelfType.classSymbols) - checkSelfConforms(reqd.typeRef, "missing requirement", "required") + checkSelfConforms(parent.typeSymbol.asClass, "illegal inheritance", "parent") + for (reqd <- cinfo.cls.givenSelfType.classSymbols) + checkSelfConforms(reqd, "missing requirement", "required") case _ => } @@ -285,7 +285,7 @@ object RefChecks { //Console.println(infoString(member) + " shadows1 " + infoString(other) " in " + clazz);//DEBUG return } - val parentSymbols = clazz.info.parents.map(_.typeSymbol) + val parentSymbols = clazz.info.parentsNEW.map(_.typeSymbol) if (parentSymbols exists (p => subOther(p) && subMember(p) && deferredCheck)) { //Console.println(infoString(member) + " shadows2 " + infoString(other) + " in " + clazz);//DEBUG return diff --git a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala index 3a330b3f041d..6f2fe09fa887 100644 --- a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala +++ b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala @@ -6,7 +6,7 @@ import core._ import ast._ import Scopes._, Contexts._, Constants._, Types._, Symbols._, Names._, Flags._, Decorators._ import ErrorReporting._, Annotations._, Denotations._, SymDenotations._, StdNames._, TypeErasure._ -import TypeApplications.AppliedType +import TypeApplications.AnyAppliedType import util.Positions._ import config.Printers.typr import ast.Trees._ @@ -104,7 +104,7 @@ trait TypeAssigner { } case tp @ HKApply(tycon, args) if toAvoid(tycon) => apply(tp.superType) - case tp @ AppliedType(tycon, args) if toAvoid(tycon) => + case tp @ AnyAppliedType(tycon, args) if toAvoid(tycon) => val base = apply(tycon) var args = tp.baseArgInfos(base.typeSymbol) if (base.typeParams.length != args.length) @@ -293,7 +293,7 @@ trait TypeAssigner { case err: ErrorType => untpd.cpy.Super(tree)(qual, mix).withType(err) case qtype @ ThisType(_) => val cls = qtype.cls - def findMixinSuper(site: Type): Type = site.parents filter (_.name == mix.name) match { + def findMixinSuper(site: Type): Type = site.parentRefs filter (_.name == mix.name) match { case p :: Nil => p case Nil => @@ -304,7 +304,7 @@ trait TypeAssigner { val owntype = if (mixinClass.exists) mixinClass.typeRef else if (!mix.isEmpty) findMixinSuper(cls.info) - else if (inConstrCall || ctx.erasedTypes) cls.info.firstParent + else if (inConstrCall || ctx.erasedTypes) cls.info.firstParentRef else { val ps = cls.classInfo.parentsWithArgs if (ps.isEmpty) defn.AnyType else ps.reduceLeft((x: Type, y: Type) => x & y) @@ -513,17 +513,15 @@ trait TypeAssigner { private def symbolicIfNeeded(sym: Symbol)(implicit ctx: Context) = { val owner = sym.owner - owner.infoOrCompleter match { - case info: ClassInfo if info.givenSelfType.exists => - // In that case a simple typeRef/termWithWithSig could return a member of - // the self type, not the symbol itself. To avoid this, we make the reference - // symbolic. In general it seems to be faster to keep the non-symblic - // reference, since there is less pressure on the uniqueness tables that way - // and less work to update all the different references. That's why symbolic references - // are only used if necessary. - NamedType.withFixedSym(owner.thisType, sym) - case _ => NoType - } + if (owner.isClass && owner.isCompleted && owner.asClass.givenSelfType.exists) + // In that case a simple typeRef/termWithWithSig could return a member of + // the self type, not the symbol itself. To avoid this, we make the reference + // symbolic. In general it seems to be faster to keep the non-symblic + // reference, since there is less pressure on the uniqueness tables that way + // and less work to update all the different references. That's why symbolic references + // are only used if necessary. + NamedType.withFixedSym(owner.thisType, sym) + else NoType } def assertExists(tp: Type) = { assert(tp != NoType); tp } diff --git a/doc-tool/src/dotty/tools/dottydoc/model/factories.scala b/doc-tool/src/dotty/tools/dottydoc/model/factories.scala index 03f11335ead1..563a20938372 100644 --- a/doc-tool/src/dotty/tools/dottydoc/model/factories.scala +++ b/doc-tool/src/dotty/tools/dottydoc/model/factories.scala @@ -57,7 +57,7 @@ object factories { } def expandTpe(t: Type, params: List[Reference] = Nil): Reference = t match { - case AppliedType(tycon, args) => { + case AnyAppliedType(tycon, args) => { val cls = tycon.typeSymbol if (defn.isFunctionClass(cls))