diff options
Diffstat (limited to 'src/dotty/tools/dotc')
23 files changed, 104 insertions, 688 deletions
diff --git a/src/dotty/tools/dotc/config/Config.scala b/src/dotty/tools/dotc/config/Config.scala index 1c22329f1..7dfc09b3f 100644 --- a/src/dotty/tools/dotc/config/Config.scala +++ b/src/dotty/tools/dotc/config/Config.scala @@ -8,8 +8,6 @@ object Config { final val cacheMemberNames = true final val cacheImplicitScopes = true - final val newHK = true - final val checkCacheMembersNamed = false /** When updating a constraint bound, check that the constrained parameter diff --git a/src/dotty/tools/dotc/core/Definitions.scala b/src/dotty/tools/dotc/core/Definitions.scala index 44d36abc5..5db9a6b0d 100644 --- a/src/dotty/tools/dotc/core/Definitions.scala +++ b/src/dotty/tools/dotc/core/Definitions.scala @@ -663,71 +663,6 @@ class Definitions { def functionArity(tp: Type)(implicit ctx: Context) = tp.dealias.argInfos.length - 1 - // ----- LambdaXYZ traits ------------------------------------------ - - private var myLambdaTraits: Set[Symbol] = Set() - - /** The set of HigherKindedXYZ traits encountered so far */ - def lambdaTraitsOBS: Set[Symbol] = myLambdaTraits - - private var LambdaTraitForVariances = mutable.Map[List[Int], ClassSymbol]() - - /** The HigherKinded trait corresponding to symbols `boundSyms` (which are assumed - * to be the type parameters of a higher-kided type). This is a class symbol that - * would be generated by the following schema. - * - * trait LambdaXYZ extends Object with P1 with ... with Pn { - * type v_1 hk$0; ...; type v_N hk$N; - * type +$Apply - * } - * - * Here: - * - * - v_i are the variances of the bound symbols (i.e. +, -, or empty). - * - XYZ is a string of length N with one letter for each variant of a bound symbol, - * using `P` (positive variance), `N` (negative variance), `I` (invariant). - * - for each positive or negative variance v_i there is a parent trait Pj which - * is the same as LambdaXYZ except that it has `I` in i-th position. - */ - def LambdaTraitOBS(vcs: List[Int]): ClassSymbol = { - assert(vcs.nonEmpty) - - def varianceFlags(v: Int) = v match { - case -1 => Contravariant - case 0 => EmptyFlags - case 1 => Covariant - } - - val completer = new LazyType { - def complete(denot: SymDenotation)(implicit ctx: Context): Unit = { - val cls = denot.asClass.classSymbol - val paramDecls = newScope - for (i <- 0 until vcs.length) - newTypeParam(cls, tpnme.hkArg(i), varianceFlags(vcs(i)), paramDecls) - newTypeField(cls, tpnme.hkApplyOBS, Covariant, paramDecls) - val parentTraitRefs = - for (i <- 0 until vcs.length if vcs(i) != 0) - yield LambdaTraitOBS(vcs.updated(i, 0)).typeRef - denot.info = ClassInfo( - ScalaPackageClass.thisType, cls, ObjectClass.typeRef :: parentTraitRefs.toList, paramDecls) - } - } - - val traitName = tpnme.hkLambdaOBS(vcs) - - def createTrait = { - val cls = newClassSymbol( - ScalaPackageClass, - traitName, - PureInterfaceCreationFlags | Synthetic, - completer) - myLambdaTraits += cls - cls - } - - LambdaTraitForVariances.getOrElseUpdate(vcs, createTrait) - } - // ----- primitive value class machinery ------------------------------------------ /** This class would also be obviated by the implicit function type design */ diff --git a/src/dotty/tools/dotc/core/NameOps.scala b/src/dotty/tools/dotc/core/NameOps.scala index 1f221b5c8..b5704480a 100644 --- a/src/dotty/tools/dotc/core/NameOps.scala +++ b/src/dotty/tools/dotc/core/NameOps.scala @@ -116,14 +116,6 @@ object NameOps { def hkArgIndex: Int = name.drop(tpnme.hkArgPrefixLength).toString.toInt - def isLambdaTraitNameOBS(implicit ctx: Context): Boolean = - name.isTypeName && name.startsWith(tpnme.hkLambdaPrefixOBS) - - def lambdaTraitVariancesOBS(implicit ctx: Context): List[Int] = { - val vs = name.drop(tpnme.hkLambdaPrefixOBS.length) - vs.toList.map(c => tpnme.varianceSuffixesOBS.indexOf(c) - 1) - } - /** If the name ends with $nn where nn are * all digits, strip the $ and the digits. * Otherwise return the argument. diff --git a/src/dotty/tools/dotc/core/StdNames.scala b/src/dotty/tools/dotc/core/StdNames.scala index e82260201..c767f4c29 100644 --- a/src/dotty/tools/dotc/core/StdNames.scala +++ b/src/dotty/tools/dotc/core/StdNames.scala @@ -529,9 +529,7 @@ object StdNames { val synthSwitch: N = "$synthSwitch" - val hkApplyOBS: N = "$Apply" val hkArgPrefix: N = "$hk" - val hkLambdaPrefixOBS: N = "Lambda$" val hkArgPrefixHead: Char = hkArgPrefix.head val hkArgPrefixLength: Int = hkArgPrefix.length @@ -744,12 +742,8 @@ object StdNames { def syntheticTypeParamNames(num: Int): List[TypeName] = (0 until num).map(syntheticTypeParamName)(breakOut) - def hkLambdaOBS(vcs: List[Int]): TypeName = hkLambdaPrefixOBS ++ vcs.map(varianceSuffixOBS).mkString def hkArg(n: Int): TypeName = hkArgPrefix ++ n.toString - def varianceSuffixOBS(v: Int): Char = varianceSuffixesOBS.charAt(v + 1) - val varianceSuffixesOBS = "NIP" - final val Conforms = encode("<:<") } diff --git a/src/dotty/tools/dotc/core/Substituters.scala b/src/dotty/tools/dotc/core/Substituters.scala index 4598aaa20..0d1c78e2f 100644 --- a/src/dotty/tools/dotc/core/Substituters.scala +++ b/src/dotty/tools/dotc/core/Substituters.scala @@ -179,24 +179,6 @@ trait Substituters { this: Context => .mapOver(tp) } - final def substRefinedThis(tp: Type, from: Type, to: Type, theMap: SubstRefinedThisMap): Type = - tp match { - case tp @ RefinedThis(binder) => - if (binder eq from) to else tp - case tp: NamedType => - if (tp.currentSymbol.isStatic) tp - else tp.derivedSelect(substRefinedThis(tp.prefix, from, to, theMap)) - case _: ThisType | _: BoundType | NoPrefix => - tp - case tp: RefinedType => - tp.derivedRefinedType(substRefinedThis(tp.parent, from, to, theMap), tp.refinedName, substRefinedThis(tp.refinedInfo, from, to, theMap)) - case tp: TypeAlias => - tp.derivedTypeAlias(substRefinedThis(tp.alias, from, to, theMap)) - case _ => - (if (theMap != null) theMap else new SubstRefinedThisMap(from, to)) - .mapOver(tp) - } - final def substRecThis(tp: Type, from: Type, to: Type, theMap: SubstRecThisMap): Type = tp match { case tp @ RecThis(binder) => @@ -284,10 +266,6 @@ trait Substituters { this: Context => def apply(tp: Type): Type = substThis(tp, from, to, this) } - final class SubstRefinedThisMap(from: Type, to: Type) extends DeepTypeMap { - def apply(tp: Type): Type = substRefinedThis(tp, from, to, this) - } - final class SubstRecThisMap(from: Type, to: Type) extends DeepTypeMap { def apply(tp: Type): Type = substRecThis(tp, from, to, this) } diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala index 124199678..e8053a740 100644 --- a/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/src/dotty/tools/dotc/core/SymDenotations.scala @@ -483,10 +483,6 @@ object SymDenotations { final def isRefinementClass(implicit ctx: Context): Boolean = name.decode == tpnme.REFINE_CLASS - /** is this symbol a trait representing a type lambda? */ - final def isLambdaTraitOBS(implicit ctx: Context): Boolean = - isClass && name.startsWith(tpnme.hkLambdaPrefixOBS) && owner == defn.ScalaPackageClass - /** Is this symbol a package object or its module class? */ def isPackageObject(implicit ctx: Context): Boolean = { val poName = if (isType) nme.PACKAGE_CLS else nme.PACKAGE diff --git a/src/dotty/tools/dotc/core/TypeApplications.scala b/src/dotty/tools/dotc/core/TypeApplications.scala index 0edc598dd..33aa060b5 100644 --- a/src/dotty/tools/dotc/core/TypeApplications.scala +++ b/src/dotty/tools/dotc/core/TypeApplications.scala @@ -81,7 +81,6 @@ object TypeApplications { object TypeLambda { def apply(argBindingFns: List[RecType => TypeBounds], bodyFn: RecType => Type)(implicit ctx: Context): Type = { - assert(Config.newHK) val argNames = argBindingFns.indices.toList.map(tpnme.hkArg) var idx = 0 RecType.closeOver(rt => @@ -92,54 +91,19 @@ object TypeApplications { }) } - def applyOBS(variances: List[Int], - argBoundsFns: List[RefinedType => TypeBounds], - bodyFn: RefinedType => Type)(implicit ctx: Context): Type = { - def argRefinements(parent: Type, i: Int, bs: List[RefinedType => TypeBounds]): Type = bs match { - case b :: bs1 => - argRefinements(RefinedType(parent, tpnme.hkArg(i), b), i + 1, bs1) - case nil => - parent + def unapply(tp: Type)(implicit ctx: Context): Option[( /*List[Int], */ List[TypeBounds], Type)] = { + def decompose(t: Type, acc: List[TypeBounds]): (List[TypeBounds], Type) = t match { + case t @ RefinedType(p, rname, rinfo: TypeBounds) if t.isTypeParam => + decompose(p, rinfo.bounds :: acc) + case t: RecType => + decompose(t.parent, acc) + case _ => + (acc, t) } - assert(variances.nonEmpty) - assert(argBoundsFns.length == variances.length) - RefinedType( - argRefinements(defn.LambdaTraitOBS(variances).typeRef, 0, argBoundsFns), - tpnme.hkApplyOBS, bodyFn(_).bounds.withVariance(1)) - } - - def unapply(tp: Type)(implicit ctx: Context): Option[(/*List[Int], */List[TypeBounds], Type)] = - if (Config.newHK) { - def decompose(t: Type, acc: List[TypeBounds]): (List[TypeBounds], Type) = t match { - case t @ RefinedType(p, rname, rinfo: TypeBounds) if t.isTypeParam => - decompose(p, rinfo.bounds :: acc) - case t: RecType => - decompose(t.parent, acc) - case _ => - (acc, t) - } - decompose(tp, Nil) match { - case (Nil, _) => None - case x => Some(x) -// case (bindings, tp) => Some((Nil, bindings, tp)) - } + decompose(tp, Nil) match { + case (Nil, _) => None + case x => Some(x) } - else tp match { - case app @ RefinedType(parent, tpnme.hkApplyOBS, refinedInfo) => - val cls = parent.typeSymbol - val variances = cls.typeParams.map(_.variance) - def collectBounds(t: Type, acc: List[TypeBounds]): List[TypeBounds] = t match { - case t @ RefinedType(p, rname, rinfo) => - assert(rname.isHkArgName) - collectBounds(p, rinfo.bounds :: acc) - case TypeRef(_, lname) => - assert(lname.isLambdaTraitNameOBS) - acc - } - val argBounds = collectBounds(parent, Nil) - Some((argBounds, refinedInfo.argInfo)) - case _ => - None } } @@ -162,7 +126,7 @@ object TypeApplications { def argsAreForwarders(args: List[Type], n: Int): Boolean = args match { case Nil => n == 0 - case TypeRef(RefinedThis(rt), sel) :: args1 => + case TypeRef(RecThis(rt), sel) :: args1 if false => rt.eq(tp) && sel == tpnme.hkArg(n - 1) && argsAreForwarders(args1, n - 1) case _ => false @@ -179,17 +143,13 @@ object TypeApplications { * * T { type p_1 v_1= U_1; ...; type p_n v_n= U_n } * - * where v_i, p_i are the variances and names of the type parameters of T, - * If `T`'s class symbol is a lambda trait, follow the refined type with a - * projection - * - * T { ... } # $Apply + * where v_i, p_i are the variances and names of the type parameters of T. */ object AppliedType { 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 { - case tp: RefinedType if Config.newHK => + case tp: RefinedType => var refinements: List[RefinedType] = Nil var tycon = tp.stripTypeVar while (tycon.isInstanceOf[RefinedType]) { @@ -209,38 +169,8 @@ object TypeApplications { None } collectArgs(tycon.typeParams, refinements, new mutable.ListBuffer[Type]) - case TypeRef(prefix, tpnme.hkApplyOBS) if !Config.newHK => - unapp(prefix) case _ => - if (Config.newHK) None - else unapp(tp) match { - case Some((tycon: TypeRef, _)) if tycon.symbol.isLambdaTraitOBS => - // We are seeing part of a lambda abstraction, not an applied type - None - case x => x - } - } - - private def unapp(tp: Type)(implicit ctx: Context): Option[(Type, List[Type])] = tp match { - case _: RefinedType => - val tparams = tp.classSymbol.typeParams - if (tparams.isEmpty) None - else { - val argBuf = new mutable.ListBuffer[Type] - def stripArgs(tp: Type, n: Int): Type = - if (n == 0) tp - else tp match { - case tp @ RefinedType(parent, pname, rinfo) if pname == tparams(n - 1).name => - val res = stripArgs(parent, n - 1) - if (res.exists) argBuf += rinfo.argInfo - res - case _ => - NoType - } - val res = stripArgs(tp, tparams.length) - if (res.exists) Some((res, argBuf.toList)) else None - } - case _ => None + None } } @@ -257,50 +187,9 @@ object TypeApplications { } /** The references `<rt>.this.$hk0, ..., <rt>.this.$hk<n-1>`. */ - def argRefs(rt: RefinedType, n: Int)(implicit ctx: Context) = - List.range(0, n).map(i => RefinedThis(rt).select(tpnme.hkArg(i))) - - /** The references `<rt>.this.$hk0, ..., <rt>.this.$hk<n-1>`. */ def argRefs(rt: RecType, n: Int)(implicit ctx: Context) = List.range(0, n).map(i => RecThis(rt).select(tpnme.hkArg(i))) - /** Merge `tp1` and `tp2` under a common lambda, combining them with `op`. - * @param tparams1 The type parameters of `tp1` - * @param tparams2 The type parameters of `tp2` - * @pre tparams1.length == tparams2.length - * Produces the type lambda - * - * [v1 X1 B1, ..., vn Xn Bn] -> op(tp1[X1, ..., Xn], tp2[X1, ..., Xn]) - * - * where - * - * - variances `vi` are the variances of corresponding type parameters for `tp1` - * or `tp2`, or are 0 of the latter disagree. - * - bounds `Bi` are the intersection of the corresponding type parameter bounds - * of `tp1` and `tp2`. - */ - def hkCombineOBS(tp1: Type, tp2: Type, - tparams1: List[TypeSymbol], tparams2: List[TypeSymbol], op: (Type, Type) => Type) - (implicit ctx: Context): Type = { - val variances = (tparams1, tparams2).zipped.map { (tparam1, tparam2) => - val v1 = tparam1.variance - val v2 = tparam2.variance - if (v1 == v2) v1 else 0 - } - val bounds: List[RefinedType => TypeBounds] = - (tparams1, tparams2).zipped.map { (tparam1, tparam2) => - val b1: RefinedType => TypeBounds = - tp1.memberInfo(tparam1).bounds.internalizeFrom(tparams1) - val b2: RefinedType => TypeBounds = - tp2.memberInfo(tparam2).bounds.internalizeFrom(tparams2) - (rt: RefinedType) => b1(rt) & b2(rt) - } - val app1: RefinedType => Type = rt => tp1.appliedTo(argRefs(rt, tparams1.length)) - val app2: RefinedType => Type = rt => tp2.appliedTo(argRefs(rt, tparams2.length)) - val body: RefinedType => Type = rt => op(app1(rt), app2(rt)) - TypeLambda.applyOBS(variances, bounds, body) - } - private class InstMap(fullType: Type)(implicit ctx: Context) extends TypeMap { var localRecs: Set[RecType] = Set.empty var keptRefs: Set[Name] = Set.empty @@ -349,33 +238,10 @@ class TypeApplications(val self: Type) extends AnyVal { self.cls.typeParams case self: TypeRef => val tsym = self.symbol - if (tsym.isClass) tsym.typeParams - else tsym.infoOrCompleter match { - case completer: TypeParamsCompleter => - val tparams = completer.completerTypeParams(tsym) - if (Config.newHK) fallbackTypeParams(tparams.map(_.variance)) - else defn.LambdaTraitOBS(tparams.map(_.variance)).typeParams - case _ => - if (!tsym.isCompleting || tsym.isAliasType) tsym.info.typeParams - else - // We are facing a problem when computing the type parameters of an uncompleted - // abstract type. We can't access the bounds of the symbol yet because that - // would cause a cause a cyclic reference. So we return `Nil` instead - // and try to make up for it later. The acrobatics in Scala2Unpicker#readType - // for reading a TypeRef show what's needed. - Nil - } + if (tsym.isClass) tsym.typeParams else tsym.info.typeParams case self: RefinedType => - // inlined and optimized version of - // val sym = self.LambdaTrait - // if (sym.exists) return sym.typeParams - if (!Config.newHK && self.refinedName == tpnme.hkApplyOBS) { - val sym = self.parent.classSymbol - if (sym.isLambdaTraitOBS) return sym.typeParams - } val precedingParams = self.parent.typeParams.filterNot(_.memberName == self.refinedName) - if (Config.newHK && self.isTypeParam) precedingParams :+ self - else precedingParams + if (self.isTypeParam) precedingParams :+ self else precedingParams case self: RecType => self.parent.typeParams case self: SingletonType => @@ -389,9 +255,7 @@ class TypeApplications(val self: Type) extends AnyVal { /** If `self` is a higher-kinded type, its type parameters $hk_i, otherwise Nil */ final def hkTypeParams(implicit ctx: Context): List[MemberBinding] = - if (Config.newHK) - if (isHK) typeParams else Nil - else LambdaTraitOBS.typeParams + if (isHK) typeParams else Nil /** If `self` is a generic class, its type parameter symbols, otherwise Nil */ final def typeParamSymbols(implicit ctx: Context): List[TypeSymbol] = typeParams match { @@ -462,19 +326,10 @@ class TypeApplications(val self: Type) extends AnyVal { } } - /** The Lambda trait underlying a type lambda */ - def LambdaTraitOBS(implicit ctx: Context): Symbol = self.stripTypeVar match { - case RefinedType(_, tpnme.hkApplyOBS, _) => - val sym = self.classSymbol - if (sym.isLambdaTraitOBS) sym else NoSymbol - case TypeBounds(lo, hi) => hi.LambdaTraitOBS - case _ => NoSymbol - } - /** Is self type higher-kinded (i.e. of kind != "*")? */ def isHK(implicit ctx: Context): Boolean = self.dealias match { case self: TypeRef => self.info.isHK - case self: RefinedType => self.refinedName == tpnme.hkApplyOBS || self.isTypeParam + case self: RefinedType => self.isTypeParam case self: SingletonType => false case self: TypeVar => self.origin.isHK case self: WildcardType => self.optBounds.isHK @@ -511,8 +366,7 @@ class TypeApplications(val self: Type) extends AnyVal { /** is receiver of the form T#$Apply? */ def isHKApply(implicit ctx: Context): Boolean = self match { - case self @ RefinedType(_, name, _) => Config.newHK && name.isHkArgName && !self.isTypeParam - case TypeRef(_, name) => !Config.newHK && (name == tpnme.hkApplyOBS) + case self @ RefinedType(_, name, _) => name.isHkArgName && !self.isTypeParam case _ => false } @@ -520,18 +374,18 @@ class TypeApplications(val self: Type) extends AnyVal { * of this application exists and is not a lambda trait. * Equivalent to * - * self.classSymbol.exists && !self.classSymbol.isLambdaTrait + * self.classSymbol.exists * * but without forcing anything. */ - def classNotLambda(implicit ctx: Context): Boolean = self.stripTypeVar match { + def safeIsClassRef(implicit ctx: Context): Boolean = self.stripTypeVar match { case self: RefinedOrRecType => - self.parent.classNotLambda + self.parent.safeIsClassRef case self: TypeRef => self.denot.exists && { val sym = self.symbol - if (sym.isClass) !sym.isLambdaTraitOBS - else sym.isCompleted && self.info.isAlias && self.info.bounds.hi.classNotLambda + sym.isClass || + sym.isCompleted && self.info.isAlias } case _ => false @@ -545,22 +399,6 @@ class TypeApplications(val self: Type) extends AnyVal { self } - /** Dealias type if it can be done without forcing anything */ - def saferDealias(implicit ctx: Context): Type = self match { - case self: TypeRef if self.denot.exists && self.symbol.isAliasType && self.symbol.isCompleted => - self.info.bounds.hi.stripTypeVar.safeDealias - case _ => - self - } - - /** Replace references to type parameters with references to hk arguments `this.$hk_i` - * Care is needed not to cause cyclic reference errors, hence `SafeSubstMap`. - */ - def internalizeFrom[T <: Type](tparams: List[Symbol])(implicit ctx: Context): RefinedType => T = - (rt: RefinedType) => - new ctx.SafeSubstMap(tparams, argRefs(rt, tparams.length)) - .apply(self).asInstanceOf[T] - /** Replace references to type parameters with references to hk arguments `this.$hk_i` * Care is needed not to cause cyclic reference errors, hence `SafeSubstMap`. */ @@ -571,7 +409,6 @@ class TypeApplications(val self: Type) extends AnyVal { new ctx.SafeSubstMap(tparams.asInstanceOf[List[Symbol]], argRefs(rt, tparams.length)) .apply(self).asInstanceOf[T] case _ => - assert(Config.newHK) def mapRefs(rt: RecType) = new TypeMap { def apply(t: Type): Type = t match { case rthis: RecThis if tparams contains rthis.binder.parent => RecThis(rt) @@ -587,38 +424,20 @@ class TypeApplications(val self: Type) extends AnyVal { * type T[X] >: L <: U becomes type T >: L <: ([X] -> _ <: U) */ def LambdaAbstract(tparams: List[Symbol])(implicit ctx: Context): Type = { - - /** Replace references to type parameters with references to hk arguments `this.$hk_i` - * Care is needed not to cause cycles, hence `SafeSubstMap`. - */ - def internalize[T <: Type](tp: T) = - (rt: RefinedType) => - new ctx.SafeSubstMap(tparams, argRefs(rt, tparams.length)) - .apply(tp).asInstanceOf[T] - def expand(tp: Type) = - if (Config.newHK) - TypeLambda( - tparams.map(tparam => - tparam.memberBoundsAsSeenFrom(self) - .withBindingKind(BindingKind.fromVariance(tparam.variance)) - .recursify(tparams)), - tp.recursify(tparams)) - else - TypeLambda.applyOBS( - tparams.map(_.variance), - tparams.map(tparam => internalize(self.memberInfo(tparam).bounds)), - internalize(tp)) + TypeLambda( + tparams.map(tparam => + tparam.memberBoundsAsSeenFrom(self) + .withBindingKind(BindingKind.fromVariance(tparam.variance)) + .recursify(tparams)), + tp.recursify(tparams)) assert(!isHK, self) self match { case self: TypeAlias => self.derivedTypeAlias(expand(self.alias.normalizeHkApply)) case self @ TypeBounds(lo, hi) => - if (Config.newHK) - self.derivedTypeBounds(lo, expand(hi.normalizeHkApply)) - else - self.derivedTypeBounds(lo, expand(TypeBounds.upper(hi.normalizeHkApply))) + self.derivedTypeBounds(lo, expand(hi.normalizeHkApply)) case _ => expand(self) } } @@ -652,7 +471,7 @@ class TypeApplications(val self: Type) extends AnyVal { * - going from a wildcard type to its upper bound */ def normalizeHkApply(implicit ctx: Context): Type = self.strictDealias match { - case self1 @ RefinedType(_, rname, _) if Config.newHK && rname.isHkArgName && self1.typeParams.isEmpty => + case self1 @ RefinedType(_, rname, _) if rname.isHkArgName && self1.typeParams.isEmpty => val inst = new InstMap(self) def instTop(tp: Type): Type = tp.strictDealias match { @@ -709,7 +528,7 @@ class TypeApplications(val self: Type) extends AnyVal { * to eta expand them. */ def isEtaExpandable(implicit ctx: Context) = self match { - case self: TypeRef => self.symbol.isClass && !self.name.isLambdaTraitNameOBS + case self: TypeRef => self.symbol.isClass case _ => false } @@ -782,7 +601,7 @@ class TypeApplications(val self: Type) extends AnyVal { def adaptHkVariances(bound: Type)(implicit ctx: Context): Type = { val hkParams = bound.hkTypeParams if (hkParams.isEmpty) self - else if (Config.newHK) { + else { def adaptArg(arg: Type): Type = arg match { case arg @ TypeLambda(tparamBounds, body) if !arg.typeParams.corresponds(hkParams)(_.memberVariance == _.memberVariance) && @@ -804,25 +623,6 @@ class TypeApplications(val self: Type) extends AnyVal { } adaptArg(self) } - else { - def adaptArg(arg: Type): Type = arg match { - case arg: TypeRef if arg.symbol.isLambdaTraitOBS && - !arg.symbol.typeParams.corresponds(hkParams)(_.variance == _.memberVariance) && - arg.symbol.typeParams.corresponds(hkParams)(varianceConforms) => - arg.prefix.select(bound.LambdaTraitOBS) - case arg: RefinedType => - arg.derivedRefinedType(adaptArg(arg.parent), arg.refinedName, arg.refinedInfo) - case arg: RecType => - arg.derivedRecType(adaptArg(arg.parent)) - case arg @ TypeAlias(alias) => - arg.derivedTypeAlias(adaptArg(alias)) - case arg @ TypeBounds(lo, hi) => - arg.derivedTypeBounds(lo, adaptArg(hi)) - case _ => - arg - } - adaptArg(self) - } } /** Encode @@ -843,8 +643,6 @@ class TypeApplications(val self: Type) extends AnyVal { final def appliedTo(args: List[Type])(implicit ctx: Context): Type = /*>|>*/ track("appliedTo") /*<|<*/ { def substHkArgs = new TypeMap { def apply(tp: Type): Type = tp match { - case TypeRef(RefinedThis(rt), name) if rt.eq(self) && name.isHkArgName => - args(name.hkArgIndex) case TypeRef(RecThis(rt), name) if rt.eq(self) && name.isHkArgName => args(name.hkArgIndex) case _ => @@ -886,8 +684,7 @@ class TypeApplications(val self: Type) extends AnyVal { assert(args.nonEmpty) matchParams(self, typParams, args) match { case refined @ RefinedType(_, pname, _) if pname.isHkArgName => - if (Config.newHK) refined.betaReduce - else TypeRef(refined, tpnme.hkApplyOBS) + refined.betaReduce // TODO Move to matchparams case refined => refined } @@ -906,8 +703,7 @@ class TypeApplications(val self: Type) extends AnyVal { case self: TypeRef if !self.symbol.isClass && self.symbol.isCompleting => // This happens when unpickling e.g. scala$collection$generic$GenMapFactory$$CC ctx.warning(i"encountered F-bounded higher-kinded type parameters for ${self.symbol}; assuming they are invariant") - if (Config.newHK) fallbackTypeParams(args map alwaysZero) - else defn.LambdaTraitOBS(args map alwaysZero).typeParams + fallbackTypeParams(args map alwaysZero) case _ => typeParams } @@ -1070,33 +866,4 @@ class TypeApplications(val self: Type) extends AnyVal { case JavaArrayType(elemtp) => elemtp case _ => firstBaseArgInfo(defn.SeqClass) } - - /** Does this type contain RefinedThis type with `target` as its underling - * refinement type? - */ - def containsRefinedThis(target: Type)(implicit ctx: Context): Boolean = { - def recur(tp: Type): Boolean = tp.stripTypeVar match { - case RefinedThis(tp) => - tp eq target - case tp: NamedType => - if (tp.symbol.isClass) !tp.symbol.isStatic && recur(tp.prefix) - else tp.info match { - case TypeAlias(alias) => recur(alias) - case _ => recur(tp.prefix) - } - case tp: RefinedType => - recur(tp.refinedInfo) || recur(tp.parent) - case tp: RecType => - recur(tp.parent) - case tp: TypeBounds => - recur(tp.lo) || recur(tp.hi) - case tp: AnnotatedType => - recur(tp.underlying) - case tp: AndOrType => - recur(tp.tp1) || recur(tp.tp2) - case _ => - false - } - !Config.newHK && recur(self) - } } diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala index c1b275b70..cf3086323 100644 --- a/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/src/dotty/tools/dotc/core/TypeComparer.scala @@ -178,11 +178,8 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { && !tp1.isInstanceOf[WithFixedSym] && !tp2.isInstanceOf[WithFixedSym] ) || - compareHkApplyOBS(tp1, tp2, inOrder = true) || - compareHkApplyOBS(tp2, tp1, inOrder = false) || thirdTryNamed(tp1, tp2) case _ => - compareHkApplyOBS(tp2, tp1, inOrder = false) || secondTry(tp1, tp2) } } @@ -259,7 +256,6 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { if (tp1.prefix.isStable) return false case _ => } - compareHkApplyOBS(tp1, tp2, inOrder = true) || thirdTry(tp1, tp2) case tp1: PolyParam => def flagNothingBound = { @@ -381,7 +377,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { } else // fast path, in particular for refinements resulting from parameterization. isSubRefinements(tp1w.asInstanceOf[RefinedType], tp2, skipped2) && - isSubType(tp1, skipped2) // TODO swap? + isSubType(tp1, skipped2) } compareRefined case tp2: RecType => @@ -547,9 +543,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { * - `B` satisfies predicate `p`. */ private def testLifted(tp1: Type, tp2: Type, tparams: List[MemberBinding], p: Type => Boolean): Boolean = { - val classBounds = - if (Config.newHK) tp2.classSymbols - else tp2.member(tpnme.hkApplyOBS).info.classSymbols + val classBounds = tp2.classSymbols def recur(bcs: List[ClassSymbol]): Boolean = bcs match { case bc :: bcs1 => val baseRef = tp1.baseTypeRef(bc) @@ -564,61 +558,6 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { recur(tp1.baseClasses) } - /** If `projection` is a hk projection T#$apply with a constrainable poly param - * as type constructor and `other` is not a hk projection, then perform the following - * steps: - * - * (1) If not `inOrder` then perform the next steps until they all succeed - * for each base type of other which - * - derives from a class bound of `projection`, - * - has the same number of type parameters than `projection` - * - has type parameter variances which conform to those of `projection`. - * If `inOrder` then perform the same steps on the original `other` type. - * - * (2) Try to eta expand the constructor of `other`. - * - * (3a) In mode `TypevarsMissConetxt` replace the projection's hk constructor parameter - * by the eta expansion of step (2) reapplied to the projection's arguments. - * (3b) In normal mode, try to unify the projection's hk constructor parameter with - * the eta expansion of step(2) - * - * (4) If `inOrder`, test `projection <: other` else test `other <: projection`. - */ - def compareHkApplyOBS(projection: NamedType, other: Type, inOrder: Boolean): Boolean = { - def tryInfer(tp: Type): Boolean = ctx.traceIndented(i"compareHK($projection, $other, inOrder = $inOrder, constr = $tp)", subtyping) { - tp match { - case tp: TypeVar => tryInfer(tp.underlying) - case param: PolyParam if canConstrain(param) => - - def unifyWith(liftedOther: Type): Boolean = { - subtyping.println(i"unify with $liftedOther") - liftedOther.typeConstructor.widen match { - case tycon: TypeRef if tycon.isEtaExpandable && tycon.typeParams.nonEmpty => - val (ok, projection1) = - if (ctx.mode.is(Mode.TypevarsMissContext)) - (true, EtaExpansion(tycon).appliedTo(projection.argInfos)) - else - (tryInstantiate(param, EtaExpansion(tycon)), projection) - ok && - (if (inOrder) isSubType(projection1, other) else isSubType(other, projection1)) - case _ => - false - } - } - val hkTypeParams = param.typeParams - subtyping.println(i"classBounds = ${projection.prefix.member(tpnme.hkApplyOBS).info.classSymbols}") - subtyping.println(i"base classes = ${other.baseClasses}") - subtyping.println(i"type params = ${hkTypeParams.map(_.memberName)}") - if (inOrder) unifyWith(other) - else testLifted(other, projection.prefix, hkTypeParams, unifyWith) - case _ => - false - } - } - !Config.newHK && projection.name == tpnme.hkApplyOBS && !other.isHKApply && - tryInfer(projection.prefix.typeConstructor.dealias) - } - /** Handle subtype tests * * app <:< other if inOrder = true @@ -695,7 +634,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { false } } - Config.newHK && app.isHKApply && !other.isHKApply && { + app.isHKApply && !other.isHKApply && { val reduced = if (inOrder) app else app.normalizeHkApply if (reduced ne app) if (inOrder) isSubType(reduced, other) else isSubType(other, reduced) @@ -824,10 +763,8 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { * rebase both itself and the member info of `tp` on a freshly created skolem type. */ protected def hasMatchingMember(name: Name, tp1: Type, tp2: RefinedType): Boolean = { - val rebindNeeded = tp2.refinementRefersToThis - val base = if (rebindNeeded) ensureStableSingleton(tp1) else tp1 - val rinfo2 = if (rebindNeeded) tp2.refinedInfo.substRefinedThis(tp2, base) else tp2.refinedInfo - val mbr = base.member(name) + val rinfo2 = tp2.refinedInfo + val mbr = tp1.member(name) def qualifies(m: SingleDenotation) = isSubType(m.info, rinfo2) @@ -843,15 +780,13 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { def selfReferentialMatch = tp1.isInstanceOf[SingletonType] && { rinfo2 match { case rinfo2: TypeAlias => - !defn.isBottomType(base.widen) && (base select name) =:= rinfo2.alias + !defn.isBottomType(tp1.widen) && (tp1 select name) =:= rinfo2.alias case _ => false } } - def varianceMatches = true // TODO: fill in - - /*>|>*/ ctx.traceIndented(i"hasMatchingMember($base . $name :? ${tp2.refinedInfo}) ${mbr.info.show} $rinfo2", subtyping) /*<|<*/ { - (memberMatches || selfReferentialMatch) && varianceMatches + /*>|>*/ ctx.traceIndented(i"hasMatchingMember($tp1 . $name :? ${tp2.refinedInfo}) ${mbr.info.show} $rinfo2", subtyping) /*<|<*/ { + memberMatches || selfReferentialMatch } } @@ -870,10 +805,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { * @return The parent type of `tp2` after skipping the matching refinements. */ private def skipMatching(tp1: Type, tp2: RefinedType): Type = tp1 match { - case tp1 @ RefinedType(parent1, name1, rinfo1: TypeAlias) - if name1 == tp2.refinedName && - !tp2.refinementRefersToThis && - !tp1.refinementRefersToThis => + case tp1 @ RefinedType(parent1, name1, rinfo1: TypeAlias) if name1 == tp2.refinedName => tp2.parent match { case parent2: RefinedType => skipMatching(parent1, parent2) case parent2 => parent2 @@ -1224,39 +1156,29 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { * allowing both interpretations. A possible remedy is to be somehow stricter * in where we allow which interpretation. */ - private def liftIfHK(tp1: Type, tp2: Type, op: (Type, Type) => Type) = - if (Config.newHK) { - val tparams1 = tp1.typeParams - val tparams2 = tp2.typeParams - if (tparams1.isEmpty || tparams2.isEmpty) op(tp1, tp2) - else if (tparams1.length != tparams2.length) mergeConflict(tp1, tp2) - else { - val bindings: List[RecType => TypeBounds] = - (tparams1, tparams2).zipped.map { (tparam1, tparam2) => - val b1: RecType => TypeBounds = - tparam1.memberBoundsAsSeenFrom(tp1).recursify(tparams1) - val b2: RecType => TypeBounds = - tparam2.memberBoundsAsSeenFrom(tp2).recursify(tparams2) - (rt: RecType) => (b1(rt) & b2(rt)) - .withBindingKind( - BindingKind.fromVariance( - (tparam1.memberVariance + tparam2.memberVariance) / 2)) - } - val app1: RecType => Type = rt => tp1.appliedTo(argRefs(rt, tparams1.length)) - val app2: RecType => Type = rt => tp2.appliedTo(argRefs(rt, tparams2.length)) - val body: RecType => Type = rt => op(app1(rt), app2(rt)) - TypeLambda(bindings, body) - } - } + private def liftIfHK(tp1: Type, tp2: Type, op: (Type, Type) => Type) = { + val tparams1 = tp1.typeParams + val tparams2 = tp2.typeParams + if (tparams1.isEmpty || tparams2.isEmpty) op(tp1, tp2) + else if (tparams1.length != tparams2.length) mergeConflict(tp1, tp2) else { - val tparams1 = tp1.typeParamSymbols - val tparams2 = tp2.typeParamSymbols - def onlyNamed(tparams: List[TypeSymbol]) = tparams.forall(!_.is(ExpandedName)) - if (tparams1.isEmpty || tparams2.isEmpty || - onlyNamed(tparams1) && onlyNamed(tparams2)) op(tp1, tp2) - else if (tparams1.length != tparams2.length) mergeConflict(tp1, tp2) - else hkCombineOBS(tp1, tp2, tparams1, tparams2, op) + val bindings: List[RecType => TypeBounds] = + (tparams1, tparams2).zipped.map { (tparam1, tparam2) => + val b1: RecType => TypeBounds = + tparam1.memberBoundsAsSeenFrom(tp1).recursify(tparams1) + val b2: RecType => TypeBounds = + tparam2.memberBoundsAsSeenFrom(tp2).recursify(tparams2) + (rt: RecType) => (b1(rt) & b2(rt)) + .withBindingKind( + BindingKind.fromVariance( + (tparam1.memberVariance + tparam2.memberVariance) / 2)) + } + val app1: RecType => Type = rt => tp1.appliedTo(argRefs(rt, tparams1.length)) + val app2: RecType => Type = rt => tp2.appliedTo(argRefs(rt, tparams2.length)) + val body: RecType => Type = rt => op(app1(rt), app2(rt)) + TypeLambda(bindings, body) } + } /** Try to distribute `&` inside type, detect and handle conflicts * @pre !(tp1 <: tp2) && !(tp2 <:< tp1) -- these cases were handled before @@ -1268,10 +1190,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { case tp1: RefinedType => tp2 match { case tp2: RefinedType if tp1.refinedName == tp2.refinedName => - tp1.derivedRefinedType( - tp1.parent & tp2.parent, - tp1.refinedName, - tp1.refinedInfo & tp2.refinedInfo.substRefinedThis(tp2, RefinedThis(tp1))) + tp1.derivedRefinedType(tp1.parent & tp2.parent, tp1.refinedName, tp1.refinedInfo & tp2.refinedInfo) case _ => NoType } diff --git a/src/dotty/tools/dotc/core/TypeOps.scala b/src/dotty/tools/dotc/core/TypeOps.scala index ca49d3d3c..6b75b574e 100644 --- a/src/dotty/tools/dotc/core/TypeOps.scala +++ b/src/dotty/tools/dotc/core/TypeOps.scala @@ -228,7 +228,7 @@ trait TypeOps { this: Context => // TODO: Make standalone object. return tp1.derivedRefinedType( approximateUnion(OrType(tp1.parent, tp2.parent)), tp1.refinedName, - homogenizedUnion(tp1.refinedInfo, tp2.refinedInfo).substRefinedThis(tp2, RefinedThis(tp1))) + homogenizedUnion(tp1.refinedInfo, tp2.refinedInfo)) //.ensuring { x => println(i"approx or $tp1 | $tp2 = $x\n constr = ${ctx.typerState.constraint}"); true } // DEBUG case _ => } diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index 2120706f6..cd1b5739d 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -51,7 +51,7 @@ object Types { * | | +--- SuperType * | | +--- ConstantType * | | +--- MethodParam - * | | +----RefinedThis + * | | +----RecThis * | | +--- SkolemType * | +- PolyParam * | +- RefinedOrRecType -+-- RefinedType @@ -507,9 +507,7 @@ object Types { } def goRefined(tp: RefinedType) = { val pdenot = go(tp.parent) - val rinfo = - if (tp.refinementRefersToThis) tp.refinedInfo.substRefinedThis(tp, pre) - else tp.refinedInfo + val rinfo = tp.refinedInfo if (name.isTypeName) { // simplified case that runs more efficiently val jointInfo = if (rinfo.isAlias) rinfo @@ -577,6 +575,7 @@ object Types { ctx.pendingMemberSearches = name :: ctx.pendingMemberSearches } + //assert(ctx.findMemberCount < 20) try go(this) catch { case ex: Throwable => @@ -964,62 +963,14 @@ object Types { * * P { type T = String, type R = P{...}.T } # R --> String * - * (2) The refinement is a fully instantiated type lambda, and the projected name is "$apply". - * In this case the rhs of the apply is returned with all references to lambda argument types - * substituted by their definitions. - * * (*) normalizes means: follow instantiated typevars and aliases. */ def lookupRefined(name: Name)(implicit ctx: Context): Type = { def loop(pre: Type): Type = pre.stripTypeVar match { case pre: RefinedType => - object instantiate extends TypeMap { - var isSafe = true - def apply(tp: Type): Type = - if (!isSafe) tp - else tp match { - case TypeRef(RefinedThis(`pre`), name) if name.isHkArgName => - member(name).info match { - case TypeAlias(alias) => alias - case _ => isSafe = false; tp - } - case tp: TypeVar if !tp.inst.exists => - isSafe = false - tp - case _ => - mapOver(tp) - } - } - def instArg(tp: Type): Type = tp match { - case tp @ TypeAlias(TypeRef(RefinedThis(`pre`), name)) if name.isHkArgName => - member(name).info match { - case TypeAlias(alias) => tp.derivedTypeAlias(alias) // needed to keep variance - case bounds => bounds - } - case _ => - instantiate(tp) - } - def instTop(tp: Type): Type = tp.stripTypeVar match { - case tp: RefinedType => - tp.derivedRefinedType(instTop(tp.parent), tp.refinedName, instArg(tp.refinedInfo)) - case _ => - instantiate(tp) - } - /** Reduce rhs of $hkApply to make it stand alone */ - def betaReduce(tp: Type) = { - val reduced = instTop(tp) - if (instantiate.isSafe) reduced else NoType - } pre.refinedInfo match { case TypeAlias(alias) => - if (pre.refinedName ne name) loop(pre.parent) - else alias match { - case TypeRef(RefinedThis(`pre`), aliasName) => lookupRefined(aliasName) // (1) - case _ => - if (!pre.refinementRefersToThis) alias - else if (name == tpnme.hkApplyOBS) betaReduce(alias) - else NoType - } + if (pre.refinedName ne name) loop(pre.parent) else alias case _ => loop(pre.parent) } case pre: RecType => @@ -1029,8 +980,6 @@ object Types { candidate } else NoType - case RefinedThis(binder) => - binder.lookupRefined(name) case SkolemType(tp) => tp.lookupRefined(name) case pre: WildcardType => @@ -1219,10 +1168,6 @@ object Types { final def substThisUnlessStatic(cls: ClassSymbol, tp: Type)(implicit ctx: Context): Type = if (cls.isStaticOwner) this else ctx.substThis(this, cls, tp, null) - /** Substitute all occurrences of `SkolemType(binder)` by `tp` */ - final def substRefinedThis(binder: Type, tp: Type)(implicit ctx: Context): Type = - ctx.substRefinedThis(this, binder, tp, null) - /** Substitute all occurrences of `RecThis(binder)` by `tp` */ final def substRecThis(binder: RecType, tp: Type)(implicit ctx: Context): Type = ctx.substRecThis(this, binder, tp, null) @@ -1643,7 +1588,7 @@ object Types { * to an (unbounded) wildcard type. * * (2) Reduce a type-ref `T { X = U; ... } # X` to `U` - * provided `U` does not refer with a RefinedThis to the + * provided `U` does not refer with a RecThis to the * refinement type `T { X = U; ... }` */ def reduceProjection(implicit ctx: Context): Type = { @@ -1715,13 +1660,6 @@ object Types { else if (isType) { val res = prefix.lookupRefined(name) if (res.exists) res - else if (name == tpnme.hkApplyOBS && prefix.classNotLambda) { - // After substitution we might end up with a type like - // `C { type hk$0 = T0; ...; type hk$n = Tn } # $Apply` - // where C is a class. In that case we eta expand `C`. - if (defn.isBottomType(prefix)) prefix.classSymbol.typeRef - else derivedSelect(prefix.EtaExpandCore) - } else if (Config.splitProjections) prefix match { case prefix: AndType => @@ -1999,9 +1937,7 @@ object Types { } object TypeRef { - def checkProjection(prefix: Type, name: TypeName)(implicit ctx: Context) = - if (name == tpnme.hkApplyOBS && prefix.classNotLambda) - assert(false, s"bad type : $prefix.$name does not allow $$Apply projection") + def checkProjection(prefix: Type, name: TypeName)(implicit ctx: Context) = () /** Create type ref with given prefix and name */ def apply(prefix: Type, name: TypeName)(implicit ctx: Context): TypeRef = { @@ -2128,34 +2064,15 @@ object Types { * @param infoFn: A function that produces the info of the refinement declaration, * given the refined type itself. */ - abstract case class RefinedType(private var myParent: Type, refinedName: Name, private var myRefinedInfo: Type) + abstract case class RefinedType(parent: Type, refinedName: Name, refinedInfo: Type) extends RefinedOrRecType with BindingType with MemberBinding { - final def parent = myParent - final def refinedInfo = myRefinedInfo - - private var refinementRefersToThisCache: Boolean = _ - private var refinementRefersToThisKnown: Boolean = false - - def refinementRefersToThis(implicit ctx: Context): Boolean = { - if (!refinementRefersToThisKnown) { - refinementRefersToThisCache = refinedInfo.containsRefinedThis(this) - refinementRefersToThisKnown = true - } - refinementRefersToThisCache - } - override def underlying(implicit ctx: Context) = parent private def badInst = throw new AssertionError(s"bad instantiation: $this") def checkInst(implicit ctx: Context): this.type = { - if (refinedName == tpnme.hkApplyOBS) - parent.stripTypeVar match { - case RefinedType(_, name, _) if name.isHkArgName => // ok - case _ => badInst - } this } @@ -2197,9 +2114,15 @@ object Types { def derivedRefinedType(parent: Type, refinedName: Name, refinedInfo: Type)(implicit ctx: Context): Type = if ((parent eq this.parent) && (refinedName eq this.refinedName) && (refinedInfo eq this.refinedInfo)) this - else - RefinedType(parent, refinedName, rt => refinedInfo.substRefinedThis(this, RefinedThis(rt))) - .betaReduce + else { + // `normalizedRefinedInfo` is `refinedInfo` reduced everywhere via `reduceProjection`. + // (this is achieved as a secondary effect of substRecThis). + // It turns out this normalization is now needed; without it there's + // A Y-check error (incompatible types involving hk lambdas) for dotty itself. + // TODO: investigate and, if possible, drop after revision. + val normalizedRefinedInfo = refinedInfo.substRecThis(dummyRec, dummyRec) + RefinedType(parent, refinedName, normalizedRefinedInfo).betaReduce + } /** Add this refinement to `parent`, provided If `refinedName` is a member of `parent`. */ def wrapIfMember(parent: Type)(implicit ctx: Context): Type = @@ -2232,36 +2155,16 @@ object Types { override def toString = s"RefinedType($parent, $refinedName, $refinedInfo)" } - class CachedRefinedType(refinedName: Name) extends RefinedType(NoType, refinedName, NoType) - - class PreHashedRefinedType(parent: Type, refinedName: Name, refinedInfo: Type, hc: Int) + class CachedRefinedType(parent: Type, refinedName: Name, refinedInfo: Type, hc: Int) extends RefinedType(parent, refinedName, refinedInfo) { myHash = hc override def computeHash = unsupported("computeHash") } object RefinedType { - def make(parent: Type, names: List[Name], infoFns: List[RefinedType => Type])(implicit ctx: Context): Type = + def make(parent: Type, names: List[Name], infos: List[Type])(implicit ctx: Context): Type = if (names.isEmpty) parent - else make(RefinedType(parent, names.head, infoFns.head), names.tail, infoFns.tail) - - def recursive(parentFn: RefinedType => Type, names: List[Name], infoFns: List[RefinedType => Type])(implicit ctx: Context): RefinedType = { - val refinements: List[RefinedType] = names.map(new CachedRefinedType(_)) - val last = refinements.last - (refinements, infoFns).zipped.foreach((rt, infoFn) => rt.myRefinedInfo = infoFn(last)) - (parentFn(last) /: refinements) { (parent, rt) => - rt.myParent = parent - ctx.base.uniqueRefinedTypes.enterIfNew(rt).checkInst - }.asInstanceOf[RefinedType] - } - - def apply(parent: Type, name: Name, infoFn: RefinedType => Type)(implicit ctx: Context): RefinedType = { - assert(!ctx.erasedTypes || ctx.mode.is(Mode.Printing)) - val res: RefinedType = new CachedRefinedType(name) - res.myParent = parent - res.myRefinedInfo = infoFn(res) - ctx.base.uniqueRefinedTypes.enterIfNew(res).checkInst - } + else make(RefinedType(parent, names.head, infos.head), names.tail, infos.tail) def apply(parent: Type, name: Name, info: Type)(implicit ctx: Context): RefinedType = { assert(!ctx.erasedTypes) @@ -2722,7 +2625,7 @@ object Types { } } - // ----- Bound types: MethodParam, PolyParam, RefinedThis -------------------------- + // ----- Bound types: MethodParam, PolyParam -------------------------- abstract class BoundType extends CachedProxyType with ValueType { type BT <: Type @@ -2806,22 +2709,6 @@ object Types { } } - /** a this-reference to an enclosing refined type `binder`. */ - case class RefinedThis(binder: RefinedType) extends BoundType with SingletonType { - type BT = RefinedType - override def underlying(implicit ctx: Context) = binder - def copyBoundType(bt: BT) = RefinedThis(bt) - - // need to customize hashCode and equals to prevent infinite recursion for - // refinements that refer to the refinement type via this - override def computeHash = addDelta(binder.identityHash, 41) - override def equals(that: Any) = that match { - case that: RefinedThis => this.binder eq that.binder - case _ => false - } - override def toString = s"RefinedThis(${binder.hashCode})" - } - /** a self-reference to an enclosing recursive type. */ case class RecThis(binder: RecType) extends BoundType with SingletonType { type BT = RecType @@ -3892,6 +3779,8 @@ object Types { class MergeError(msg: String, val tp1: Type, val tp2: Type) extends TypeError(msg) + @sharable val dummyRec = new RecType(rt => NoType) + // ----- Debug --------------------------------------------------------- @sharable var debugTrace = false diff --git a/src/dotty/tools/dotc/core/Uniques.scala b/src/dotty/tools/dotc/core/Uniques.scala index b00508d60..cb9670c69 100644 --- a/src/dotty/tools/dotc/core/Uniques.scala +++ b/src/dotty/tools/dotc/core/Uniques.scala @@ -107,8 +107,8 @@ object Uniques { def enterIfNew(parent: Type, refinedName: Name, refinedInfo: Type): RefinedType = { val h = doHash(refinedName, refinedInfo, parent) - def newType = new PreHashedRefinedType(parent, refinedName, refinedInfo, h) - if (monitored) recordCaching(h, classOf[PreHashedRefinedType]) + def newType = new CachedRefinedType(parent, refinedName, refinedInfo, h) + if (monitored) recordCaching(h, classOf[CachedRefinedType]) if (h == NotCached) newType else { val r = findPrevious(h, parent, refinedName, refinedInfo) diff --git a/src/dotty/tools/dotc/core/tasty/TastyFormat.scala b/src/dotty/tools/dotc/core/tasty/TastyFormat.scala index e9708961a..38d55e0e8 100644 --- a/src/dotty/tools/dotc/core/tasty/TastyFormat.scala +++ b/src/dotty/tools/dotc/core/tasty/TastyFormat.scala @@ -259,8 +259,7 @@ object TastyFormat { final val TYPEREFdirect = 66 final val TERMREFpkg = 67 final val TYPEREFpkg = 68 - final val REFINEDthis = 69 - final val RECthis = REFINEDthis // !!! + final val RECthis = 69 final val BYTEconst = 70 final val SHORTconst = 71 final val CHARconst = 72 diff --git a/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/src/dotty/tools/dotc/core/tasty/TreePickler.scala index 9be5c8bcf..d6e6c4d6b 100644 --- a/src/dotty/tools/dotc/core/tasty/TreePickler.scala +++ b/src/dotty/tools/dotc/core/tasty/TreePickler.scala @@ -211,11 +211,6 @@ class TreePickler(pickler: TastyPickler) { case tpe: SuperType => writeByte(SUPERtype) withLength { pickleType(tpe.thistpe); pickleType(tpe.supertpe)} - case tpe: RefinedThis => - writeByte(REFINEDthis) - val binderAddr = pickledTypes.get(tpe.binder) - assert(binderAddr != null, tpe.binder) - writeRef(binderAddr.asInstanceOf[Addr]) case tpe: RecThis => writeByte(RECthis) val binderAddr = pickledTypes.get(tpe.binder) diff --git a/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index d9a062263..2d230c630 100644 --- a/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -260,7 +260,7 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) { val parent = readType() val ttag = nextUnsharedTag if (ttag == TYPEBOUNDS || ttag == TYPEALIAS) name = name.toTypeName - RefinedType(parent, name, rt => registeringType(rt, readType())) + RefinedType(parent, name, readType()) // Note that the lambda "rt => ..." is not equivalent to a wildcard closure! // Eta expansion of the latter puts readType() out of the expression. case APPLIEDtype => @@ -325,8 +325,6 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) { readPackageRef().termRef case TYPEREF => val name = readName().toTypeName - if (name.isLambdaTraitNameOBS) // Make sure corresponding lambda trait exists - defn.LambdaTraitOBS(name.lambdaTraitVariancesOBS) TypeRef(readType(), name) case TERMREF => readNameSplitSig() match { @@ -337,11 +335,8 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) { ThisType.raw(readType().asInstanceOf[TypeRef]) case RECtype => RecType(rt => registeringType(rt, readType())) - case REFINEDthis => - readTypeRef() match { - case t: RefinedType => RefinedThis(t) - case t: RecType => RecThis(t) - } + case RECthis => + RecThis(readTypeRef().asInstanceOf[RecType]) case SHARED => val ref = readAddr() typeAtAddr.getOrElseUpdate(ref, forkAt(ref).readType()) diff --git a/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala b/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala index 557a9df74..18a4e83b6 100644 --- a/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala +++ b/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala @@ -632,8 +632,6 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas case info => tp.derivedRefinedType(parent1, name, info) } - case tp @ TypeRef(pre, tpnme.hkApplyOBS) => - tp.derivedSelect(elim(pre)) case _ => tp } diff --git a/src/dotty/tools/dotc/printing/PlainPrinter.scala b/src/dotty/tools/dotc/printing/PlainPrinter.scala index a9f5b771a..a8888fd3c 100644 --- a/src/dotty/tools/dotc/printing/PlainPrinter.scala +++ b/src/dotty/tools/dotc/printing/PlainPrinter.scala @@ -50,9 +50,6 @@ class PlainPrinter(_ctx: Context) extends Printer { homogenize(tp1) & homogenize(tp2) case OrType(tp1, tp2) => homogenize(tp1) | homogenize(tp2) - case tp @ TypeRef(_, tpnme.hkApplyOBS) => - val tp1 = tp.reduceProjection - if (tp1 eq tp) tp else homogenize(tp1) case tp: RefinedType => tp.normalizeHkApply case tp: SkolemType => @@ -250,8 +247,6 @@ class PlainPrinter(_ctx: Context) extends Printer { val idx = openRecs.reverse.indexOf(tp.binder) if (idx >= 0) selfRecName(idx + 1) else "{...}.this" // TODO move underlying type to an addendum, e.g. ... z3 ... where z3: ... - case tp: RefinedThis => - s"${nameString(tp.binder.typeSymbol)}{...}.this" case tp: SkolemType => if (homogenizedView) toText(tp.info) else tp.repr } diff --git a/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/src/dotty/tools/dotc/printing/RefinedPrinter.scala index 61e29982b..3da977b31 100644 --- a/src/dotty/tools/dotc/printing/RefinedPrinter.scala +++ b/src/dotty/tools/dotc/printing/RefinedPrinter.scala @@ -118,9 +118,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { if (defn.isTupleClass(cls)) return toTextTuple(args) return (toTextLocal(tycon) ~ "[" ~ Text(args map argText, ", ") ~ "]").close case tp @ TypeLambda(argBoundss, body) => - val variances = - if (Config.newHK) argBoundss.map(b => BindingKind.toVariance(b.bindingKind)) - else tp.classSymbol.typeParams.map(_.variance) + val variances = argBoundss.map(b => BindingKind.toVariance(b.bindingKind)) val prefix = ((('X' - 'A') + lambdaNestingLevel) % 26 + 'A').toChar val paramNames = argBoundss.indices.toList.map(prefix.toString + _) val instantiate = new TypeMap { diff --git a/src/dotty/tools/dotc/sbt/ExtractAPI.scala b/src/dotty/tools/dotc/sbt/ExtractAPI.scala index c0a3c3dfe..d4b38c66e 100644 --- a/src/dotty/tools/dotc/sbt/ExtractAPI.scala +++ b/src/dotty/tools/dotc/sbt/ExtractAPI.scala @@ -403,8 +403,8 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder apiType(tpe) case tp: ThisType => apiThis(tp.cls) - case RefinedThis(binder) => - apiThis(binder.typeSymbol) + case RecThis(binder) => + apiThis(binder.typeSymbol) // !!! this is almost certainly wrong !!! case tp: ParamType => new api.ParameterRef(tp.paramName.toString) case tp: LazyRef => diff --git a/src/dotty/tools/dotc/sbt/ExtractDependencies.scala b/src/dotty/tools/dotc/sbt/ExtractDependencies.scala index 1f19a1058..026a518ce 100644 --- a/src/dotty/tools/dotc/sbt/ExtractDependencies.scala +++ b/src/dotty/tools/dotc/sbt/ExtractDependencies.scala @@ -163,8 +163,7 @@ private class ExtractDependenciesCollector(implicit val ctx: Context) extends tp sym.eq(NoSymbol) || sym.isEffectiveRoot || sym.isAnonymousFunction || - sym.isAnonymousClass || - sym.isLambdaTraitOBS + sym.isAnonymousClass private def addInheritanceDependency(sym: Symbol): Unit = _topLevelInheritanceDependencies += sym.topLevelClass diff --git a/src/dotty/tools/dotc/typer/Applications.scala b/src/dotty/tools/dotc/typer/Applications.scala index cdbf692cd..caae422d3 100644 --- a/src/dotty/tools/dotc/typer/Applications.scala +++ b/src/dotty/tools/dotc/typer/Applications.scala @@ -634,7 +634,6 @@ trait Applications extends Compatibility { self: Typer => typedFn.tpe.widen match { case pt: PolyType => if (typedArgs.length <= pt.paramBounds.length && !isNamed) - typedArgs = typedArgs.zipWithConserve(pt.paramBounds)(adaptTypeArg) if (typedFn.symbol == defn.Predef_classOf && typedArgs.nonEmpty) { val arg = typedArgs.head checkClassType(arg.tpe, arg.pos, traitReq = false, stablePrefixReq = false) @@ -644,9 +643,6 @@ trait Applications extends Compatibility { self: Typer => assignType(cpy.TypeApply(tree)(typedFn, typedArgs), typedFn, typedArgs) } - def adaptTypeArg(tree: tpd.Tree, bound: Type)(implicit ctx: Context): tpd.Tree = - if (Config.newHK) tree else tree.withType(tree.tpe.etaExpandIfHK(bound)) - /** Rewrite `new Array[T](....)` if T is an unbounded generic to calls to newGenericArray. * It is performed during typer as creation of generic arrays needs a classTag. * we rely on implicit search to find one. diff --git a/src/dotty/tools/dotc/typer/Implicits.scala b/src/dotty/tools/dotc/typer/Implicits.scala index 1b02f7e70..a5246cf6b 100644 --- a/src/dotty/tools/dotc/typer/Implicits.scala +++ b/src/dotty/tools/dotc/typer/Implicits.scala @@ -284,13 +284,10 @@ trait ImplicitRunInfo { self: RunInfo => override implicit protected val ctx: Context = liftingCtx override def stopAtStatic = true def apply(tp: Type) = tp match { - case tp: TypeRef if tp.symbol.isLambdaTraitOBS => - defn.AnyType case tp: TypeRef if tp.symbol.isAbstractOrAliasType => val pre = tp.prefix def joinClass(tp: Type, cls: ClassSymbol) = - if (cls.isLambdaTraitOBS) tp - else AndType.make(tp, cls.typeRef.asSeenFrom(pre, cls.owner)) + AndType.make(tp, cls.typeRef.asSeenFrom(pre, cls.owner)) val lead = if (tp.prefix eq NoPrefix) defn.AnyType else apply(tp.prefix) (lead /: tp.classSymbols)(joinClass) case tp: TypeVar => diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala index bc8f8e281..bf36942e0 100644 --- a/src/dotty/tools/dotc/typer/Namer.scala +++ b/src/dotty/tools/dotc/typer/Namer.scala @@ -973,29 +973,6 @@ class Namer { typer: Typer => } ensureUpToDate(sym.typeRef, dummyInfo) ensureUpToDate(sym.typeRef.appliedTo(tparamSyms.map(_.typeRef)), TypeBounds.empty) - - if (Config.newHK) sym.info - else etaExpandArgsOBS.apply(sym.info) - } - - /** Eta expand all class types C appearing as arguments to a higher-kinded - * type parameter to type lambdas, e.g. [HK0] => C[HK0]. This is necessary - * because in `typedAppliedTypeTree` we might have missed some eta expansions - * of arguments in F-bounds, because the recursive type was initialized with - * TypeBounds.empty. - */ - def etaExpandArgsOBS(implicit ctx: Context) = new TypeMap { - def apply(tp: Type): Type = tp match { - case tp: RefinedType => - val args = tp.argInfos.mapconserve(this) - if (args.nonEmpty) { - val tycon = tp.withoutArgs(args) - val tycon1 = this(tycon) - val tparams = tycon.typeParams - val args1 = if (args.length == tparams.length) etaExpandIfHK(tparams, args) else args - if ((tycon1 eq tycon) && (args1 eq args)) tp else tycon1.appliedTo(args1) - } else mapOver(tp) - case _ => mapOver(tp) - } + sym.info } } diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala index 96bc2ab35..2ab06bf70 100644 --- a/src/dotty/tools/dotc/typer/Typer.scala +++ b/src/dotty/tools/dotc/typer/Typer.scala @@ -949,8 +949,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit (if (isVarPattern(arg)) desugar.patternVar(arg) else arg, tparam.memberBounds) else (arg, WildcardType) - val arg1 = typed(desugaredArg, argPt) - adaptTypeArg(arg1, tparam.memberBounds) + typed(desugaredArg, argPt) } args.zipWithConserve(tparams)(typedArg(_, _)).asInstanceOf[List[Tree]] } |