aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core/TypeApplications.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2016-06-29 19:12:29 +0200
committerMartin Odersky <odersky@gmail.com>2016-07-11 13:34:59 +0200
commit5daae278392ed6fabd45c9fa55aded970ca2a348 (patch)
tree3ddec4b259a4c359efdff5fa4392a88819d336fe /src/dotty/tools/dotc/core/TypeApplications.scala
parent4bf43f82c88dbeb0578e289b37ce1a7580aa22f2 (diff)
downloaddotty-5daae278392ed6fabd45c9fa55aded970ca2a348.tar.gz
dotty-5daae278392ed6fabd45c9fa55aded970ca2a348.tar.bz2
dotty-5daae278392ed6fabd45c9fa55aded970ca2a348.zip
Multiple fixes
- Swap order of tests in lookupRefined - Change joins of BindingKinds. A type parameter joint with a normal refinement represents a type parameter that has been filled in. So the Binding attribute should be removed. - Fix printing of type lambdas under new hk scheme - refine isRef for hk type The new definition avoids that a higher-kinded type "isRef" of an underlying class. I.e. `[X] -> Any` is not longer a ref to `Any`. - Fix withBindingKind for type aliases Old definition converted aliases to type bounds. - Multiple fixes to BetaReduce - Fix logic for hk subtype tests - Make isHK more precise
Diffstat (limited to 'src/dotty/tools/dotc/core/TypeApplications.scala')
-rw-r--r--src/dotty/tools/dotc/core/TypeApplications.scala84
1 files changed, 67 insertions, 17 deletions
diff --git a/src/dotty/tools/dotc/core/TypeApplications.scala b/src/dotty/tools/dotc/core/TypeApplications.scala
index 9ceae6e5f..dfd1caf62 100644
--- a/src/dotty/tools/dotc/core/TypeApplications.scala
+++ b/src/dotty/tools/dotc/core/TypeApplications.scala
@@ -285,17 +285,18 @@ object TypeApplications {
TypeLambda.applyOBS(variances, bounds, body)
}
- private class InstMap(fullType: Type)(implicit ctx: Context) extends TypeMap {
+ private class InstMap(fullType: Type, shortLived: Boolean)(implicit ctx: Context) extends TypeMap {
var localRecs: Set[RecType] = Set.empty
var keptRefs: Set[Name] = Set.empty
var isSafe: Boolean = true
+ var tyconIsHK: 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 =>
+ case tp: TypeVar if !tp.inst.exists && !shortLived =>
isSafe = false
tp
case _ =>
@@ -451,8 +452,10 @@ class TypeApplications(val self: Type) extends AnyVal {
def isHK(implicit ctx: Context): Boolean = self.dealias match {
case self: TypeRef => self.info.isHK
case self: RefinedType => self.refinedName == tpnme.hkApplyOBS || self.isTypeParam
- case self: RecType => self.parent.isHK
- case TypeBounds(_, hi) => hi.isHK
+ case self: SingletonType => false
+ case self: TypeVar => self.origin.isHK
+ case self: WildcardType => self.optBounds.isHK
+ case self: TypeProxy => self.underlying.isHK
case _ => false
}
@@ -552,20 +555,55 @@ class TypeApplications(val self: Type) extends AnyVal {
assert(!isHK, self)
self match {
case self: TypeAlias =>
- self.derivedTypeAlias(expand(self.alias.BetaReduce))
+ self.derivedTypeAlias(expand(self.alias.BetaReduce()))
case self @ TypeBounds(lo, hi) =>
if (Config.newHK)
- self.derivedTypeBounds(lo, expand(hi.BetaReduce))
+ self.derivedTypeBounds(lo, expand(hi.BetaReduce()))
else
- self.derivedTypeBounds(lo, expand(TypeBounds.upper(hi.BetaReduce)))
+ self.derivedTypeBounds(lo, expand(TypeBounds.upper(hi.BetaReduce())))
case _ => expand(self)
}
}
- 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 `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
+ * - dropping refinements and rec-types
+ * - going from a wildcard type to its upper bound
+ *
+ * @param shortLived If `false` suppresses all rewritings where a type variable with
+ * an unknown or uncommitted instance is rewritten. Reason: If the
+ * type variable is finally instantiated to something else, the
+ * reduction might not be valid anymore. However, when reducing
+ * during `<:<` tests `shortLived` is true and the reduction
+ * is never suppressed, because then we are only interested
+ * in subtyping relative to the current context.
+ */
+ def BetaReduce(shortLived: Boolean = false)(implicit ctx: Context): Type = self.dealias match {
+ case self1 @ RefinedType(_, rname, _) if Config.newHK && rname.isHkArgName && self1.typeParams.isEmpty =>
+ val inst = new InstMap(self, shortLived)
+ def instTop(tp: Type): Type =
if (!inst.isSafe) tp
else tp.dealias match {
case tp: RecType =>
@@ -574,18 +612,30 @@ class TypeApplications(val self: Type) extends AnyVal {
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))
+ val bounds @ TypeBounds(_, _) = self.member(sel).info
+ instTop(tp.derivedRefinedType(parent, rname, bounds.withBindingKind(NoBinding)))
case _ =>
val parent1 = instTop(parent)
- if (rname.isHkArgName && !inst.keptRefs.contains(rname)) parent1
+ if (rname.isHkArgName &&
+ !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 =>
- inst(tp)
- }}
+ inst.tyconIsHK = tp.isHK
+ val res = inst(tp)
+ tp match {
+ case tp: WildcardType =>
+ println(s"inst $tp --> $res")
+ case _ =>
+ }
+ res
+ }
val reduced = instTop(self)
if (inst.isSafe) reduced else self
- case self1 => self1
+ case _ => self
}
/** A type ref is eta expandable if it refers to a non-lambda class.
@@ -761,7 +811,7 @@ class TypeApplications(val self: Type) extends AnyVal {
matchParams(RefinedType(t, tparam.memberName, arg.toBounds(tparam)), tparams1, args1)
} catch {
case ex: MatchError =>
- println(s"applied type mismatch: $self $args, typeParams = $typParams") // !!! DEBUG
+ println(s"applied type mismatch: $self with underlying ${self.underlyingIfProxy}, args = $args, typeParams = $typParams") // !!! DEBUG
//println(s"precomplete decls = ${self.typeSymbol.unforcedDecls.toList.map(_.denot).mkString("\n ")}")
throw ex
}