From 4bf43f82c88dbeb0578e289b37ce1a7580aa22f2 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 29 Jun 2016 19:09:43 +0200 Subject: Turn on new hk scheme For the moment under newHK flag. - avoid crasher in derivedTypeParams (NamedTypes don't always have symbols) - Revise logic in type comparer for new HK scheme --- src/dotty/tools/dotc/ast/Desugar.scala | 2 +- src/dotty/tools/dotc/config/Config.scala | 2 +- src/dotty/tools/dotc/core/Definitions.scala | 10 +- src/dotty/tools/dotc/core/NameOps.scala | 10 +- src/dotty/tools/dotc/core/StdNames.scala | 10 +- src/dotty/tools/dotc/core/SymDenotations.scala | 4 +- src/dotty/tools/dotc/core/TypeApplications.scala | 341 ++++++++++++++------- src/dotty/tools/dotc/core/TypeComparer.scala | 144 +++++++-- src/dotty/tools/dotc/core/TypeOps.scala | 3 +- src/dotty/tools/dotc/core/Types.scala | 34 +- .../tools/dotc/core/tasty/TreeUnpickler.scala | 4 +- .../dotc/core/unpickleScala2/Scala2Unpickler.scala | 2 +- src/dotty/tools/dotc/printing/PlainPrinter.scala | 2 +- src/dotty/tools/dotc/printing/RefinedPrinter.scala | 3 +- src/dotty/tools/dotc/typer/TypeAssigner.scala | 2 +- 15 files changed, 404 insertions(+), 169 deletions(-) diff --git a/src/dotty/tools/dotc/ast/Desugar.scala b/src/dotty/tools/dotc/ast/Desugar.scala index f603f6817..a9705e209 100644 --- a/src/dotty/tools/dotc/ast/Desugar.scala +++ b/src/dotty/tools/dotc/ast/Desugar.scala @@ -66,7 +66,7 @@ object desugar { val relocate = new TypeMap { val originalOwner = sym.owner def apply(tp: Type) = tp match { - case tp: NamedType if tp.symbol.owner eq originalOwner => + case tp: NamedType if tp.symbol.exists && (tp.symbol.owner eq originalOwner) => val defctx = ctx.outersIterator.dropWhile(_.scope eq ctx.scope).next var local = defctx.denotNamed(tp.name).suchThat(_ is ParamOrAccessor).symbol if (local.exists) (defctx.owner.thisType select local).dealias diff --git a/src/dotty/tools/dotc/config/Config.scala b/src/dotty/tools/dotc/config/Config.scala index be8a367d7..63ecdc76d 100644 --- a/src/dotty/tools/dotc/config/Config.scala +++ b/src/dotty/tools/dotc/config/Config.scala @@ -8,7 +8,7 @@ object Config { final val cacheMemberNames = true final val cacheImplicitScopes = true - final val newHK = false + final val newHK = true final val checkCacheMembersNamed = false diff --git a/src/dotty/tools/dotc/core/Definitions.scala b/src/dotty/tools/dotc/core/Definitions.scala index 5cb373cfd..1311bb583 100644 --- a/src/dotty/tools/dotc/core/Definitions.scala +++ b/src/dotty/tools/dotc/core/Definitions.scala @@ -668,7 +668,7 @@ class Definitions { private var myLambdaTraits: Set[Symbol] = Set() /** The set of HigherKindedXYZ traits encountered so far */ - def lambdaTraits: Set[Symbol] = myLambdaTraits + def lambdaTraitsOBS: Set[Symbol] = myLambdaTraits private var LambdaTraitForVariances = mutable.Map[List[Int], ClassSymbol]() @@ -689,7 +689,7 @@ class Definitions { * - 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 LambdaTrait(vcs: List[Int]): ClassSymbol = { + def LambdaTraitOBS(vcs: List[Int]): ClassSymbol = { assert(vcs.nonEmpty) def varianceFlags(v: Int) = v match { @@ -704,16 +704,16 @@ class Definitions { val paramDecls = newScope for (i <- 0 until vcs.length) newTypeParam(cls, tpnme.hkArg(i), varianceFlags(vcs(i)), paramDecls) - newTypeField(cls, tpnme.hkApply, Covariant, paramDecls) + newTypeField(cls, tpnme.hkApplyOBS, Covariant, paramDecls) val parentTraitRefs = for (i <- 0 until vcs.length if vcs(i) != 0) - yield LambdaTrait(vcs.updated(i, 0)).typeRef + yield LambdaTraitOBS(vcs.updated(i, 0)).typeRef denot.info = ClassInfo( ScalaPackageClass.thisType, cls, ObjectClass.typeRef :: parentTraitRefs.toList, paramDecls) } } - val traitName = tpnme.hkLambda(vcs) + val traitName = tpnme.hkLambdaOBS(vcs) def createTrait = { val cls = newClassSymbol( diff --git a/src/dotty/tools/dotc/core/NameOps.scala b/src/dotty/tools/dotc/core/NameOps.scala index 17af899e9..1f221b5c8 100644 --- a/src/dotty/tools/dotc/core/NameOps.scala +++ b/src/dotty/tools/dotc/core/NameOps.scala @@ -116,12 +116,12 @@ object NameOps { def hkArgIndex: Int = name.drop(tpnme.hkArgPrefixLength).toString.toInt - def isLambdaTraitName(implicit ctx: Context): Boolean = - name.isTypeName && name.startsWith(tpnme.hkLambdaPrefix) + def isLambdaTraitNameOBS(implicit ctx: Context): Boolean = + name.isTypeName && name.startsWith(tpnme.hkLambdaPrefixOBS) - def lambdaTraitVariances(implicit ctx: Context): List[Int] = { - val vs = name.drop(tpnme.hkLambdaPrefix.length) - vs.toList.map(c => tpnme.varianceSuffixes.indexOf(c) - 1) + 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 diff --git a/src/dotty/tools/dotc/core/StdNames.scala b/src/dotty/tools/dotc/core/StdNames.scala index 81f6da0e2..e82260201 100644 --- a/src/dotty/tools/dotc/core/StdNames.scala +++ b/src/dotty/tools/dotc/core/StdNames.scala @@ -529,9 +529,9 @@ object StdNames { val synthSwitch: N = "$synthSwitch" - val hkApply: N = "$Apply" + val hkApplyOBS: N = "$Apply" val hkArgPrefix: N = "$hk" - val hkLambdaPrefix: N = "Lambda$" + val hkLambdaPrefixOBS: N = "Lambda$" val hkArgPrefixHead: Char = hkArgPrefix.head val hkArgPrefixLength: Int = hkArgPrefix.length @@ -744,11 +744,11 @@ object StdNames { def syntheticTypeParamNames(num: Int): List[TypeName] = (0 until num).map(syntheticTypeParamName)(breakOut) - def hkLambda(vcs: List[Int]): TypeName = hkLambdaPrefix ++ vcs.map(varianceSuffix).mkString + def hkLambdaOBS(vcs: List[Int]): TypeName = hkLambdaPrefixOBS ++ vcs.map(varianceSuffixOBS).mkString def hkArg(n: Int): TypeName = hkArgPrefix ++ n.toString - def varianceSuffix(v: Int): Char = varianceSuffixes.charAt(v + 1) - val varianceSuffixes = "NIP" + def varianceSuffixOBS(v: Int): Char = varianceSuffixesOBS.charAt(v + 1) + val varianceSuffixesOBS = "NIP" final val Conforms = encode("<:<") } diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala index 7715885c4..8fefdf7a7 100644 --- a/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/src/dotty/tools/dotc/core/SymDenotations.scala @@ -479,8 +479,8 @@ object SymDenotations { name.decode == tpnme.REFINE_CLASS /** is this symbol a trait representing a type lambda? */ - final def isLambdaTrait(implicit ctx: Context): Boolean = - isClass && name.startsWith(tpnme.hkLambdaPrefix) && owner == defn.ScalaPackageClass + 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 = { diff --git a/src/dotty/tools/dotc/core/TypeApplications.scala b/src/dotty/tools/dotc/core/TypeApplications.scala index d9521b3c8..9ceae6e5f 100644 --- a/src/dotty/tools/dotc/core/TypeApplications.scala +++ b/src/dotty/tools/dotc/core/TypeApplications.scala @@ -15,43 +15,9 @@ import StdNames.tpnme import util.Positions.Position import config.Printers._ import collection.mutable - import dotty.tools.dotc.config.Config +import dotty.tools.dotc.config.Config import java.util.NoSuchElementException -object TypeApplicationsNewHK { - import TypeApplications._ - - object TypeLambda { - def apply(argBindingFns: List[RecType => TypeBounds], - bodyFn: RecType => Type)(implicit ctx: Context): Type = { - val argNames = argBindingFns.indices.toList.map(tpnme.hkArg) - var idx = 0 - RecType.closeOver(rt => - (bodyFn(rt) /: argBindingFns) { (parent, argBindingFn) => - val res = RefinedType(parent, tpnme.hkArg(idx), argBindingFn(rt)) - idx += 1 - res - }) - } - - def unapply(tp: Type)(implicit ctx: Context): Option[(List[TypeBounds], Type)] = { - def decompose(t: Type, acc: List[TypeBounds]): (List[TypeBounds], Type) = t match { - case t @ RefinedType(p, rname, rinfo: TypeBounds) - if rname.isHkArgName && rinfo.isBinding => - 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) - } - } - } -} - object TypeApplications { /** Assert type is not a TypeBounds instance and return it unchanged */ @@ -81,22 +47,42 @@ object TypeApplications { def variancesConform(syms1: List[MemberBinding], syms2: List[MemberBinding])(implicit ctx: Context) = syms1.corresponds(syms2)(varianceConforms) + def fallbackTypeParams(n: Int)(implicit ctx: Context): List[MemberBinding] = { + def memberBindings(n: Int): Type = + if (n == 0) NoType + else + RefinedType( + memberBindings(n - 1), + tpnme.hkArg(n - 1), + TypeBounds.empty.withBindingKind(NonvariantBinding)) + def decompose(t: Type, acc: List[MemberBinding]): List[MemberBinding] = t match { + case t: RefinedType => decompose(t.parent, t :: acc) + case NoType => acc + } + decompose(memberBindings(n), Nil) + } + /** Extractor for * * [v1 X1: B1, ..., vn Xn: Bn] -> T * ==> * ([X_i := this.$hk_i] T) { type v_i $hk_i: (new)B_i } - * - * [X] -> List[X] - * - * List { type List$A = this.$hk_0 } { type $hk_0 } - * - * [X] -> X - * - * mu(this) this.$hk_0 & { type $hk_0 } */ object TypeLambda { - def apply(variances: List[Int], + 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 => + (bodyFn(rt) /: argBindingFns) { (parent, argBindingFn) => + val res = RefinedType(parent, tpnme.hkArg(idx), argBindingFn(rt)) + idx += 1 + res + }) + } + + 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 { @@ -108,26 +94,42 @@ object TypeApplications { assert(variances.nonEmpty) assert(argBoundsFns.length == variances.length) RefinedType( - argRefinements(defn.LambdaTrait(variances).typeRef, 0, argBoundsFns), - tpnme.hkApply, bodyFn(_).bounds.withVariance(1)) + 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)] = tp match { - case app @ RefinedType(parent, tpnme.hkApply, 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.isLambdaTraitName) - acc + 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 rname.isHkArgName && rinfo.isBinding => + decompose(p, rinfo.bounds :: acc) + case t: RecType => + decompose(t.parent, acc) + case _ => + (acc, t) } - val argBounds = collectBounds(parent, Nil) - Some((variances, argBounds, refinedInfo.argInfo)) - case _ => - None + decompose(tp, Nil) match { + case (Nil, _) => None + case x => Some(x) +// case (bindings, tp) => Some((Nil, bindings, tp)) + } + } + 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 } } @@ -156,7 +158,7 @@ object TypeApplications { false } tp match { - case TypeLambda(_, argBounds, AppliedType(fn: TypeRef, args)) + case TypeLambda(argBounds, AppliedType(fn: TypeRef, args)) if argsAreForwarders(args, tp.typeParams.length) => Some(fn) case _ => None } @@ -177,10 +179,32 @@ object TypeApplications { 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 TypeRef(prefix, tpnme.hkApply) => unapp(prefix) + case tp: RefinedType if Config.newHK => + var refinements: List[RefinedType] = Nil + var tycon = tp.stripTypeVar + while (tycon.isInstanceOf[RefinedType]) { + val rt = tycon.asInstanceOf[RefinedType] + refinements = rt :: refinements + tycon = rt.parent.stripTypeVar + } + def collectArgs(tparams: List[MemberBinding], + 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 => + collectArgs(tparams.tail, refinements1, argBuf += rinfo.argInfo) + case _ => + None + } + collectArgs(tycon.typeParams, refinements, new mutable.ListBuffer[Type]) + case TypeRef(prefix, tpnme.hkApplyOBS) if !Config.newHK => + unapp(prefix) case _ => - unapp(tp) match { - case Some((tycon: TypeRef, _)) if tycon.symbol.isLambdaTrait => + 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 @@ -239,7 +263,7 @@ object TypeApplications { * - bounds `Bi` are the intersection of the corresponding type parameter bounds * of `tp1` and `tp2`. */ - def hkCombine(tp1: Type, tp2: Type, + 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) => @@ -258,7 +282,25 @@ object TypeApplications { 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(variances, bounds, body) + 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 + var isSafe: Boolean = true + def apply(tp: Type): Type = tp match { + case tp @ TypeRef(RecThis(rt), sel) if sel.isHkArgName && localRecs.contains(rt) => + fullType.member(sel).info match { + case TypeAlias(alias) => apply(alias) + case _ => keptRefs += sel; tp + } + case tp: TypeVar if !tp.inst.exists => + isSafe = false + tp + case _ => + mapOver(tp) + } } } @@ -290,7 +332,8 @@ class TypeApplications(val self: Type) extends AnyVal { else tsym.infoOrCompleter match { case completer: TypeParamsCompleter => val tparams = completer.completerTypeParams(tsym) - defn.LambdaTrait(tparams.map(_.variance)).typeParams + if (Config.newHK) tparams + else defn.LambdaTraitOBS(tparams.map(_.variance)).typeParams case _ => if (!tsym.isCompleting || tsym.isAliasType) tsym.info.typeParams else @@ -305,11 +348,15 @@ class TypeApplications(val self: Type) extends AnyVal { // inlined and optimized version of // val sym = self.LambdaTrait // if (sym.exists) return sym.typeParams - if (self.refinedName == tpnme.hkApply) { + if (!Config.newHK && self.refinedName == tpnme.hkApplyOBS) { val sym = self.parent.classSymbol - if (sym.isLambdaTrait) return sym.typeParams + if (sym.isLambdaTraitOBS) return sym.typeParams } - self.parent.typeParams.filterNot(_.memberName == self.refinedName) + val precedingParams = self.parent.typeParams + if (Config.newHK && self.isTypeParam) precedingParams :+ self + else precedingParams.filterNot(_.memberName == self.refinedName) + case self: RecType => + self.parent.typeParams case self: SingletonType => Nil case self: TypeProxy => @@ -319,6 +366,11 @@ class TypeApplications(val self: Type) extends AnyVal { } } + final def hkTypeParams(implicit ctx: Context): List[MemberBinding] = + if (Config.newHK) + if (isHK) typeParams else Nil + else LambdaTraitOBS.typeParams + final def typeParamSymbols(implicit ctx: Context): List[TypeSymbol] = { val tparams = typeParams assert(tparams.isEmpty || tparams.head.isInstanceOf[Symbol]) @@ -387,25 +439,27 @@ class TypeApplications(val self: Type) extends AnyVal { } /** The Lambda trait underlying a type lambda */ - def LambdaTrait(implicit ctx: Context): Symbol = self.stripTypeVar match { - case RefinedType(_, tpnme.hkApply, _) => + def LambdaTraitOBS(implicit ctx: Context): Symbol = self.stripTypeVar match { + case RefinedType(_, tpnme.hkApplyOBS, _) => val sym = self.classSymbol - if (sym.isLambdaTrait) sym else NoSymbol - case TypeBounds(lo, hi) => hi.LambdaTrait + if (sym.isLambdaTraitOBS) sym else NoSymbol + case TypeBounds(lo, hi) => hi.LambdaTraitOBS case _ => NoSymbol } - /** Is receiver type higher-kinded (i.e. of kind != "*")? */ + /** 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 RefinedType(_, tpnme.hkApply, _) => true + case self: RefinedType => self.refinedName == tpnme.hkApplyOBS || self.isTypeParam + case self: RecType => self.parent.isHK case TypeBounds(_, hi) => hi.isHK case _ => false } /** is receiver of the form T#$Apply? */ - def isHKApply: Boolean = self match { - case TypeRef(_, name) => name == tpnme.hkApply + 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 _ => false } @@ -423,7 +477,7 @@ class TypeApplications(val self: Type) extends AnyVal { case self: TypeRef => self.denot.exists && { val sym = self.symbol - if (sym.isClass) !sym.isLambdaTrait + if (sym.isClass) !sym.isLambdaTraitOBS else sym.isCompleted && self.info.isAlias && self.info.bounds.hi.classNotLambda } case _ => @@ -449,10 +503,22 @@ class TypeApplications(val self: Type) extends AnyVal { /** 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 recursify[T <: Type](tparams: List[Symbol])(implicit ctx: Context): RecType => T = - (rt: RecType) => - new ctx.SafeSubstMap(tparams, argRefs(rt, tparams.length)) - .apply(self).asInstanceOf[T] + def recursify[T <: Type](tparams: List[MemberBinding])(implicit ctx: Context): RecType => T = + tparams match { + case (_: Symbol) :: _ => + (rt: RecType) => + 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) + case _ => mapOver(t) + } + } + mapRefs(_).apply(self).asInstanceOf[T] + } /** Lambda abstract `self` with given type parameters. Examples: * @@ -469,27 +535,65 @@ class TypeApplications(val self: Type) extends AnyVal { new ctx.SafeSubstMap(tparams, argRefs(rt, tparams.length)) .apply(tp).asInstanceOf[T] - def expand(tp: Type) = { - TypeLambda( - tparams.map(_.variance), - tparams.map(tparam => internalize(self.memberInfo(tparam).bounds)), - internalize(tp)) - } + 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)) + + assert(!isHK, self) self match { case self: TypeAlias => - self.derivedTypeAlias(expand(self.alias)) + self.derivedTypeAlias(expand(self.alias.BetaReduce)) case self @ TypeBounds(lo, hi) => - self.derivedTypeBounds(lo, expand(TypeBounds.upper(hi))) + if (Config.newHK) + self.derivedTypeBounds(lo, expand(hi.BetaReduce)) + else + self.derivedTypeBounds(lo, expand(TypeBounds.upper(hi.BetaReduce))) case _ => expand(self) } } - /** A type ref is eta expandable if it refers to a non-lambda class. + def BetaReduce(implicit ctx: Context): Type = self.dealias match { + case self1 @ RefinedType(_, rname, _) if Config.newHK && rname.isHkArgName => + val inst = new InstMap(self) + def instTop(tp: Type): Type = { + if (!inst.isSafe) tp + else tp.dealias 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.isHkArgName && inst.localRecs.contains(rt) => + instTop(tp.derivedRefinedType(parent, rname, self.member(sel).info)) + case _ => + val parent1 = instTop(parent) + if (rname.isHkArgName && !inst.keptRefs.contains(rname)) parent1 + else tp.derivedRefinedType(parent1, rname, inst(rinfo)) + } + case tp => + inst(tp) + }} + val reduced = instTop(self) + if (inst.isSafe) reduced else self + case self1 => self1 + } + + /** 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 isEtaExpandable(implicit ctx: Context) = self match { - case self: TypeRef => self.symbol.isClass && !self.name.isLambdaTraitName + case self: TypeRef => self.symbol.isClass && !self.name.isLambdaTraitNameOBS case _ => false } @@ -519,8 +623,7 @@ class TypeApplications(val self: Type) extends AnyVal { /** Eta expand if `self` is a (non-lambda) class reference and `bound` is a higher-kinded type */ def etaExpandIfHK(bound: Type)(implicit ctx: Context): Type = { - val boundLambda = bound.LambdaTrait - val hkParams = boundLambda.typeParams + val hkParams = bound.hkTypeParams if (hkParams.isEmpty) self else self match { case self: TypeRef if self.symbol.isClass && self.typeParams.length == hkParams.length => @@ -561,15 +664,36 @@ class TypeApplications(val self: Type) extends AnyVal { * is covariant is irrelevant, so can be ignored. */ def adaptHkVariances(bound: Type)(implicit ctx: Context): Type = { - val boundLambda = bound.LambdaTrait - val hkParams = boundLambda.typeParams + val hkParams = bound.hkTypeParams if (hkParams.isEmpty) self + else if (Config.newHK) { + def adaptArg(arg: Type): Type = arg match { + case arg @ TypeLambda(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) + TypeLambda(adjusted.map(lift), lift(body)) + case arg @ TypeAlias(alias) => + arg.derivedTypeAlias(adaptArg(alias)) + case arg @ TypeBounds(lo, hi) => + arg.derivedTypeBounds(lo, adaptArg(hi)) + case _ => + arg + } + adaptArg(self) + } else { def adaptArg(arg: Type): Type = arg match { - case arg: TypeRef if arg.symbol.isLambdaTrait && - !arg.symbol.typeParams.corresponds(hkParams)(_.variance == _.variance) && - arg.symbol.typeParams.corresponds(hkParams)(varianceConforms) => - arg.prefix.select(boundLambda) + 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 => @@ -605,6 +729,8 @@ class TypeApplications(val self: Type) extends AnyVal { 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 _ => mapOver(tp) } @@ -613,7 +739,7 @@ class TypeApplications(val self: Type) extends AnyVal { else self.stripTypeVar match { case EtaExpansion(self1) => self1.appliedTo(args) - case TypeLambda(_, _, body) if !args.exists(_.isInstanceOf[TypeBounds]) => + case TypeLambda(_, body) if !args.exists(_.isInstanceOf[TypeBounds]) => substHkArgs(body) case self: PolyType => self.instantiate(args) @@ -643,8 +769,8 @@ class TypeApplications(val self: Type) extends AnyVal { } assert(args.nonEmpty) matchParams(self, typParams, args) match { - case refined @ RefinedType(_, pname, _) if pname.isHkArgName => - TypeRef(refined, tpnme.hkApply) + case refined @ RefinedType(_, pname, _) if pname.isHkArgName && !Config.newHK => + TypeRef(refined, tpnme.hkApplyOBS) case refined => refined } @@ -663,7 +789,8 @@ 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") - defn.LambdaTrait(args map alwaysZero).typeParams + if (Config.newHK) fallbackTypeParams(args.length) + else defn.LambdaTraitOBS(args map alwaysZero).typeParams case _ => typeParams } @@ -853,6 +980,6 @@ class TypeApplications(val self: Type) extends AnyVal { case _ => false } - recur(self) + !Config.newHK && recur(self) } } diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala index 58c6bea3a..3648b3764 100644 --- a/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/src/dotty/tools/dotc/core/TypeComparer.scala @@ -178,11 +178,11 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { && !tp1.isInstanceOf[WithFixedSym] && !tp2.isInstanceOf[WithFixedSym] ) || - compareHkApply(tp1, tp2, inOrder = true) || - compareHkApply(tp2, tp1, inOrder = false) || + compareHkApplyOBS(tp1, tp2, inOrder = true) || + compareHkApplyOBS(tp2, tp1, inOrder = false) || thirdTryNamed(tp1, tp2) case _ => - compareHkApply(tp2, tp1, inOrder = false) || + compareHkApplyOBS(tp2, tp1, inOrder = false) || secondTry(tp1, tp2) } } @@ -259,7 +259,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { if (tp1.prefix.isStable) return false case _ => } - compareHkApply(tp1, tp2, inOrder = true) || + compareHkApplyOBS(tp1, tp2, inOrder = true) || thirdTry(tp1, tp2) case tp1: PolyParam => def flagNothingBound = { @@ -354,6 +354,12 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { case tp2: RefinedType => def compareRefinedSlow: Boolean = { val name2 = tp2.refinedName + if (name2.isHkArgName) { + val tp2reduced = tp2.BetaReduce + if (Config.newHK && (tp2reduced ne tp2)) return isSubType(tp1, tp2reduced) + if (Config.newHK && tp2.isTypeParam) return compareHkLambda(tp2, tp1, inOrder = false) + if (Config.newHK && !tp1.isHKApply) return compareHkApply(tp2, tp1, inOrder = false) + } isSubType(tp1, tp2.parent) && (name2 == nme.WILDCARD || hasMatchingMember(name2, tp1, tp2)) } @@ -370,6 +376,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { case _ => compareRefinedSlow || fourthTry(tp1, tp2) || + compareHkApply(tp2, tp1, inOrder = false) || compareHkLambda(tp2, tp1, inOrder = false) || compareAliasedRefined(tp2, tp1, inOrder = false) } @@ -494,9 +501,15 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { } isNewSubType(tp1.underlying.widenExpr, tp2) || comparePaths case tp1: RefinedType => + if (Config.newHK && tp1.refinedName.isHkArgName) { + val tp1reduced = tp1.BetaReduce + if (Config.newHK && (tp1reduced ne tp1)) return isSubType(tp1reduced, tp2) + if (Config.newHK && tp1.isTypeParam) return compareHkLambda(tp1, tp2, inOrder = true) + if (Config.newHK && !tp2.isHKApply) return compareHkApply(tp1, tp2, inOrder = true) + } isNewSubType(tp1.parent, tp2) || - compareHkLambda(tp1, tp2, inOrder = true) || - compareAliasedRefined(tp1, tp2, inOrder = true) + !Config.newHK && compareHkLambda(tp1, tp2, inOrder = true) || + !Config.newHK && compareAliasedRefined(tp1, tp2, inOrder = true) case tp1: RecType => isNewSubType(tp1.parent, tp2) case AndType(tp11, tp12) => @@ -535,7 +548,9 @@ 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 = tp2.member(tpnme.hkApply).info.classSymbols + val classBounds = + if (Config.newHK) tp2.classSymbols + else tp2.member(tpnme.hkApplyOBS).info.classSymbols def recur(bcs: List[ClassSymbol]): Boolean = bcs match { case bc :: bcs1 => val baseRef = tp1.baseTypeRef(bc) @@ -570,7 +585,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { * * (4) If `inOrder`, test `projection <: other` else test `other <: projection`. */ - def compareHkApply(projection: NamedType, other: Type, inOrder: Boolean): Boolean = { + 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) @@ -592,7 +607,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { } } val hkTypeParams = param.typeParams - subtyping.println(i"classBounds = ${projection.prefix.member(tpnme.hkApply).info.classSymbols}") + subtyping.println(i"classBounds = ${projection.prefix.member(tpnme.hkApplyOBS).info.classSymbols}") subtyping.println(i"base classes = ${other.baseClasses}") subtyping.println(i"type params = $hkTypeParams") if (inOrder) unifyWith(other) @@ -601,13 +616,67 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { false } } - projection.name == tpnme.hkApply && !other.isHKApply && + !Config.newHK && projection.name == tpnme.hkApplyOBS && !other.isHKApply && tryInfer(projection.prefix.typeConstructor.dealias) } + /** 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 compareHkApply(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.isEtaExpandable && 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") + if (inOrder) unifyWith(other) + else testLifted(other, app, hkTypeParams, unifyWith) + case _ => + false + } + } + Config.newHK && app.isHKApply && !other.isHKApply && tryInfer(app.typeConstructor.dealias) + } + /** Compare type lambda with non-lambda type. */ def compareHkLambda(rt: RefinedType, other: Type, inOrder: Boolean) = rt match { - case TypeLambda(vs, args, body) => + case TypeLambda(args, body) => other.isInstanceOf[TypeRef] && args.length == other.typeParams.length && { val applied = other.appliedTo(argRefs(rt, args.length)) @@ -1123,15 +1192,39 @@ 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) = { - val tparams1 = tp1.typeParamSymbols // TODO revise for new hk scheme - val tparams2 = tp2.typeParamSymbols - def onlyNamed(tparams: List[TypeSymbol]) = tparams.forall(!_.is(ExpandedName)) - if (tparams1.isEmpty || tparams2.isEmpty || + 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) + } + } + 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 hkCombine(tp1, tp2, tparams1, tparams2, op) - } + else if (tparams1.length != tparams2.length) mergeConflict(tp1, tp2) + else hkCombineOBS(tp1, tp2, tparams1, tparams2, op) + } /** Try to distribute `&` inside type, detect and handle conflicts * @pre !(tp1 <: tp2) && !(tp2 <:< tp1) -- these cases were handled before @@ -1415,15 +1508,16 @@ class ExplainingTypeComparer(initctx: Context) extends TypeComparer(initctx) { override def copyIn(ctx: Context) = new ExplainingTypeComparer(ctx) - override def compareHkApply(projection: NamedType, other: Type, inOrder: Boolean) = - if (projection.name == tpnme.hkApply) - traceIndented(i"compareHkApply $projection, $other, $inOrder") { - super.compareHkApply(projection, other, inOrder) + override def compareHkApply(app: RefinedType, other: Type, inOrder: Boolean) = + if (app.isHKApply) + traceIndented(i"compareHkApply $app, $other, $inOrder, ${app.typeConstructor.dealias}") { + super.compareHkApply(app, other, inOrder) } - else super.compareHkApply(projection, other, inOrder) + else super.compareHkApply(app, other, inOrder) override def compareHkLambda(rt: RefinedType, other: Type, inOrder: Boolean) = - if (rt.refinedName == tpnme.hkApply) + if (!Config.newHK && rt.refinedName == tpnme.hkApplyOBS || + Config.newHK && rt.isTypeParam) traceIndented(i"compareHkLambda $rt, $other, $inOrder") { super.compareHkLambda(rt, other, inOrder) } diff --git a/src/dotty/tools/dotc/core/TypeOps.scala b/src/dotty/tools/dotc/core/TypeOps.scala index 54846087f..bb9566b6f 100644 --- a/src/dotty/tools/dotc/core/TypeOps.scala +++ b/src/dotty/tools/dotc/core/TypeOps.scala @@ -6,6 +6,7 @@ import Contexts._, Types._, Symbols._, Names._, Flags._, Scopes._ import SymDenotations._, Denotations.SingleDenotation import config.Printers._ import util.Positions._ +import NameOps._ import Decorators._ import StdNames._ import Annotations._ @@ -382,7 +383,7 @@ trait TypeOps { this: Context => // TODO: Make standalone object. var formals: SimpleMap[TypeName, Symbol] = SimpleMap.Empty // A map of all formal parent parameter // Strip all refinements from parent type, populating `refinements` and `formals` maps. - def normalizeToRef(tp: Type): TypeRef = tp.dealias match { + def normalizeToRef(tp: Type): TypeRef = tp.dealias.BetaReduce match { case tp: TypeRef => tp case tp @ RefinedType(tp1, name: TypeName, rinfo) => diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index 42abc4251..22a26968c 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -465,8 +465,10 @@ object Types { case _ => NoDenotation } - def goRec(tp: RecType) = + def goRec(tp: RecType) = { + //println(s"find member $pre . $name in $tp") go(tp.parent).mapInfo(_.substRecThis(tp, pre)) + } def goRefined(tp: RefinedType) = { val pdenot = go(tp.parent) val rinfo = @@ -960,7 +962,7 @@ object Types { else if (!pre.refinementRefersToThis) alias else alias match { case TypeRef(RefinedThis(`pre`), aliasName) => lookupRefined(aliasName) // (1) - case _ => if (name == tpnme.hkApply) betaReduce(alias) else NoType // (2) // ### use TypeApplication's betaReduce + case _ => if (name == tpnme.hkApplyOBS) betaReduce(alias) else NoType // (2) // ### use TypeApplication's betaReduce } case _ => loop(pre.parent) } @@ -1624,7 +1626,7 @@ object Types { ctx.underlyingRecursions -= 1 } - /** A selection of the same kind, but with potentially a differet prefix. + /** A selection of the same kind, but with potentially a different prefix. * The following normalizations are performed for type selections T#A: * * T#A --> B if A is bound to an alias `= B` in T @@ -1641,7 +1643,7 @@ object Types { else if (isType) { val res = prefix.lookupRefined(name) if (res.exists) res - else if (name == tpnme.hkApply && prefix.classNotLambda) { + 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`. @@ -1751,7 +1753,11 @@ object Types { type ThisType = TypeRef - override def underlying(implicit ctx: Context): Type = info + override def underlying(implicit ctx: Context): Type = { + val res = info + assert(res != this, this) + res + } } final class TermRefWithSignature(prefix: Type, name: TermName, override val sig: Signature) extends TermRef(prefix, name) { @@ -1922,7 +1928,7 @@ object Types { object TypeRef { def checkProjection(prefix: Type, name: TypeName)(implicit ctx: Context) = - if (name == tpnme.hkApply && prefix.classNotLambda) + if (name == tpnme.hkApplyOBS && prefix.classNotLambda) assert(false, s"bad type : $prefix.$name does not allow $$Apply projection") /** Create type ref with given prefix and name */ @@ -2073,7 +2079,7 @@ object Types { throw new AssertionError(s"bad instantiation: $this") def checkInst(implicit ctx: Context): this.type = { - if (refinedName == tpnme.hkApply) + if (refinedName == tpnme.hkApplyOBS) parent.stripTypeVar match { case RefinedType(_, name, _) if name.isHkArgName => // ok case _ => badInst @@ -3015,6 +3021,8 @@ object Types { def withBindingKind(bk: BindingKind)(implicit ctx: Context) = derivedTypeBounds(lo, hi, bk) + //def checkBinding: this.type = { assert(isBinding); this } + def contains(tp: Type)(implicit ctx: Context): Boolean = tp match { case tp: TypeBounds => lo <:< tp.lo && tp.hi <:< hi case tp: ClassInfo => @@ -3052,16 +3060,20 @@ object Types { /** If this type and that type have the same variance, this variance, otherwise 0 */ final def commonVariance(that: TypeBounds): Int = (this.variance + that.variance) / 2 - override def computeHash = doHash(variance, lo, hi) + override def computeHash = doHash(variance * 41 + bindingKind.n, lo, hi) override def equals(that: Any): Boolean = that match { case that: TypeBounds => - (this.lo eq that.lo) && (this.hi eq that.hi) && this.variance == that.variance + (this.lo eq that.lo) && (this.hi eq that.hi) && + (this.variance == that.variance) && (this.bindingKind == that.bindingKind) case _ => false } - override def toString = - if (lo eq hi) s"TypeAlias($lo, $variance)" else s"TypeBounds($lo, $hi)" + override def toString = { + def bkString = if (isBinding) s"|bk=${BindingKind.toVariance(bindingKind)}" else "" + if (lo eq hi) s"TypeAlias($lo, $variance)" + else s"TypeBounds($lo, $hi$bkString)" + } } class RealTypeBounds(lo: Type, hi: Type, bk: BindingKind) extends TypeBounds(lo, hi)(bk) diff --git a/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index 1b4e7845a..d9a062263 100644 --- a/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -325,8 +325,8 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) { readPackageRef().termRef case TYPEREF => val name = readName().toTypeName - if (name.isLambdaTraitName) // Make sure curresponding lambda trait exists - defn.LambdaTrait(name.lambdaTraitVariances) + if (name.isLambdaTraitNameOBS) // Make sure corresponding lambda trait exists + defn.LambdaTraitOBS(name.lambdaTraitVariancesOBS) TypeRef(readType(), name) case TERMREF => readNameSplitSig() match { diff --git a/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala b/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala index 2663777af..557a9df74 100644 --- a/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala +++ b/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala @@ -632,7 +632,7 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas case info => tp.derivedRefinedType(parent1, name, info) } - case tp @ TypeRef(pre, tpnme.hkApply) => + 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 59f1608db..20bf8b407 100644 --- a/src/dotty/tools/dotc/printing/PlainPrinter.scala +++ b/src/dotty/tools/dotc/printing/PlainPrinter.scala @@ -50,7 +50,7 @@ class PlainPrinter(_ctx: Context) extends Printer { homogenize(tp1) & homogenize(tp2) case OrType(tp1, tp2) => homogenize(tp1) | homogenize(tp2) - case tp @ TypeRef(_, tpnme.hkApply) => + case tp @ TypeRef(_, tpnme.hkApplyOBS) => val tp1 = tp.reduceProjection if (tp1 eq tp) tp else homogenize(tp1) case tp: LazyRef => diff --git a/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/src/dotty/tools/dotc/printing/RefinedPrinter.scala index 1020468a9..b5bc17c0c 100644 --- a/src/dotty/tools/dotc/printing/RefinedPrinter.scala +++ b/src/dotty/tools/dotc/printing/RefinedPrinter.scala @@ -116,7 +116,8 @@ 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 @ TypeLambda(variances, argBoundss, body) => + case tp @ TypeLambda(argBoundss, body) => + val variances = tp.classSymbol.typeParams.map(_.variance) val prefix = ((('X' - 'A') + lambdaNestingLevel) % 26 + 'A').toChar val paramNames = variances.indices.toList.map(prefix.toString + _) val instantiate = new TypeMap { diff --git a/src/dotty/tools/dotc/typer/TypeAssigner.scala b/src/dotty/tools/dotc/typer/TypeAssigner.scala index b7e2fd832..4752d2827 100644 --- a/src/dotty/tools/dotc/typer/TypeAssigner.scala +++ b/src/dotty/tools/dotc/typer/TypeAssigner.scala @@ -432,7 +432,7 @@ trait TypeAssigner { .withBindingKind(BindingKind.fromVariance(tparam.variance)) .recursify(tparams)) val bodyFn = body.tpe.recursify(tparams) - tree.withType(TypeApplicationsNewHK.TypeLambda(argBindingFns, bodyFn)) + tree.withType(TypeApplications.TypeLambda(argBindingFns, bodyFn)) } def assignType(tree: untpd.ByNameTypeTree, result: Tree)(implicit ctx: Context) = -- cgit v1.2.3