diff options
author | Martin Odersky <odersky@gmail.com> | 2014-05-01 11:16:34 +0200 |
---|---|---|
committer | Dmitry Petrashko <dmitry.petrashko@gmail.com> | 2014-05-08 21:51:47 +0200 |
commit | 9099df69ceb9a73073c63ba051d7da1230cf25fa (patch) | |
tree | 7eb1ee323a50f54000a4eb8a00fe92b5548a9a75 /src/dotty | |
parent | cb1f9cb03f9610d0c6f4d8aa08b9144e90dcf2b5 (diff) | |
download | dotty-9099df69ceb9a73073c63ba051d7da1230cf25fa.tar.gz dotty-9099df69ceb9a73073c63ba051d7da1230cf25fa.tar.bz2 dotty-9099df69ceb9a73073c63ba051d7da1230cf25fa.zip |
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.
Diffstat (limited to 'src/dotty')
-rw-r--r-- | src/dotty/tools/dotc/core/TypeApplications.scala | 42 |
1 files changed, 28 insertions, 14 deletions
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) |