From 646bf97d7c2e66b4332b86f2e6cd6440fc442215 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 29 Jun 2016 20:15:22 +0200 Subject: Beta-reduce with wildcard arguments if this is safe. Makes pos/partialApplications compile. - Fix appliedTo for aliasTypes Returned a general TypeBounds instance before. --- src/dotty/tools/dotc/core/TypeApplications.scala | 48 ++++++++++++++++++++++-- src/dotty/tools/dotc/core/TypeComparer.scala | 6 --- 2 files changed, 45 insertions(+), 9 deletions(-) (limited to 'src/dotty/tools/dotc/core') 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 => diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala index e6cd0a0df..d0c299ae4 100644 --- a/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/src/dotty/tools/dotc/core/TypeComparer.scala @@ -1409,12 +1409,6 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { mergeNames(names1, names2, nme.syntheticParamName), formals1, tp1.resultType & tp2.resultType.subst(tp2, tp1)) case _ => - tp2 match { - case tp2 @ MethodType(names2, formals2) => - println( - TypeComparer.explained(implicit ctx => isSameType(formals1.head, formals2.head))) - case _ => - } mergeConflict(tp1, tp2) } case tp1: PolyType => -- cgit v1.2.3