aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2016-06-04 18:21:11 +0200
committerMartin Odersky <odersky@gmail.com>2016-07-11 13:35:00 +0200
commit939d9da26ee5992c17cd1fae0a501ed66a49fb95 (patch)
tree7efeb8e2cc3f4fdcfcbbf8b06051b3b4fc55240b
parentae1f248ff407b231455a43ecbaf4751c0bb2bbaa (diff)
downloaddotty-939d9da26ee5992c17cd1fae0a501ed66a49fb95.tar.gz
dotty-939d9da26ee5992c17cd1fae0a501ed66a49fb95.tar.bz2
dotty-939d9da26ee5992c17cd1fae0a501ed66a49fb95.zip
Add a second betaReduce
The new one only reduces straight applications of type lambdas with definite arguments. It is called very early on appliedTo, and derivedRefinedType. The old one, now renamed to normalizeHkApply also handles wildcard arguments and can garbage collect general unneeded hk-refinements. It is called later, at various places. TODO: See what functionality of normalizeHkApply should go into betaReduce instead. Maybe we can even drop normalizeHkApply? However: need to be careful to maintain aliases for hk type inference.
-rw-r--r--src/dotty/tools/dotc/core/ConstraintHandling.scala2
-rw-r--r--src/dotty/tools/dotc/core/TypeApplications.scala13
-rw-r--r--src/dotty/tools/dotc/core/TypeComparer.scala6
-rw-r--r--src/dotty/tools/dotc/core/TypeOps.scala4
-rw-r--r--src/dotty/tools/dotc/core/Types.scala38
-rw-r--r--tests/neg/hklower.scala2
6 files changed, 50 insertions, 15 deletions
diff --git a/src/dotty/tools/dotc/core/ConstraintHandling.scala b/src/dotty/tools/dotc/core/ConstraintHandling.scala
index 3b368ad5e..8072a111a 100644
--- a/src/dotty/tools/dotc/core/ConstraintHandling.scala
+++ b/src/dotty/tools/dotc/core/ConstraintHandling.scala
@@ -286,7 +286,7 @@ trait ConstraintHandling {
else if (fromBelow) defn.NothingType
else defn.AnyType
case bound: RefinedType =>
- bound.BetaReduce
+ bound.normalizeHkApply
case _ =>
bound
}
diff --git a/src/dotty/tools/dotc/core/TypeApplications.scala b/src/dotty/tools/dotc/core/TypeApplications.scala
index 7b2d2c3b2..0de951c31 100644
--- a/src/dotty/tools/dotc/core/TypeApplications.scala
+++ b/src/dotty/tools/dotc/core/TypeApplications.scala
@@ -565,12 +565,12 @@ 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.normalizeHkApply))
case self @ TypeBounds(lo, hi) =>
if (Config.newHK)
- self.derivedTypeBounds(lo, expand(hi.BetaReduce))
+ self.derivedTypeBounds(lo, expand(hi.normalizeHkApply))
else
- self.derivedTypeBounds(lo, expand(TypeBounds.upper(hi.BetaReduce)))
+ self.derivedTypeBounds(lo, expand(TypeBounds.upper(hi.normalizeHkApply)))
case _ => expand(self)
}
}
@@ -603,7 +603,7 @@ class TypeApplications(val self: Type) extends AnyVal {
* - dropping refinements and rec-types
* - going from a wildcard type to its upper bound
*/
- def BetaReduce(implicit ctx: Context): Type = self.strictDealias match {
+ def normalizeHkApply(implicit ctx: Context): Type = self.strictDealias match {
case self1 @ RefinedType(_, rname, _) if Config.newHK && rname.isHkArgName && self1.typeParams.isEmpty =>
val inst = new InstMap(self)
@@ -840,8 +840,9 @@ class TypeApplications(val self: Type) extends AnyVal {
}
assert(args.nonEmpty)
matchParams(self, typParams, args) match {
- case refined @ RefinedType(_, pname, _) if pname.isHkArgName && !Config.newHK =>
- TypeRef(refined, tpnme.hkApplyOBS)
+ case refined @ RefinedType(_, pname, _) if pname.isHkArgName =>
+ if (Config.newHK) refined.betaReduce
+ else TypeRef(refined, tpnme.hkApplyOBS)
case refined =>
refined
}
diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala
index c82dc6a39..c1cbe0752 100644
--- a/src/dotty/tools/dotc/core/TypeComparer.scala
+++ b/src/dotty/tools/dotc/core/TypeComparer.scala
@@ -661,7 +661,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
}
}
Config.newHK && app.isHKApply && !other.isHKApply && {
- val reduced = app.BetaReduce
+ val reduced = app.normalizeHkApply
if (reduced ne app)
if (inOrder) isSubType(reduced, other) else isSubType(other, reduced)
else tryInfer(app.typeConstructor.dealias)
@@ -675,7 +675,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
val applied = other.appliedTo(argRefs(rt, args.length))
if (inOrder) isSubType(body, applied)
else body match {
- case body: TypeBounds => body.contains(applied)
+ case body: TypeBounds => body.contains(applied) // Can be dropped?
case _ => isSubType(applied, body)
}
}
@@ -1503,7 +1503,7 @@ class ExplainingTypeComparer(initctx: Context) extends TypeComparer(initctx) {
override def compareHkApply(app: RefinedType, other: Type, inOrder: Boolean) =
if (app.isHKApply)
- traceIndented(i"compareHkApply $app, $other, $inOrder, ${app.BetaReduce}") {
+ traceIndented(i"compareHkApply $app, $other, $inOrder, ${app.normalizeHkApply}") {
super.compareHkApply(app, other, inOrder)
}
else super.compareHkApply(app, other, inOrder)
diff --git a/src/dotty/tools/dotc/core/TypeOps.scala b/src/dotty/tools/dotc/core/TypeOps.scala
index c6a18f305..ca49d3d3c 100644
--- a/src/dotty/tools/dotc/core/TypeOps.scala
+++ b/src/dotty/tools/dotc/core/TypeOps.scala
@@ -158,7 +158,7 @@ trait TypeOps { this: Context => // TODO: Make standalone object.
tp
case tp: RefinedType =>
tp.derivedRefinedType(simplify(tp.parent, theMap), tp.refinedName, simplify(tp.refinedInfo, theMap))
- .BetaReduce
+ .normalizeHkApply
case tp: TypeAlias =>
tp.derivedTypeAlias(simplify(tp.alias, theMap))
case AndType(l, r) =>
@@ -384,7 +384,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.BetaReduce match {
+ def normalizeToRef(tp: Type): TypeRef = tp.dealias.normalizeHkApply 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 403b49da6..2fa4f94c1 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -2131,9 +2131,43 @@ object Types {
this
}
- def derivedRefinedType(parent: Type, refinedName: Name, refinedInfo: Type)(implicit ctx: Context): RefinedType =
+ def betaReduce(implicit ctx: Context): Type = refinedInfo match {
+ case TypeAlias(alias) =>
+ def instantiate(rt: RecType) = new TypeMap {
+ def apply(t: Type) = t match {
+ case TypeRef(RecThis(`rt`), `refinedName`) => alias
+ case tp: TypeRef =>
+ val pre1 = apply(tp.prefix)
+ if (pre1 ne tp.prefix) tp.newLikeThis(pre1) else tp
+ case _ => mapOver(t)
+ }
+ }
+ def substAlias(tp: Type): Type = tp.safeDealias match {
+ case tp @ RefinedType(p, rname, rinfo) if tp.isTypeParam =>
+ if (rname == refinedName) p // check bounds?
+ else tp.derivedRefinedType(substAlias(p), rname, rinfo)
+ case tp: RecType =>
+ val p1 = substAlias(tp.parent)
+ if (p1 ne tp.parent) tp.rebind(instantiate(tp)(p1))
+ else tp
+ case _ =>
+ tp
+ }
+ val reduced = substAlias(parent)
+ if (reduced ne parent) {
+ hk.println(i"REDUCE $this ----> ${reduced}")
+ reduced
+ }
+ else this
+ case _ =>
+ this
+ }
+
+ def derivedRefinedType(parent: Type, refinedName: Name, refinedInfo: Type)(implicit ctx: Context): Type =
if ((parent eq this.parent) && (refinedName eq this.refinedName) && (refinedInfo eq this.refinedInfo)) this
- else RefinedType(parent, refinedName, rt => refinedInfo.substRefinedThis(this, RefinedThis(rt)))
+ else
+ RefinedType(parent, refinedName, rt => refinedInfo.substRefinedThis(this, RefinedThis(rt)))
+ .betaReduce
/** Add this refinement to `parent`, provided If `refinedName` is a member of `parent`. */
def wrapIfMember(parent: Type)(implicit ctx: Context): Type =
diff --git a/tests/neg/hklower.scala b/tests/neg/hklower.scala
index 5c1ba27ba..e29a1545e 100644
--- a/tests/neg/hklower.scala
+++ b/tests/neg/hklower.scala
@@ -1,4 +1,4 @@
-class Test { // error conflicting bounds
+class Test {
type T[X] // OK
type U[X] = T[X] // OK