diff options
-rw-r--r-- | src/dotty/tools/dotc/config/Config.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/ConstraintHandling.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/MemberBinding.scala | 35 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/NameOps.scala | 15 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/StdNames.scala | 6 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Symbols.scala | 12 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/TypeApplications.scala | 344 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/TypeComparer.scala | 175 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/TypeOps.scala | 3 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/TypeParamInfo.scala | 29 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Types.scala | 82 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/tasty/TreePickler.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/printing/PlainPrinter.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/printing/RefinedPrinter.scala | 30 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/TypeAssigner.scala | 18 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Typer.scala | 4 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Variances.scala | 4 |
17 files changed, 112 insertions, 653 deletions
diff --git a/src/dotty/tools/dotc/config/Config.scala b/src/dotty/tools/dotc/config/Config.scala index cd2b7ea4b..eba42e881 100644 --- a/src/dotty/tools/dotc/config/Config.scala +++ b/src/dotty/tools/dotc/config/Config.scala @@ -10,8 +10,6 @@ object Config { final val checkCacheMembersNamed = false - final val newHK = true - /** When updating a constraint bound, check that the constrained parameter * does not appear at the top-level of either of its bounds. */ diff --git a/src/dotty/tools/dotc/core/ConstraintHandling.scala b/src/dotty/tools/dotc/core/ConstraintHandling.scala index 44b6abe12..ace441566 100644 --- a/src/dotty/tools/dotc/core/ConstraintHandling.scala +++ b/src/dotty/tools/dotc/core/ConstraintHandling.scala @@ -286,8 +286,6 @@ trait ConstraintHandling { if (!addParamBound(bound)) NoType else if (fromBelow) defn.NothingType else defn.AnyType - case bound: RefinedType if !Config.newHK => - bound.normalizeHkApplyOLD case _ => bound } diff --git a/src/dotty/tools/dotc/core/MemberBinding.scala b/src/dotty/tools/dotc/core/MemberBinding.scala deleted file mode 100644 index bff8b30a0..000000000 --- a/src/dotty/tools/dotc/core/MemberBinding.scala +++ /dev/null @@ -1,35 +0,0 @@ -package dotty.tools.dotc.core - -import Names.Name -import Contexts.Context -import Types.{Type, TypeBounds} - -/** A common super trait of Symbol and Refinement. - * Used to capture the attributes of type parameters - * which can be implemented as either symbols or refinements. - * TODO: Rename (TypeParamInfo?) - */ -trait MemberBinding { - - /** Does this binding represent a type parameter? - * Only in that case the rest of the binding's methods are significant. - */ - def isTypeParam(implicit ctx: Context): Boolean - - /** The name of the member */ - def memberName(implicit ctx: Context): Name - - /** The info of the member */ - def memberBounds(implicit ctx: Context): TypeBounds - - /** The info of the member as seen from a prefix type. - * This can be different from `memberInfo` if the binding - * is a type symbol of a class. - */ - def memberBoundsAsSeenFrom(pre: Type)(implicit ctx: Context): TypeBounds - - /** The variance of the type parameter - * @pre: isTypeParam = true - */ - def memberVariance(implicit ctx: Context): Int -}
\ No newline at end of file diff --git a/src/dotty/tools/dotc/core/NameOps.scala b/src/dotty/tools/dotc/core/NameOps.scala index 120540dc7..f5e0eb8cd 100644 --- a/src/dotty/tools/dotc/core/NameOps.scala +++ b/src/dotty/tools/dotc/core/NameOps.scala @@ -101,21 +101,6 @@ object NameOps { name.length > 0 && name.last == '=' && name.head != '=' && isOperatorPart(name.head) } - /** Is this the name of a higher-kinded type parameter of a Lambda? */ - def isHkArgNameOLD = - name.length > 0 && - name.head == tpnme.hkArgPrefixHeadOLD && - name.startsWith(tpnme.hkArgPrefixOLD) && { - val digits = name.drop(tpnme.hkArgPrefixLengthOLD) - digits.length <= 4 && digits.forall(_.isDigit) - } - - /** The index of the higher-kinded type parameter with this name. - * Pre: isLambdaArgName. - */ - def hkArgIndexOLD: Int = - name.drop(tpnme.hkArgPrefixLengthOLD).toString.toInt - /** 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 0adf80d8f..778d13cab 100644 --- a/src/dotty/tools/dotc/core/StdNames.scala +++ b/src/dotty/tools/dotc/core/StdNames.scala @@ -529,10 +529,6 @@ object StdNames { val synthSwitch: N = "$synthSwitch" - val hkArgPrefixOLD: N = "$hk" - val hkArgPrefixHeadOLD: Char = hkArgPrefixOLD.head - val hkArgPrefixLengthOLD: Int = hkArgPrefixOLD.length - // unencoded operators object raw { final val AMP : N = "&" @@ -746,8 +742,6 @@ object StdNames { def syntheticLambdaParamNames(num: Int): List[TypeName] = (0 until num).map(syntheticLambdaParamName)(breakOut) - def hkArgOLD(n: Int): TypeName = hkArgPrefixOLD ++ n.toString - final val Conforms = encode("<:<") } diff --git a/src/dotty/tools/dotc/core/Symbols.scala b/src/dotty/tools/dotc/core/Symbols.scala index c7eb54812..df8bc8116 100644 --- a/src/dotty/tools/dotc/core/Symbols.scala +++ b/src/dotty/tools/dotc/core/Symbols.scala @@ -367,7 +367,7 @@ object Symbols { * @param coord The coordinates of the symbol (a position or an index) * @param id A unique identifier of the symbol (unique per ContextBase) */ - class Symbol private[Symbols] (val coord: Coord, val id: Int) extends DotClass with MemberBinding with printing.Showable { + class Symbol private[Symbols] (val coord: Coord, val id: Int) extends DotClass with TypeParamInfo with printing.Showable { type ThisName <: Name @@ -489,12 +489,12 @@ object Symbols { */ def pos: Position = if (coord.isPosition) coord.toPosition else NoPosition - // MemberBinding methods + // TypeParamInfo methods def isTypeParam(implicit ctx: Context) = denot.is(TypeParam) - def memberName(implicit ctx: Context): Name = name - def memberBounds(implicit ctx: Context) = denot.info.bounds - def memberBoundsAsSeenFrom(pre: Type)(implicit ctx: Context) = pre.memberInfo(this).bounds - def memberVariance(implicit ctx: Context) = denot.variance + def paramName(implicit ctx: Context): Name = name + def paramBounds(implicit ctx: Context) = denot.info.bounds + def paramBoundsAsSeenFrom(pre: Type)(implicit ctx: Context) = pre.memberInfo(this).bounds + def paramVariance(implicit ctx: Context) = denot.variance // -------- Printing -------------------------------------------------------- diff --git a/src/dotty/tools/dotc/core/TypeApplications.scala b/src/dotty/tools/dotc/core/TypeApplications.scala index e989e42b7..a09039521 100644 --- a/src/dotty/tools/dotc/core/TypeApplications.scala +++ b/src/dotty/tools/dotc/core/TypeApplications.scala @@ -46,67 +46,16 @@ object TypeApplications { /** Does the variance of type parameter `tparam1` conform to the variance of type parameter `tparam2`? */ - def varianceConforms(tparam1: MemberBinding, tparam2: MemberBinding)(implicit ctx: Context): Boolean = - varianceConforms(tparam1.memberVariance, tparam2.memberVariance) + def varianceConforms(tparam1: TypeParamInfo, tparam2: TypeParamInfo)(implicit ctx: Context): Boolean = + varianceConforms(tparam1.paramVariance, tparam2.paramVariance) /** Doe the variances of type parameters `tparams1` conform to the variances * of corresponding type parameters `tparams2`? * This is only the case of `tparams1` and `tparams2` have the same length. */ - def variancesConform(tparams1: List[MemberBinding], tparams2: List[MemberBinding])(implicit ctx: Context): Boolean = + def variancesConform(tparams1: List[TypeParamInfo], tparams2: List[TypeParamInfo])(implicit ctx: Context): Boolean = tparams1.corresponds(tparams2)(varianceConforms) - def fallbackTypeParamsOLD(variances: List[Int])(implicit ctx: Context): List[MemberBinding] = { - def memberBindings(vs: List[Int]): Type = vs match { - case Nil => NoType - case v :: vs1 => - RefinedType( - memberBindings(vs1), - tpnme.hkArgOLD(vs1.length), - TypeBounds.empty.withBindingKind(BindingKind.fromVariance(v))) - } - def decompose(t: Type, acc: List[MemberBinding]): List[MemberBinding] = t match { - case t: RefinedType => decompose(t.parent, t :: acc) - case NoType => acc - } - decompose(memberBindings(variances), Nil) - } - - /** Extractor for - * - * [v1 X1: B1, ..., vn Xn: Bn] -> T - * ==> - * ([X_i := this.$hk_i] T) { type v_i $hk_i: (new)B_i } - */ - object TypeLambdaOLD { - def apply(argBindingFns: List[RecType => TypeBounds], - bodyFn: RecType => Type)(implicit ctx: Context): Type = { - val argNames = argBindingFns.indices.toList.map(tpnme.hkArgOLD) - var idx = 0 - RecType.closeOver(rt => - (bodyFn(rt) /: argBindingFns) { (parent, argBindingFn) => - val res = RefinedType(parent, tpnme.hkArgOLD(idx), argBindingFn(rt)) - idx += 1 - res - }) - } - - 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) - } - decompose(tp, Nil) match { - case (Nil, _) => None - case x => Some(x) - } - } - } - /** Extractor for * * [v1 X1: B1, ..., vn Xn: Bn] -> C[X1, ..., Xn] @@ -118,33 +67,14 @@ object TypeApplications { */ object EtaExpansion { def apply(tycon: Type)(implicit ctx: Context) = { - if (Config.newHK) assert(tycon.typeParams.nonEmpty, tycon) - else assert(tycon.isEtaExpandableOLD) + assert(tycon.typeParams.nonEmpty, tycon) tycon.EtaExpand(tycon.typeParamSymbols) } - def unapply(tp: Type)(implicit ctx: Context): Option[TypeRef] = - if (Config.newHK) - tp match { - case tp @ TypeLambda(tparams, AppliedType(fn: TypeRef, args)) - if (args == tparams.map(_.toArg)) => Some(fn) - case _ => None - } - else { - def argsAreForwarders(args: List[Type], n: Int): Boolean = args match { - case Nil => - n == 0 - case TypeRef(RecThis(rt), sel) :: args1 if false => - rt.eq(tp) && sel == tpnme.hkArgOLD(n - 1) && argsAreForwarders(args1, n - 1) - case _ => - false - } - tp match { - case TypeLambdaOLD(argBounds, AppliedType(fn: TypeRef, args)) - if argsAreForwarders(args, tp.typeParams.length) => Some(fn) - case _ => None - } - } + def unapply(tp: Type)(implicit ctx: Context): Option[TypeRef] = tp match { + case tp @ TypeLambda(tparams, AppliedType(fn: TypeRef, args)) if (args == tparams.map(_.toArg)) => Some(fn) + case _ => None + } } /** Extractor for type application T[U_1, ..., U_n]. This is the refined type @@ -165,13 +95,13 @@ object TypeApplications { refinements = rt :: refinements tycon = rt.parent.stripTypeVar } - def collectArgs(tparams: List[MemberBinding], + def collectArgs(tparams: List[TypeParamInfo], refinements: List[RefinedType], argBuf: mutable.ListBuffer[Type]): Option[(Type, List[Type])] = refinements match { case Nil if tparams.isEmpty && argBuf.nonEmpty => Some((tycon, argBuf.toList)) case RefinedType(_, rname, rinfo) :: refinements1 - if tparams.nonEmpty && rname == tparams.head.memberName => + if tparams.nonEmpty && rname == tparams.head.paramName => collectArgs(tparams.tail, refinements1, argBuf += rinfo.argInfo) case _ => None @@ -186,44 +116,16 @@ object TypeApplications { /** Adapt all arguments to possible higher-kinded type parameters using etaExpandIfHK */ - def etaExpandIfHK(tparams: List[MemberBinding], args: List[Type])(implicit ctx: Context): List[Type] = + def etaExpandIfHK(tparams: List[TypeParamInfo], args: List[Type])(implicit ctx: Context): List[Type] = if (tparams.isEmpty) args else { - def bounds(tparam: MemberBinding) = tparam match { + def bounds(tparam: TypeParamInfo) = tparam match { case tparam: Symbol => tparam.infoOrCompleter - case tparam: RefinedType if !Config.newHK => tparam.memberBounds - case tparam: LambdaParam => tparam.memberBounds + case tparam: LambdaParam => tparam.paramBounds } args.zipWithConserve(tparams)((arg, tparam) => arg.etaExpandIfHK(bounds(tparam))) } - /** The references `<rt>.this.$hk0, ..., <rt>.this.$hk<n-1>`. */ - def argRefsOLD(rt: RecType, n: Int)(implicit ctx: Context) = - List.range(0, n).map(i => RecThis(rt).select(tpnme.hkArgOLD(i))) - - private class InstMapOLD(fullType: Type)(implicit ctx: Context) extends TypeMap { - var localRecs: Set[RecType] = Set.empty - var keptRefs: Set[Name] = Set.empty - var tyconIsHK: Boolean = true - def apply(tp: Type): Type = tp match { - case tp @ TypeRef(RecThis(rt), sel) if sel.isHkArgNameOLD && localRecs.contains(rt) => - fullType.member(sel).info match { - case TypeAlias(alias) => apply(alias) - case _ => keptRefs += sel; tp - } - case tp: TypeVar if !tp.inst.exists => - val bounds = tp.instanceOpt.orElse(ctx.typeComparer.bounds(tp.origin)) - bounds.foreachPart { - case TypeRef(RecThis(rt), sel) if sel.isHkArgNameOLD && localRecs.contains(rt) => - keptRefs += sel - case _ => - } - tp - case _ => - mapOver(tp) - } - } - /** A type map that tries to reduce a (part of) the result type of the type lambda `tycon` * with the given `args`(some of which are wildcard arguments represented by type bounds). * Non-wildcard arguments are substituted everywhere as usual. A wildcard argument @@ -281,7 +183,7 @@ class TypeApplications(val self: Type) extends AnyVal { * with the bounds on its hk args. See `LambdaAbstract`, where these * types get introduced, and see `isBoundedLambda` below for the test. */ - final def typeParams(implicit ctx: Context): List[MemberBinding] = /*>|>*/ track("typeParams") /*<|<*/ { + final def typeParams(implicit ctx: Context): List[TypeParamInfo] = /*>|>*/ track("typeParams") /*<|<*/ { self match { case self: ClassInfo => self.cls.typeParams @@ -293,8 +195,7 @@ class TypeApplications(val self: Type) extends AnyVal { else if (!tsym.isCompleting) tsym.info.typeParams else Nil case self: RefinedType => - val precedingParams = self.parent.typeParams.filterNot(_.memberName == self.refinedName) - if (self.isTypeParam) precedingParams :+ self else precedingParams + self.parent.typeParams.filterNot(_.paramName == self.refinedName) case self: RecType => self.parent.typeParams case _: HKApply | _: SingletonType => @@ -309,7 +210,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] = + final def hkTypeParams(implicit ctx: Context): List[TypeParamInfo] = if (isHK) typeParams else Nil /** If `self` is a generic class, its type parameter symbols, otherwise Nil */ @@ -384,7 +285,7 @@ class TypeApplications(val self: Type) extends AnyVal { /** 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 => !Config.newHK && self.isTypeParam + case self: RefinedType => false case self: TypeLambda => true case self: HKApply => false case self: SingletonType => false @@ -410,8 +311,7 @@ class TypeApplications(val self: Type) extends AnyVal { if (!tsym.isCompleting || tsym.isAliasType) tsym.info.knownHK else 0 } - case self: RefinedType => - if (!Config.newHK && self.isTypeParam) 1 else -1 + case self: RefinedType => -1 case self: TypeLambda => 1 case self: HKApply => -1 case self: SingletonType => -1 @@ -423,12 +323,6 @@ class TypeApplications(val self: Type) extends AnyVal { case _ => -1 } - /** is receiver a higher-kinded application? */ - def isHKApplyOLD(implicit ctx: Context): Boolean = self match { - case self @ RefinedType(_, name, _) => name.isHkArgNameOLD && !self.isTypeParam - case _ => false - } - /** True if it can be determined without forcing that the class symbol * of this application exists. Equivalent to * @@ -457,25 +351,6 @@ class TypeApplications(val self: Type) extends AnyVal { 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 recursifyOLD[T <: Type](tparams: List[MemberBinding])(implicit ctx: Context): RecType => T = - tparams match { - case (_: Symbol) :: _ => - (rt: RecType) => - new ctx.SafeSubstMap(tparams.asInstanceOf[List[Symbol]], argRefsOLD(rt, tparams.length)) - .apply(self).asInstanceOf[T] - case _ => - def mapRefs(rt: RecType) = new TypeMap { - def apply(t: Type): Type = t match { - case rthis: RecThis if tparams contains rthis.binder.parent => RecThis(rt) - case _ => mapOver(t) - } - } - mapRefs(_).apply(self).asInstanceOf[T] - } - /** Lambda abstract `self` with given type parameters. Examples: * * type T[X] = U becomes type T = [X] -> U @@ -485,124 +360,18 @@ class TypeApplications(val self: Type) extends AnyVal { */ def LambdaAbstract(tparams: List[Symbol])(implicit ctx: Context): Type = { def expand(tp: Type) = - if (Config.newHK) - TypeLambda( - tpnme.syntheticLambdaParamNames(tparams.length), tparams.map(_.variance))( - tl => tparams.map(tparam => tl.lifted(tparams, tparam.info).bounds), - tl => tl.lifted(tparams, tp)) - else - TypeLambdaOLD( - tparams.map(tparam => - tparam.memberBoundsAsSeenFrom(self) - .withBindingKind(BindingKind.fromVariance(tparam.variance)) - .recursifyOLD(tparams)), - tp.recursifyOLD(tparams)) - + TypeLambda( + tpnme.syntheticLambdaParamNames(tparams.length), tparams.map(_.variance))( + tl => tparams.map(tparam => tl.lifted(tparams, tparam.info).bounds), + tl => tl.lifted(tparams, tp)) assert(!isHK, self) - if (Config.newHK) self match { + self match { case self: TypeAlias => self.derivedTypeAlias(expand(self.alias)) case self @ TypeBounds(lo, hi) => self.derivedTypeBounds(lo, expand(hi)) case _ => expand(self) } - else self match { - case self: TypeAlias => - self.derivedTypeAlias(expand(self.alias.normalizeHkApplyOLD)) - case self @ TypeBounds(lo, hi) => - self.derivedTypeBounds(lo, expand(hi.normalizeHkApplyOLD)) - case _ => expand(self) - } - } - - /** If `self` is a * type, perform the following rewritings: - * - * 1. For every occurrence of `z.$hk_i`, where `z` is a RecThis type that refers - * to some recursive type in `self`, if the member of `self.hk$i` has an alias - * type `= U`: - * - * z.$hk_i --> U - * - * 2. For every top-level binding `type A = z.$hk_i$, where `z` is a RecThis type that refers - * to some recursive type in `self`, if the member of `self` has bounds `S..U`: - * - * type A = z.$hk_i --> type A >: S <: U - * - * 3. If the type constructor preceding all bindings is a * type, delete every top-level - * binding `{ type $hk_i ... }` where `$hk_i` does not appear in the prefix of the binding. - * I.e. - * - * T { type $hk_i ... } --> T - * - * If `$hk_i` does not appear in `T`. - * - * A binding is top-level if it can be reached by - * - * - following aliases unless the type is a LazyRef - * (need to keep cycle breakers around, see i974.scala) - * - dropping refinements and rec-types - * - going from a wildcard type to its upper bound - */ - def normalizeHkApplyOLD(implicit ctx: Context): Type = self.strictDealias match { - case self1 @ RefinedType(_, rname, _) if rname.isHkArgNameOLD && self1.typeParams.isEmpty => - val inst = new InstMapOLD(self) - - def instTop(tp: Type): Type = tp.strictDealias match { - case tp: RecType => - inst.localRecs += tp - tp.rebind(instTop(tp.parent)) - case tp @ RefinedType(parent, rname, rinfo) => - rinfo match { - case TypeAlias(TypeRef(RecThis(rt), sel)) if sel.isHkArgNameOLD && inst.localRecs.contains(rt) => - val bounds @ TypeBounds(_, _) = self.member(sel).info - instTop(tp.derivedRefinedType(parent, rname, bounds.withBindingKind(NoBinding))) - case _ => - val parent1 = instTop(parent) - if (rname.isHkArgNameOLD && - !inst.tyconIsHK && - !inst.keptRefs.contains(rname)) parent1 - else tp.derivedRefinedType(parent1, rname, inst(rinfo)) - } - case tp @ WildcardType(bounds @ TypeBounds(lo, hi)) => - tp.derivedWildcardType(bounds.derivedTypeBounds(inst(lo), instTop(hi))) - case tp: LazyRef => - instTop(tp.ref) - case tp => - inst.tyconIsHK = tp.isHK - inst(tp) - } - - def isLazy(tp: Type): Boolean = tp.strictDealias match { - case tp: RefinedOrRecType => isLazy(tp.parent) - case tp @ WildcardType(bounds @ TypeBounds(lo, hi)) => isLazy(hi) - case tp: LazyRef => true - case _ => false - } - - val reduced = - if (isLazy(self1)) { - // A strange dance is needed here to make 974.scala compile. - val res = LazyRef(() => instTop(self)) - res.ref // without this line, pickling 974.scala fails with an assertion error - // saying that we address a RecThis outside its Rec (in the case of RecThis of pickleNewType) - res // without this line, typing 974.scala gives a stackoverflow in asSeenFrom. - } - else instTop(self) - if (reduced ne self) { - hk.println(i"reduce $self --> $reduced / ${inst.tyconIsHK}") - //hk.println(s"reduce $self --> $reduced") - } - reduced - case _ => self - } - - /** A type ref is eta expandable if it refers to a non-lambda class. - * In that case we can look for parameterized base types of the type - * to eta expand them. - */ - def isEtaExpandableOLD(implicit ctx: Context) = self match { - case self: TypeRef => self.symbol.isClass - case _ => false } /** Convert a type constructor `TC` which has type parameters `T1, ..., Tn` @@ -681,23 +450,12 @@ class TypeApplications(val self: Type) extends AnyVal { else { def adaptArg(arg: Type): Type = arg match { case arg @ TypeLambda(tparams, body) if - !tparams.corresponds(hkParams)(_.memberVariance == _.memberVariance) && + !tparams.corresponds(hkParams)(_.paramVariance == _.paramVariance) && tparams.corresponds(hkParams)(varianceConforms) => - TypeLambda(tparams.map(_.memberName), hkParams.map(_.memberVariance))( + TypeLambda(tparams.map(_.paramName), hkParams.map(_.paramVariance))( tl => arg.paramBounds.map(_.subst(arg, tl).bounds), tl => arg.resultType.subst(arg, tl) ) - case arg @ TypeLambdaOLD(tparamBounds, body) if - !arg.typeParams.corresponds(hkParams)(_.memberVariance == _.memberVariance) && - arg.typeParams.corresponds(hkParams)(varianceConforms) => - def adjustVariance(bounds: TypeBounds, tparam: MemberBinding): TypeBounds = - bounds.withBindingKind(BindingKind.fromVariance(tparam.memberVariance)) - def lift[T <: Type](tp: T): (RecType => T) = arg match { - case rt0: RecType => tp.subst(rt0, _).asInstanceOf[T] - case _ => (x => tp) - } - val adjusted = (tparamBounds, hkParams).zipped.map(adjustVariance) - TypeLambdaOLD(adjusted.map(lift), lift(body)) case arg @ TypeAlias(alias) => arg.derivedTypeAlias(adaptArg(alias)) case arg @ TypeBounds(lo, hi) => @@ -731,16 +489,6 @@ class TypeApplications(val self: Type) extends AnyVal { self.instantiate(args) case EtaExpansion(self1) => self1.appliedTo(args) - case TypeLambdaOLD(_, body) if !args.exists(_.isInstanceOf[TypeBounds]) => - def substHkArgs = new TypeMap { - def apply(tp: Type): Type = tp match { - case TypeRef(RecThis(rt), name) if rt.eq(self) && name.isHkArgNameOLD => - args(name.hkArgIndexOLD) - case _ => - mapOver(tp) - } - } - substHkArgs(body) case self1: WildcardType => self1 case _ => @@ -753,12 +501,12 @@ class TypeApplications(val self: Type) extends AnyVal { * @param args = `U1, ..., Un` * @param tparams are assumed to be the type parameters of `T`. */ - final def appliedTo(args: List[Type], typParams: List[MemberBinding])(implicit ctx: Context): Type = { - def matchParams(t: Type, tparams: List[MemberBinding], args: List[Type])(implicit ctx: Context): Type = args match { + final def appliedTo(args: List[Type], typParams: List[TypeParamInfo])(implicit ctx: Context): Type = { + def matchParams(t: Type, tparams: List[TypeParamInfo], args: List[Type])(implicit ctx: Context): Type = args match { case arg :: args1 => try { val tparam :: tparams1 = tparams - matchParams(RefinedType(t, tparam.memberName, arg.toBounds(tparam)), tparams1, args1) + matchParams(RefinedType(t, tparam.paramName, arg.toBounds(tparam)), tparams1, args1) } catch { case ex: MatchError => println(s"applied type mismatch: $self with underlying ${self.underlyingIfProxy}, args = $args, typeParams = $typParams") // !!! DEBUG @@ -790,12 +538,7 @@ class TypeApplications(val self: Type) extends AnyVal { case _ if typParams.isEmpty || typParams.head.isInstanceOf[LambdaParam] => HKApply(self, args) case dealiased => - matchParams(dealiased, typParams, args) match { - case refined @ RefinedType(_, pname, _) if !Config.newHK && pname.isHkArgNameOLD => - refined.betaReduceOLD - case refined => - refined - } + matchParams(dealiased, typParams, args) } } @@ -810,34 +553,21 @@ class TypeApplications(val self: Type) extends AnyVal { * up hk type parameters matching the arguments. This is needed when unpickling * Scala2 files such as `scala.collection.generic.Mapfactory`. */ - final def safeAppliedTo(args: List[Type])(implicit ctx: Context) = - if (Config.newHK) - self match { - case self: TypeRef if !self.symbol.isClass && self.symbol.isCompleting => - HKApply(self, args) - case _ => - appliedTo(args, typeParams) - } - else { - val safeTypeParams = self match { - 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") - fallbackTypeParamsOLD(args map alwaysZero) - case _ => - typeParams - } - appliedTo(args, safeTypeParams) - } + final def safeAppliedTo(args: List[Type])(implicit ctx: Context) = self match { + case self: TypeRef if !self.symbol.isClass && self.symbol.isCompleting => + HKApply(self, args) + case _ => + appliedTo(args, typeParams) + } /** Turn this type, which is used as an argument for * type parameter `tparam`, into a TypeBounds RHS */ - final def toBounds(tparam: MemberBinding)(implicit ctx: Context): TypeBounds = self match { + final def toBounds(tparam: TypeParamInfo)(implicit ctx: Context): TypeBounds = self match { case self: TypeBounds => // this can happen for wildcard args self case _ => - val v = tparam.memberVariance + val v = tparam.paramVariance /* Not neeeded. if (v > 0 && !(tparam is Local) && !(tparam is ExpandedTypeParam)) TypeBounds.upper(self) else if (v < 0 && !(tparam is Local) && !(tparam is ExpandedTypeParam)) TypeBounds.lower(self) diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala index 38b45b2b0..55a964ee9 100644 --- a/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/src/dotty/tools/dotc/core/TypeComparer.scala @@ -364,16 +364,9 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { // This twist is needed to make collection/generic/ParFactory.scala compile fourthTry(tp1, tp2) || compareRefinedSlow case _ => - if (tp2.isTypeParam) { - compareHkLambdaOLD(tp1, tp2) || - fourthTry(tp1, tp2) - } - else { - compareHkApplyOLD(tp2, tp1, inOrder = false) || - compareRefinedSlow || - fourthTry(tp1, tp2) || - compareAliasedRefined(tp2, tp1, inOrder = false) - } + compareRefinedSlow || + fourthTry(tp1, tp2) || + compareAliasedRefined(tp2, tp1, inOrder = false) // @@@ still needed? } else // fast path, in particular for refinements resulting from parameterization. isSubRefinements(tp1w.asInstanceOf[RefinedType], tp2, skipped2) && @@ -399,7 +392,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { // so the bounds checking should look like this: // // tparams1.corresponds(tparams2)((tparam1, tparam2) => - // isSubType(tparam2.memberBounds.subst(tp2, tp1), tparam1.memberBounds)) + // isSubType(tparam2.paramBounds.subst(tp2, tp1), tparam1.paramBounds)) // // But that would invalidate a pattern such as // `[X0 <: Number] -> Number <:< [X0] -> Any` @@ -531,7 +524,6 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { } isNewSubType(tp1.underlying.widenExpr, tp2) || comparePaths case tp1: RefinedType => - compareHkApplyOLD(tp1, tp2, inOrder = true) || isNewSubType(tp1.parent, tp2) || compareAliasedRefined(tp1, tp2, inOrder = true) case tp1: RecType => @@ -693,10 +685,10 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { /** Subtype test for corresponding arguments in `args1`, `args2` according to * variances in type parameters `tparams`. */ - def isSubArgs(args1: List[Type], args2: List[Type], tparams: List[MemberBinding]): Boolean = + def isSubArgs(args1: List[Type], args2: List[Type], tparams: List[TypeParamInfo]): Boolean = if (args1.isEmpty) args2.isEmpty else args2.nonEmpty && { - val v = tparams.head.memberVariance + val v = tparams.head.paramVariance (v > 0 || isSubType(args2.head, args1.head)) && (v < 0 || isSubType(args1.head, args2.head)) } @@ -706,7 +698,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { * - the type parameters of `B` match one-by-one the variances of `tparams`, * - `B` satisfies predicate `p`. */ - private def testLifted(tp1: Type, tp2: Type, tparams: List[MemberBinding], p: Type => Boolean): Boolean = { + private def testLifted(tp1: Type, tp2: Type, tparams: List[TypeParamInfo], p: Type => Boolean): Boolean = { val classBounds = tp2.classSymbols def recur(bcs: List[ClassSymbol]): Boolean = bcs match { case bc :: bcs1 => @@ -722,109 +714,6 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { recur(tp1.baseClasses) } - /** Handle subtype tests - * - * app <:< other if inOrder = true - * other <:< app if inOrder = false - * - * where `app` is an hk application but `other` is not. - * - * As a first step, if `app` appears on the right, try to normalize it using - * `normalizeHkApply`, if that gives a different type proceed with a regular subtype - * test using that type instead of `app`. - * - * Otherwise, if `app` has constrainable poly param as type constructor, - * 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 `app`, - * - has the same number of type parameters as `app` - * - has type parameter variances which conform to those of `app`. - * 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 `app <: other` else test `other <: app`. - */ - def compareHkApplyOLD(app: RefinedType, other: Type, inOrder: Boolean): Boolean = { - def tryInfer(tp: Type): Boolean = ctx.traceIndented(i"compareHK($app, $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.isEtaExpandableOLD && tycon.typeParams.nonEmpty => - val (ok, app1) = - if (ctx.mode.is(Mode.TypevarsMissContext)) - (true, EtaExpansion(tycon).appliedTo(app.argInfos)) - else - (tryInstantiate(param, EtaExpansion(tycon)), app) - ok && - (if (inOrder) isSubType(app1, other) else isSubType(other, app1)) - case _ => - false - } - } - val hkTypeParams = param.typeParams - subtyping.println(i"classBounds = ${app.classSymbols}") - subtyping.println(i"base classes = ${other.baseClasses}") - subtyping.println(i"type params = $hkTypeParams, ${app.classSymbol}") - if (inOrder) unifyWith(other) - else testLifted(other, app, hkTypeParams, unifyWith) - case _ => - // why only handle the case where one of the sides is a typevar or poly param? - // If the LHS is a hk application, then the normal logic already handles - // all other cases. Indeed, say you have - // - // type C[T] <: List[T] - // - // where C is an abstract type. Then to verify `C[Int] <: List[Int]`, - // use compareRefinedslow to get `C <: List` and verify that - // - // C#List$T = C$$hk0 = Int - // - // If the RHS is a hk application, we can also go through - // the normal logic because lower bounds are not parameterized. - // If were to re-introduce parameterized lower bounds of hk types - // we'd have to add some logic to handle them here. - false - } - } - app.isHKApplyOLD && !other.isHKApplyOLD && { - val reduced = if (inOrder) app else app.normalizeHkApplyOLD - if (reduced ne app) - if (inOrder) isSubType(reduced, other) else isSubType(other, reduced) - else tryInfer(app.typeConstructor.dealias) - } - } - - /** Compare type lambda with non-lambda type. */ - def compareHkLambdaOLD(tp1: Type, tp2: RefinedType): Boolean = tp1.stripTypeVar match { - case TypeLambdaOLD(args1, body1) => - //println(i"comparing $tp1 <:< $tp2") - tp2 match { - case TypeLambdaOLD(args2, body2) => - args1.corresponds(args2)((arg1, arg2) => - varianceConforms(BindingKind.toVariance(arg1.bindingKind), - BindingKind.toVariance(arg2.bindingKind))) && - // don't compare bounds; it would go in the wrong sense anyway. - isSubType(body1, body2) - case _ => false - } - case RefinedType(parent1, _, _) => - compareHkLambdaOLD(parent1, tp2) - case _ => - false - } - /** Say we are comparing a refined type `P{type M = U}` or `P{type M >: L <: U}`. * If P#M refers to a BaseTypeArg aliased to some other typeref P#N, * do the same comparison with `P{type N = U}` or `P{type N >: L <: U}`, respectively. @@ -1324,45 +1213,25 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { private def liftIfHK(tp1: Type, tp2: Type, op: (Type, Type) => Type, original: (Type, Type) => Type) = { val tparams1 = tp1.typeParams val tparams2 = tp2.typeParams - if (!Config.newHK && tparams1.isEmpty || tparams2.isEmpty) op(tp1, tp2) - else if (Config.newHK && tparams1.isEmpty) + if (tparams1.isEmpty) if (tparams2.isEmpty) op(tp1, tp2) - else original(tp1, tp2.appliedTo(tp2.typeParams.map(_.memberBoundsAsSeenFrom(tp2)))) - else if (Config.newHK && tparams2.isEmpty) - original(tp1.appliedTo(tp1.typeParams.map(_.memberBoundsAsSeenFrom(tp1))), tp2) - else if (!Config.newHK && (tparams1.isEmpty || tparams2.isEmpty)) op(tp1, tp2) - else if (!Config.newHK && tparams1.length != tparams2.length) mergeConflict(tp1, tp2) - else if (Config.newHK) { + else original(tp1, tp2.appliedTo(tp2.typeParams.map(_.paramBoundsAsSeenFrom(tp2)))) + else if (tparams2.isEmpty) + original(tp1.appliedTo(tp1.typeParams.map(_.paramBoundsAsSeenFrom(tp1))), tp2) + else { val numArgs = tparams1.length def argRefs(tl: GenericType) = List.range(0, numArgs).map(PolyParam(tl, _)) TypeLambda( paramNames = tpnme.syntheticLambdaParamNames(numArgs), variances = (tparams1, tparams2).zipped.map((tparam1, tparam2) => - (tparam1.memberVariance + tparam2.memberVariance) / 2))( + (tparam1.paramVariance + tparam2.paramVariance) / 2))( paramBoundsExp = tl => (tparams1, tparams2).zipped.map((tparam1, tparam2) => - tl.lifted(tparams1, tparam1.memberBoundsAsSeenFrom(tp1)).bounds & - tl.lifted(tparams2, tparam2.memberBoundsAsSeenFrom(tp2)).bounds), + tl.lifted(tparams1, tparam1.paramBoundsAsSeenFrom(tp1)).bounds & + tl.lifted(tparams2, tparam2.paramBoundsAsSeenFrom(tp2)).bounds), resultTypeExp = tl => original(tl.lifted(tparams1, tp1).appliedTo(argRefs(tl)), tl.lifted(tparams2, tp2).appliedTo(argRefs(tl)))) } - else { - val bindings: List[RecType => TypeBounds] = - (tparams1, tparams2).zipped.map { (tparam1, tparam2) => - val b1: RecType => TypeBounds = - tparam1.memberBoundsAsSeenFrom(tp1).recursifyOLD(tparams1) - val b2: RecType => TypeBounds = - tparam2.memberBoundsAsSeenFrom(tp2).recursifyOLD(tparams2) - (rt: RecType) => (b1(rt) & b2(rt)) - .withBindingKind( - BindingKind.fromVariance( - (tparam1.memberVariance + tparam2.memberVariance) / 2)) - } - val app1: RecType => Type = rt => tp1.appliedTo(argRefsOLD(rt, tparams1.length)) - val app2: RecType => Type = rt => tp2.appliedTo(argRefsOLD(rt, tparams2.length)) - val body: RecType => Type = rt => op(app1(rt), app2(rt)) - TypeLambdaOLD(bindings, body) - } } /** Try to distribute `&` inside type, detect and handle conflicts @@ -1652,19 +1521,5 @@ class ExplainingTypeComparer(initctx: Context) extends TypeComparer(initctx) { } } - override def compareHkApplyOLD(app: RefinedType, other: Type, inOrder: Boolean) = - if (app.isHKApplyOLD) - traceIndented(i"compareHkApply $app, $other, $inOrder, ${app.normalizeHkApplyOLD}") { - super.compareHkApplyOLD(app, other, inOrder) - } - else super.compareHkApplyOLD(app, other, inOrder) - - override def compareHkLambdaOLD(tp1: Type, tp2: RefinedType): Boolean = - if (tp2.isTypeParam) - traceIndented(i"compareHkLambda $tp1, $tp2") { - super.compareHkLambdaOLD(tp1, tp2) - } - else super.compareHkLambdaOLD(tp1, tp2) - override def toString = "Subtype trace:" + { try b.toString finally b.clear() } } diff --git a/src/dotty/tools/dotc/core/TypeOps.scala b/src/dotty/tools/dotc/core/TypeOps.scala index 0d02de1da..3a797cce3 100644 --- a/src/dotty/tools/dotc/core/TypeOps.scala +++ b/src/dotty/tools/dotc/core/TypeOps.scala @@ -158,7 +158,6 @@ trait TypeOps { this: Context => // TODO: Make standalone object. tp case tp: RefinedType => tp.derivedRefinedType(simplify(tp.parent, theMap), tp.refinedName, simplify(tp.refinedInfo, theMap)) - .normalizeHkApplyOLD case tp: TypeAlias => tp.derivedTypeAlias(simplify(tp.alias, theMap)) case AndType(l, r) => @@ -386,7 +385,7 @@ trait TypeOps { this: Context => // TODO: Make standalone object. // Strip all refinements from parent type, populating `refinements` and `formals` maps. def normalizeToRef(tp: Type): TypeRef = { def fail = throw new TypeError(s"unexpected parent type: $tp") - tp.dealias.normalizeHkApplyOLD match { + tp.dealias match { case tp: TypeRef => tp case tp @ RefinedType(tp1, name: TypeName, rinfo) => diff --git a/src/dotty/tools/dotc/core/TypeParamInfo.scala b/src/dotty/tools/dotc/core/TypeParamInfo.scala new file mode 100644 index 000000000..ff3c8fca7 --- /dev/null +++ b/src/dotty/tools/dotc/core/TypeParamInfo.scala @@ -0,0 +1,29 @@ +package dotty.tools.dotc.core + +import Names.Name +import Contexts.Context +import Types.{Type, TypeBounds} + +/** A common super trait of Symbol and LambdaParam. + * Used to capture the attributes of type parameters which can be implemented as either. + */ +trait TypeParamInfo { + + /** Is this the info of a type parameter? Might be wrong for symbols */ + def isTypeParam(implicit ctx: Context): Boolean + + /** The name of the type parameter */ + def paramName(implicit ctx: Context): Name + + /** The info of the type parameter */ + def paramBounds(implicit ctx: Context): TypeBounds + + /** The info of the type parameter as seen from a prefix type. + * This can be different from `memberInfo` if the binding + * is a type symbol of a class. + */ + def paramBoundsAsSeenFrom(pre: Type)(implicit ctx: Context): TypeBounds + + /** The variance of the type parameter */ + def paramVariance(implicit ctx: Context): Int +}
\ No newline at end of file diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index c9d2b5029..9150925ff 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -116,12 +116,8 @@ object Types { case TypeAlias(tp) => tp.isRef(sym) case _ => this1.symbol eq sym } - case this1: RefinedType => - !this1.isTypeParam && this1.parent.isRef(sym) - case this1: RecType => - this1.parent.isRef(sym) - case _ => - false + case this1: RefinedOrRecType => this1.parent.isRef(sym) + case _ => false } /** Is this type a (neither aliased nor applied) reference to class `sym`? */ @@ -939,7 +935,7 @@ object Types { tp.underlying.underlyingClassRef(refinementOK) case tp: RefinedType => def isParamName = tp.classSymbol.typeParams.exists(_.name == tp.refinedName) - if (refinementOK || tp.isTypeParam || isParamName) tp.underlying.underlyingClassRef(refinementOK) + if (refinementOK || isParamName) tp.underlying.underlyingClassRef(refinementOK) else NoType case tp: RecType => tp.underlying.underlyingClassRef(refinementOK) @@ -2099,8 +2095,7 @@ object Types { * @param infoFn: A function that produces the info of the refinement declaration, * given the refined type itself. */ - abstract case class RefinedType(parent: Type, refinedName: Name, refinedInfo: Type) - extends RefinedOrRecType with BindingType with MemberBinding { + abstract case class RefinedType(parent: Type, refinedName: Name, refinedInfo: Type) extends RefinedOrRecType { override def underlying(implicit ctx: Context) = parent @@ -2111,42 +2106,6 @@ object Types { this } - def betaReduceOLD(implicit ctx: Context): Type = refinedInfo match { - case TypeAlias(alias) if refinedName.isHkArgNameOLD => - def instantiate(rt: RecType) = new TypeMap { - def apply(t: Type) = t match { - case TypeRef(RecThis(`rt`), `refinedName`) => alias - case tp: TypeRef => - val pre1 = apply(tp.prefix) - if (pre1 ne tp.prefix) tp.newLikeThis(pre1) else tp - case _ => mapOver(t) - } - } - def substAlias(tp: Type): Type = tp.safeDealias match { - case tp @ RefinedType(p, rname, rinfo) if tp.isTypeParam => - if (rname == refinedName) p // check bounds? - else tp.derivedRefinedType(substAlias(p), rname, rinfo) - case tp: RecType => - val p1 = substAlias(tp.parent) - if (p1 ne tp.parent) tp.rebind(instantiate(tp)(p1)) - else tp - case _ => - tp - } - parent match { - case parent: LazyRef => - LazyRef(() => derivedRefinedType(parent.ref, refinedName, refinedInfo)) - case _ => - val reduced = substAlias(parent) - if (reduced ne parent) { - hk.println(i"REDUCE $this ----> ${reduced}") - reduced - } else this - } - case _ => - this - } - 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 { @@ -2156,7 +2115,7 @@ object Types { // 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).betaReduceOLD + RefinedType(parent, refinedName, normalizedRefinedInfo) } /** Add this refinement to `parent`, provided If `refinedName` is a member of `parent`. */ @@ -2164,17 +2123,6 @@ object Types { if (parent.member(refinedName).exists) derivedRefinedType(parent, refinedName, refinedInfo) else parent - // MemberBinding methods - // TODO: Needed? - def isTypeParam(implicit ctx: Context) = refinedInfo match { - case tp: TypeBounds => tp.isBinding - case _ => false - } - def memberName(implicit ctx: Context) = refinedName - def memberBounds(implicit ctx: Context) = refinedInfo.bounds - def memberBoundsAsSeenFrom(pre: Type)(implicit ctx: Context) = memberBounds - def memberVariance(implicit ctx: Context) = BindingKind.toVariance(refinedInfo.bounds.bindingKind) - override def equals(that: Any) = that match { case that: RefinedType => this.parent == that.parent && @@ -2623,7 +2571,7 @@ object Types { def duplicate(paramNames: List[TypeName] = this.paramNames, paramBounds: List[TypeBounds] = this.paramBounds, resType: Type)(implicit ctx: Context): GenericType - def lifted(tparams: List[MemberBinding], t: Type)(implicit ctx: Context): Type = + def lifted(tparams: List[TypeParamInfo], t: Type)(implicit ctx: Context): Type = tparams match { case LambdaParam(poly, _) :: _ => t.subst(poly, this) @@ -2710,12 +2658,12 @@ object Types { } /** The parameter of a type lambda */ - case class LambdaParam(tl: TypeLambda, n: Int) extends MemberBinding { + case class LambdaParam(tl: TypeLambda, n: Int) extends TypeParamInfo { def isTypeParam(implicit ctx: Context) = true - def memberName(implicit ctx: Context): TypeName = tl.paramNames(n) - def memberBounds(implicit ctx: Context): TypeBounds = tl.paramBounds(n) - def memberBoundsAsSeenFrom(pre: Type)(implicit ctx: Context): TypeBounds = memberBounds - def memberVariance(implicit ctx: Context): Int = tl.variances(n) + def paramName(implicit ctx: Context): TypeName = tl.paramNames(n) + def paramBounds(implicit ctx: Context): TypeBounds = tl.paramBounds(n) + def paramBoundsAsSeenFrom(pre: Type)(implicit ctx: Context): TypeBounds = paramBounds + def paramVariance(implicit ctx: Context): Int = tl.variances(n) def toArg: Type = PolyParam(tl, n) } @@ -2756,7 +2704,7 @@ object Types { case _ => defn.AnyType } - def typeParams(implicit ctx: Context): List[MemberBinding] = { + def typeParams(implicit ctx: Context): List[TypeParamInfo] = { val tparams = tycon.typeParams if (tparams.isEmpty) TypeLambda.any(args.length).typeParams else tparams } @@ -3574,10 +3522,10 @@ object Types { if (inst.exists) apply(inst) else tp case tp: HKApply => - def mapArg(arg: Type, tparam: MemberBinding): Type = { + def mapArg(arg: Type, tparam: TypeParamInfo): Type = { val saved = variance - if (tparam.memberVariance < 0) variance = -variance - else if (tparam.memberVariance == 0) variance = 0 + if (tparam.paramVariance < 0) variance = -variance + else if (tparam.paramVariance == 0) variance = 0 try this(arg) finally variance = saved } diff --git a/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/src/dotty/tools/dotc/core/tasty/TreePickler.scala index f604bff62..6a51b9642 100644 --- a/src/dotty/tools/dotc/core/tasty/TreePickler.scala +++ b/src/dotty/tools/dotc/core/tasty/TreePickler.scala @@ -257,7 +257,7 @@ class TreePickler(pickler: TastyPickler) { case tpe: TypeLambda => writeByte(LAMBDAtype) val paramNames = tpe.typeParams.map(tparam => - varianceToPrefix(tparam.memberVariance) +: tparam.memberName) + varianceToPrefix(tparam.paramVariance) +: tparam.paramName) pickleMethodic(tpe.resultType, paramNames, tpe.paramBounds) case tpe: MethodType if richTypes => writeByte(METHODtype) diff --git a/src/dotty/tools/dotc/printing/PlainPrinter.scala b/src/dotty/tools/dotc/printing/PlainPrinter.scala index 880804b9e..656650d91 100644 --- a/src/dotty/tools/dotc/printing/PlainPrinter.scala +++ b/src/dotty/tools/dotc/printing/PlainPrinter.scala @@ -51,8 +51,6 @@ class PlainPrinter(_ctx: Context) extends Printer { homogenize(tp1) & homogenize(tp2) case OrType(tp1, tp2) => homogenize(tp1) | homogenize(tp2) - case tp: RefinedType if !Config.newHK => - tp.normalizeHkApplyOLD case tp: SkolemType => homogenize(tp.info) case tp: LazyRef => diff --git a/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/src/dotty/tools/dotc/printing/RefinedPrinter.scala index c772267e7..34456d0b9 100644 --- a/src/dotty/tools/dotc/printing/RefinedPrinter.scala +++ b/src/dotty/tools/dotc/printing/RefinedPrinter.scala @@ -113,36 +113,6 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { if (defn.isFunctionClass(cls)) return toTextFunction(args) if (defn.isTupleClass(cls)) return toTextTuple(args) return (toTextLocal(tycon) ~ "[" ~ Text(args map argText, ", ") ~ "]").close - case tp @ TypeLambdaOLD(argBoundss, body) => - 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 { - def contains(tp1: Type, tp2: Type): Boolean = - tp1.eq(tp2) || { - tp1.stripTypeVar match { - case tp1: RefinedOrRecType => contains(tp1.parent, tp2) - case _ => false - } - } - def apply(t: Type): Type = t match { - case TypeRef(RecThis(rt), name) if name.isHkArgNameOLD && contains(tp, rt) => - // Make up a name that prints as "Xi". Need to be careful we do not - // accidentally unique-hash to something else. That's why we can't - // use prefix = NoPrefix or a WithFixedSym instance. - TypeRef.withSymAndName( - defn.EmptyPackageClass.thisType, defn.AnyClass, - paramNames(name.hkArgIndexOLD).toTypeName) - case _ => - mapOver(t) - } - } - val instArgs = argBoundss.map(instantiate).asInstanceOf[List[TypeBounds]] - val instBody = instantiate(body).dropAlias - lambdaNestingLevel += 1 - try - return typeLambdaText(paramNames, variances, instArgs, instBody) - finally lambdaNestingLevel -=1 case tp: TypeRef => val hideType = tp.symbol is AliasPreferred if (hideType && !ctx.phase.erasedTypes && !tp.symbol.isCompleting) { diff --git a/src/dotty/tools/dotc/typer/TypeAssigner.scala b/src/dotty/tools/dotc/typer/TypeAssigner.scala index e26ea1138..0344ae6c6 100644 --- a/src/dotty/tools/dotc/typer/TypeAssigner.scala +++ b/src/dotty/tools/dotc/typer/TypeAssigner.scala @@ -4,10 +4,9 @@ package typer import core._ import ast._ -import config.Config.newHK import Scopes._, Contexts._, Constants._, Types._, Symbols._, Names._, Flags._, Decorators._ import ErrorReporting._, Annotations._, Denotations._, SymDenotations._, StdNames._, TypeErasure._ -import TypeApplications.{AppliedType, TypeLambdaOLD} +import TypeApplications.AppliedType import util.Positions._ import config.Printers._ import ast.Trees._ @@ -99,7 +98,7 @@ trait TypeAssigner { val base = apply(tycon) var args = tp.baseArgInfos(base.typeSymbol) if (base.typeParams.length != args.length) - args = base.typeParams.map(_.memberBounds) + args = base.typeParams.map(_.paramBounds) base.appliedTo(args) case tp @ RefinedType(parent, name, rinfo) if variance > 0 => val parent1 = apply(tp.parent) @@ -413,7 +412,7 @@ trait TypeAssigner { def refineNamed(tycon: Type, arg: Tree) = arg match { case ast.Trees.NamedArg(name, argtpt) => // Dotty deviation: importing ast.Trees._ and matching on NamedArg gives a cyclic ref error - val tparam = tparams.find(_.memberName == name) match { + val tparam = tparams.find(_.paramName == name) match { case Some(tparam) => tparam case none => ntparams.find(_.name == name).getOrElse(NoSymbol) } @@ -430,16 +429,7 @@ trait TypeAssigner { } def assignType(tree: untpd.TypeLambdaTree, tparamDefs: List[TypeDef], body: Tree)(implicit ctx: Context) = - if (newHK) tree.withType(TypeLambda.fromSymbols(tparamDefs.map(_.symbol), body.tpe)) - else { - val tparams = tparamDefs.map(_.symbol) - val argBindingFns = tparams.map(tparam => - tparam.info.bounds - .withBindingKind(BindingKind.fromVariance(tparam.variance)) - .recursifyOLD(tparams)) - val bodyFn = body.tpe.recursifyOLD(tparams) - tree.withType(TypeLambdaOLD(argBindingFns, bodyFn)) - } + tree.withType(TypeLambda.fromSymbols(tparamDefs.map(_.symbol), body.tpe)) def assignType(tree: untpd.ByNameTypeTree, result: Tree)(implicit ctx: Context) = tree.withType(ExprType(result.tpe)) diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala index 49d69f04e..da176427a 100644 --- a/src/dotty/tools/dotc/typer/Typer.scala +++ b/src/dotty/tools/dotc/typer/Typer.scala @@ -942,10 +942,10 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit ctx.error(d"wrong number of type arguments for ${tpt1.tpe}, should be ${tparams.length}", tree.pos) args = args.take(tparams.length) } - def typedArg(arg: untpd.Tree, tparam: MemberBinding) = { + def typedArg(arg: untpd.Tree, tparam: TypeParamInfo) = { val (desugaredArg, argPt) = if (ctx.mode is Mode.Pattern) - (if (isVarPattern(arg)) desugar.patternVar(arg) else arg, tparam.memberBounds) + (if (isVarPattern(arg)) desugar.patternVar(arg) else arg, tparam.paramBounds) else (arg, WildcardType) typed(desugaredArg, argPt) diff --git a/src/dotty/tools/dotc/typer/Variances.scala b/src/dotty/tools/dotc/typer/Variances.scala index a2f9a0f16..a8abe5e30 100644 --- a/src/dotty/tools/dotc/typer/Variances.scala +++ b/src/dotty/tools/dotc/typer/Variances.scala @@ -84,11 +84,11 @@ object Variances { case ExprType(restpe) => varianceInType(restpe)(tparam) case tp @ HKApply(tycon, args) => - def varianceInArgs(v: Variance, args: List[Type], tparams: List[MemberBinding]): Variance = + def varianceInArgs(v: Variance, args: List[Type], tparams: List[TypeParamInfo]): Variance = args match { case arg :: args1 => varianceInArgs( - v & compose(varianceInType(arg)(tparam), tparams.head.memberVariance), + v & compose(varianceInType(arg)(tparam), tparams.head.paramVariance), args1, tparams.tail) case nil => v |