aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/typer
diff options
context:
space:
mode:
authorNicolas Stucki <nicolas.stucki@gmail.com>2016-08-24 13:38:40 +0200
committerNicolas Stucki <nicolas.stucki@gmail.com>2016-09-05 11:52:37 +0200
commitbd54fd04dada033836d2b9113e40b9485a52522a (patch)
tree8bf563d777ea2bdd17cf3578e30e9df9b3681e75 /src/dotty/tools/dotc/typer
parenta0e7adb070ee9c73c0cca081196198296cbd63ab (diff)
downloaddotty-bd54fd04dada033836d2b9113e40b9485a52522a.tar.gz
dotty-bd54fd04dada033836d2b9113e40b9485a52522a.tar.bz2
dotty-bd54fd04dada033836d2b9113e40b9485a52522a.zip
Fix #1468: Add type parameter support for scala.Dynamic
Diffstat (limited to 'src/dotty/tools/dotc/typer')
-rw-r--r--src/dotty/tools/dotc/typer/Applications.scala19
-rw-r--r--src/dotty/tools/dotc/typer/Dynamic.scala32
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala12
3 files changed, 43 insertions, 20 deletions
diff --git a/src/dotty/tools/dotc/typer/Applications.scala b/src/dotty/tools/dotc/typer/Applications.scala
index 099105de3..318f2f8ff 100644
--- a/src/dotty/tools/dotc/typer/Applications.scala
+++ b/src/dotty/tools/dotc/typer/Applications.scala
@@ -593,8 +593,10 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
case ErrorType => tree.withType(ErrorType)
case TryDynamicCallType =>
tree match {
- case tree @ Apply(Select(qual, name), args) if !isDynamicMethod(name) =>
- typedDynamicApply(qual, name, args, pt)(tree)
+ case Apply(Select(qual, name), args) if !isDynamicMethod(name) =>
+ typedDynamicApply(qual, name, None, args, pt)(tree)
+ case Apply(TypeApply(Select(qual, name), targs), args) if !isDynamicMethod(name) =>
+ typedDynamicApply(qual, name, Some(targs), args, pt)(tree)
case _ =>
handleUnexpectedFunType(tree, fun1)
}
@@ -679,7 +681,18 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
}
case _ =>
}
- assignType(cpy.TypeApply(tree)(typedFn, typedArgs), typedFn, typedArgs)
+ if (typedFn.tpe eq TryDynamicCallType) {
+ (pt, typedFn) match {
+ case (_: FunProto, _)=>
+ tree.withType(TryDynamicCallType)
+ case (_, Select(qual, name)) =>
+ typedDynamicSelect(qual, name, Some(typedArgs), pt)
+ case _ =>
+ tree.withType(TryDynamicCallType)
+ }
+ } else {
+ assignType(cpy.TypeApply(tree)(typedFn, typedArgs), typedFn, typedArgs)
+ }
}
/** Rewrite `new Array[T](....)` if T is an unbounded generic to calls to newGenericArray.
diff --git a/src/dotty/tools/dotc/typer/Dynamic.scala b/src/dotty/tools/dotc/typer/Dynamic.scala
index aeb3cca8c..f5303b833 100644
--- a/src/dotty/tools/dotc/typer/Dynamic.scala
+++ b/src/dotty/tools/dotc/typer/Dynamic.scala
@@ -10,7 +10,6 @@ import dotty.tools.dotc.core.Contexts.Context
import dotty.tools.dotc.core.Names.Name
import dotty.tools.dotc.core.StdNames._
import dotty.tools.dotc.core.Types._
-import dotty.tools.dotc.core.Mode
import dotty.tools.dotc.core.Decorators._
object Dynamic {
@@ -30,10 +29,12 @@ object Dynamic {
trait Dynamic { self: Typer with Applications =>
/** Translate selection that does not typecheck according to the normal rules into a applyDynamic/applyDynamicNamed.
- * foo.bar(baz0, baz1, ...) ~~> foo.applyDynamic(bar)(baz0, baz1, ...)
- * foo.bar(x = bazX, y = bazY, baz, ...) ~~> foo.applyDynamicNamed("bar")(("x", bazX), ("y", bazY), ("", baz), ...)
+ * foo.bar(baz0, baz1, ...) ~~> foo.applyDynamic(bar)(baz0, baz1, ...)
+ * foo.bar[T0, ...](baz0, baz1, ...) ~~> foo.applyDynamic[T0, ...](bar)(baz0, baz1, ...)
+ * foo.bar(x = bazX, y = bazY, baz, ...) ~~> foo.applyDynamicNamed("bar")(("x", bazX), ("y", bazY), ("", baz), ...)
+ * foo.bar[T0, ...](x = bazX, y = bazY, baz, ...) ~~> foo.applyDynamicNamed[T0, ...]("bar")(("x", bazX), ("y", bazY), ("", baz), ...)
*/
- def typedDynamicApply(qual: untpd.Tree, name: Name, args: List[untpd.Tree], pt: Type)(original: untpd.Apply)(
+ def typedDynamicApply(qual: untpd.Tree, name: Name, targsOpt: Option[List[untpd.Tree]], args: List[untpd.Tree], pt: Type)(original: untpd.Apply)(
implicit ctx: Context): Tree = {
def isNamedArg(arg: untpd.Tree): Boolean = arg match { case NamedArg(_, _) => true; case _ => false }
val dynName = if (args.exists(isNamedArg)) nme.applyDynamicNamed else nme.applyDynamic
@@ -47,25 +48,32 @@ trait Dynamic { self: Typer with Applications =>
case arg => namedArgTuple("", arg)
}
val args1 = if (dynName == nme.applyDynamic) args else namedArgs
- typedApply(untpd.Apply(coreDynamic(qual, dynName, name), args1), pt)
+ typedApply(untpd.Apply(coreDynamic(qual, dynName, name, targsOpt), args1), pt)
}
}
/** Translate selection that does not typecheck according to the normal rules into a selectDynamic.
- * foo.bar ~~> foo.selectDynamic(bar)
+ * foo.bar ~~> foo.selectDynamic(bar)
+ * foo.bar[T0, ...] ~~> foo.selectDynamic[T0, ...](bar)
*
* Note: inner part of translation foo.bar(baz) = quux ~~> foo.selectDynamic(bar).update(baz, quux) is achieved
* through an existing transformation of in typedAssign [foo.bar(baz) = quux ~~> foo.bar.update(baz, quux)].
*/
- def typedDynamicSelect(tree: untpd.Select, pt: Type)(implicit ctx: Context): Tree =
- typedApply(coreDynamic(tree.qualifier, nme.selectDynamic, tree.name), pt)
+ def typedDynamicSelect(qualifier: untpd.Tree, name: Name, targsOpt: Option[List[Tree]], pt: Type)(implicit ctx: Context): Tree =
+ typedApply(coreDynamic(qualifier, nme.selectDynamic, name, targsOpt), pt)
/** Translate selection that does not typecheck according to the normal rules into a updateDynamic.
* foo.bar = baz ~~> foo.updateDynamic(bar)(baz)
*/
- def typedDynamicAssign(qual: untpd.Tree, name: Name, rhs: untpd.Tree, pt: Type)(implicit ctx: Context): Tree =
- typedApply(untpd.Apply(coreDynamic(qual, nme.updateDynamic, name), rhs), pt)
+ def typedDynamicAssign(qual: untpd.Tree, name: Name, targsOpt: Option[List[untpd.Tree]], rhs: untpd.Tree, pt: Type)(implicit ctx: Context): Tree =
+ typedApply(untpd.Apply(coreDynamic(qual, nme.updateDynamic, name, targsOpt), rhs), pt)
- private def coreDynamic(qual: untpd.Tree, dynName: Name, name: Name)(implicit ctx: Context): untpd.Apply =
- untpd.Apply(untpd.Select(qual, dynName), Literal(Constant(name.toString)))
+ private def coreDynamic(qual: untpd.Tree, dynName: Name, name: Name, targsOpt: Option[List[untpd.Tree]])(implicit ctx: Context): untpd.Apply = {
+ val select = untpd.Select(qual, dynName)
+ val selectWithTypes = targsOpt match {
+ case Some(targs) => untpd.TypeApply(select, targs)
+ case None => select
+ }
+ untpd.Apply(selectWithTypes, Literal(Constant(name.toString)))
+ }
}
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index fdcfe347b..cce692b42 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -318,10 +318,10 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
if (tree.name.isTypeName) checkStable(qual1.tpe, qual1.pos)
val select = typedSelect(tree, pt, qual1)
pt match {
- case _: FunProto | AssignProto => select
- case _ =>
- if (select.tpe eq TryDynamicCallType) typedDynamicSelect(tree, pt)
- else select
+ case _ if select.tpe ne TryDynamicCallType => select
+ case _: FunProto | AssignProto => select
+ case PolyProto(_,_) => select
+ case _ => typedDynamicSelect(tree.qualifier, tree.name, None, pt)
}
}
@@ -520,7 +520,9 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
case TryDynamicCallType =>
tree match {
case Assign(Select(qual, name), rhs) if !isDynamicMethod(name) =>
- typedDynamicAssign(qual, name, rhs, pt)
+ typedDynamicAssign(qual, name, None, rhs, pt)
+ case Assign(TypeApply(Select(qual, name), targs), rhs) if !isDynamicMethod(name) =>
+ typedDynamicAssign(qual, name, Some(targs), rhs, pt)
case _ => reassignmentToVal
}
case tpe =>