aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2016-06-29 19:09:43 +0200
committerMartin Odersky <odersky@gmail.com>2016-07-11 13:34:59 +0200
commit4bf43f82c88dbeb0578e289b37ce1a7580aa22f2 (patch)
tree41c4483ffcf4e93e8d19f4ec89206a848738eb08
parent178e90e441481364f19163a9dad624a4d859fb1b (diff)
downloaddotty-4bf43f82c88dbeb0578e289b37ce1a7580aa22f2.tar.gz
dotty-4bf43f82c88dbeb0578e289b37ce1a7580aa22f2.tar.bz2
dotty-4bf43f82c88dbeb0578e289b37ce1a7580aa22f2.zip
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
-rw-r--r--src/dotty/tools/dotc/ast/Desugar.scala2
-rw-r--r--src/dotty/tools/dotc/config/Config.scala2
-rw-r--r--src/dotty/tools/dotc/core/Definitions.scala10
-rw-r--r--src/dotty/tools/dotc/core/NameOps.scala10
-rw-r--r--src/dotty/tools/dotc/core/StdNames.scala10
-rw-r--r--src/dotty/tools/dotc/core/SymDenotations.scala4
-rw-r--r--src/dotty/tools/dotc/core/TypeApplications.scala341
-rw-r--r--src/dotty/tools/dotc/core/TypeComparer.scala144
-rw-r--r--src/dotty/tools/dotc/core/TypeOps.scala3
-rw-r--r--src/dotty/tools/dotc/core/Types.scala34
-rw-r--r--src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala4
-rw-r--r--src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala2
-rw-r--r--src/dotty/tools/dotc/printing/PlainPrinter.scala2
-rw-r--r--src/dotty/tools/dotc/printing/RefinedPrinter.scala3
-rw-r--r--src/dotty/tools/dotc/typer/TypeAssigner.scala2
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) =