From 9099df69ceb9a73073c63ba051d7da1230cf25fa Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 1 May 2014 11:16:34 +0200 Subject: Fix for type applications. Test case in TreeTransformers.scala. We have there type Mutator[T] = (TreeTransform, T, Context) => TreeTransform It turns out that then Mutator[X] for some type X did not typecheck because the typer got confused what were the type parameters of the Function3 type on Mutator's RHS. The fix adds a case to handle RefinedTypes that bind type parameters. --- src/dotty/tools/dotc/core/TypeApplications.scala | 42 ++++++++++++++++-------- 1 file changed, 28 insertions(+), 14 deletions(-) (limited to 'src/dotty') diff --git a/src/dotty/tools/dotc/core/TypeApplications.scala b/src/dotty/tools/dotc/core/TypeApplications.scala index 4b251f183..c4845a249 100644 --- a/src/dotty/tools/dotc/core/TypeApplications.scala +++ b/src/dotty/tools/dotc/core/TypeApplications.scala @@ -111,7 +111,7 @@ class TypeApplications(val self: Type) extends AnyVal { /** Encode the type resulting from applying this type to given arguments */ final def appliedTo(args: List[Type])(implicit ctx: Context): Type = /*>|>*/ track("appliedTo") /*<|<*/ { - def recur(tp: Type, tparams: List[TypeSymbol], args: List[Type]): Type = args match { + def matchParams(tp: Type, tparams: List[TypeSymbol], args: List[Type]): Type = args match { case arg :: args1 => if (tparams.isEmpty) { println(s"applied type mismatch: $self $args, typeParams = $typeParams, tsym = ${self.typeSymbol.debugString}") // !!! DEBUG @@ -119,32 +119,46 @@ class TypeApplications(val self: Type) extends AnyVal { } val tparam = tparams.head val tp1 = RefinedType(tp, tparam.name, arg.toBounds(tparam)) - recur(tp1, tparams.tail, args1) + matchParams(tp1, tparams.tail, args1) case nil => tp } - def safeTypeParams(tsym: Symbol) = - if (tsym.isClass || !self.typeSymbol.isCompleting) typeParams - else { - ctx.warning("encountered F-bounded higher-kinded type parameters; assuming they are invariant") - defn.hkTrait(args map alwaysZero).typeParams - } - - if (args.isEmpty || !canHaveTypeParams) self - else self match { + /** Instantiate type `tp` with `args`. + * @param original The original type for which we compute the type parameters + * This makes a difference for refinement types, because + * refinements bind type parameters and thereby remove them + * from `typeParams`. + */ + def instantiate(tp: Type, original: Type): Type = tp match { case tp: TypeRef => val tsym = tp.symbol if (tsym.isAliasType) tp.underlying.appliedTo(args) - else recur(tp, safeTypeParams(tsym), args) + else { + val safeTypeParams = + if (tsym.isClass || !tp.typeSymbol.isCompleting) original.typeParams + else { + ctx.warning("encountered F-bounded higher-kinded type parameters; assuming they are invariant") + defn.hkTrait(args map alwaysZero).typeParams + } + matchParams(tp, safeTypeParams, args) + } + case tp: RefinedType => + tp.derivedRefinedType( + instantiate(tp.parent, original), + tp.refinedName, + tp.refinedInfo) case tp: TypeProxy => - tp.underlying.appliedTo(args) + instantiate(tp.underlying, original) case AndType(l, r) => l.appliedTo(args) & r case tp: PolyType => tp.instantiate(args) case ErrorType => - self + tp } + + if (args.isEmpty || !canHaveTypeParams) self + else instantiate(self, self) } final def appliedTo(arg: Type)(implicit ctx: Context): Type = appliedTo(arg :: Nil) -- cgit v1.2.3