diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/dotty/tools/dotc/ast/TreeInfo.scala | 14 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Applications.scala | 19 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Dynamic.scala | 32 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Typer.scala | 12 |
4 files changed, 43 insertions, 34 deletions
diff --git a/src/dotty/tools/dotc/ast/TreeInfo.scala b/src/dotty/tools/dotc/ast/TreeInfo.scala index a48651ebf..7c3f7f385 100644 --- a/src/dotty/tools/dotc/ast/TreeInfo.scala +++ b/src/dotty/tools/dotc/ast/TreeInfo.scala @@ -630,20 +630,6 @@ object TreeInfo { } } - def isApplyDynamicName(name: Name) = (name == nme.updateDynamic) || (name == nme.selectDynamic) || (name == nme.applyDynamic) || (name == nme.applyDynamicNamed) - - class DynamicApplicationExtractor(nameTest: Name => Boolean) { - def unapply(tree: Tree) = tree match { - case Apply(TypeApply(Select(qual, oper), _), List(Literal(Constant(name)))) if nameTest(oper) => Some((qual, name)) - case Apply(Select(qual, oper), List(Literal(Constant(name)))) if nameTest(oper) => Some((qual, name)) - case Apply(Ident(oper), List(Literal(Constant(name)))) if nameTest(oper) => Some((EmptyTree(), name)) - case _ => None - } - } - object DynamicUpdate extends DynamicApplicationExtractor(_ == nme.updateDynamic) - object DynamicApplication extends DynamicApplicationExtractor(isApplyDynamicName) - object DynamicApplicationNamed extends DynamicApplicationExtractor(_ == nme.applyDynamicNamed) - object MacroImplReference { private def refPart(tree: Tree): Tree = tree match { case TypeApply(fun, _) => refPart(fun) 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 => |