aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core/TypeApplications.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2014-05-01 11:16:34 +0200
committerDmitry Petrashko <dmitry.petrashko@gmail.com>2014-05-08 21:51:47 +0200
commit9099df69ceb9a73073c63ba051d7da1230cf25fa (patch)
tree7eb1ee323a50f54000a4eb8a00fe92b5548a9a75 /src/dotty/tools/dotc/core/TypeApplications.scala
parentcb1f9cb03f9610d0c6f4d8aa08b9144e90dcf2b5 (diff)
downloaddotty-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/tools/dotc/core/TypeApplications.scala')
-rw-r--r--src/dotty/tools/dotc/core/TypeApplications.scala42
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)