aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core/TypeApplications.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2016-06-29 20:15:22 +0200
committerMartin Odersky <odersky@gmail.com>2016-07-11 13:35:05 +0200
commit646bf97d7c2e66b4332b86f2e6cd6440fc442215 (patch)
tree9e1734cfe4c2b93fbbcaaea31dbbe464d8ffe3b6 /src/dotty/tools/dotc/core/TypeApplications.scala
parent8805dd4f821e06a688fcf492b61033fe0992e752 (diff)
downloaddotty-646bf97d7c2e66b4332b86f2e6cd6440fc442215.tar.gz
dotty-646bf97d7c2e66b4332b86f2e6cd6440fc442215.tar.bz2
dotty-646bf97d7c2e66b4332b86f2e6cd6440fc442215.zip
Beta-reduce with wildcard arguments if this is safe.
Makes pos/partialApplications compile. - Fix appliedTo for aliasTypes Returned a general TypeBounds instance before.
Diffstat (limited to 'src/dotty/tools/dotc/core/TypeApplications.scala')
-rw-r--r--src/dotty/tools/dotc/core/TypeApplications.scala48
1 files changed, 45 insertions, 3 deletions
diff --git a/src/dotty/tools/dotc/core/TypeApplications.scala b/src/dotty/tools/dotc/core/TypeApplications.scala
index 274fc8ff8..714d2a5e3 100644
--- a/src/dotty/tools/dotc/core/TypeApplications.scala
+++ b/src/dotty/tools/dotc/core/TypeApplications.scala
@@ -223,6 +223,44 @@ object TypeApplications {
mapOver(tp)
}
}
+
+ /** A type map that tries to reduce a (part of) the result type of the type lambda `tycon`
+ * with the given `args`(some of which are wildcard arguments represented by type bounds).
+ * Non-wildcard arguments are substituted everywhere as usual. A wildcard argument
+ * `>: L <: H` is substituted for a type lambda parameter `X` only if `X` appears
+ * in a toplevel refinement of the form
+ *
+ * { type A = X }
+ *
+ * and there are no other occurrences of `X` in the reduced type. In that case
+ * the refinement above is replaced by
+ *
+ * { type A >: L <: U }
+ *
+ * The `allReplaced` field indicates whether all occurrences of type lambda parameters
+ * in the reduced type have been replaced with arguments.
+ */
+ class Reducer(tycon: TypeLambda, args: List[Type])(implicit ctx: Context) extends TypeMap {
+ private var available = Set((0 until args.length): _*)
+ var allReplaced = true
+ def hasWildcardArg(p: PolyParam) =
+ p.binder == tycon && args(p.paramNum).isInstanceOf[TypeBounds]
+ def apply(t: Type) = t match {
+ case t @ TypeAlias(p: PolyParam) if hasWildcardArg(p) && available.contains(p.paramNum) =>
+ available -= p.paramNum
+ args(p.paramNum)
+ case p: PolyParam if p.binder == tycon =>
+ if (hasWildcardArg(p)) { allReplaced = false; p }
+ else args(p.paramNum)
+ case _: TypeBounds | _: HKApply =>
+ val saved = available
+ available = Set()
+ try mapOver(t)
+ finally available = saved
+ case _ =>
+ mapOver(t)
+ }
+ }
}
import TypeApplications._
@@ -733,12 +771,16 @@ class TypeApplications(val self: Type) extends AnyVal {
self.stripTypeVar match {
case self: TypeLambda =>
if (!args.exists(_.isInstanceOf[TypeBounds])) self.instantiate(args)
- else self match {
- case EtaExpansion(selfTycon) => selfTycon.appliedTo(args)
- case _ => HKApply(self, args)
+ else {
+ val reducer = new Reducer(self, args)
+ val reduced = reducer(self.resType)
+ if (reducer.allReplaced) reduced
+ else HKApply(self, args)
}
case self: AndOrType =>
self.derivedAndOrType(self.tp1.appliedTo(args), self.tp2.appliedTo(args))
+ case self: TypeAlias =>
+ self.derivedTypeAlias(self.alias.appliedTo(args))
case self: TypeBounds =>
self.derivedTypeBounds(self.lo, self.hi.appliedTo(args))
case self: LazyRef =>