From 86bf552cd421288b00525eb1a264652ee32d742d Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sat, 11 Mar 2017 20:52:03 +0100 Subject: Take parameter dependencies into account Take parameter dependencies into account when typechecking arguments. --- .../src/dotty/tools/dotc/typer/Applications.scala | 26 +++++++++++++++++----- .../src/dotty/tools/dotc/typer/ProtoTypes.scala | 6 +++++ 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index b459e2745..5dcf16b62 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -178,6 +178,8 @@ trait Applications extends Compatibility { self: Typer with Dynamic => */ protected def normalizedFun: Tree + protected def typeOfArg(arg: Arg): Type + /** If constructing trees, pull out all parts of the function * which are not idempotent into separate prefix definitions */ @@ -380,8 +382,16 @@ trait Applications extends Compatibility { self: Typer with Dynamic => if (success) formals match { case formal :: formals1 => - def addTyped(arg: Arg, formal: Type) = + /** Add result of typing argument `arg` against parameter type `formal`. + * @return A type transformation to apply to all arguments following this one. + */ + def addTyped(arg: Arg, formal: Type): Type => Type = { addArg(typedArg(arg, formal), formal) + if (methodType.isParamDependent) + _.substParam(MethodParam(methodType, n), typeOfArg(arg)) + else + identity + } def missingArg(n: Int): Unit = { val pname = methodType.paramNames(n) @@ -395,8 +405,10 @@ trait Applications extends Compatibility { self: Typer with Dynamic => val getter = findDefaultGetter(n + numArgs(normalizedFun)) if (getter.isEmpty) missingArg(n) else { - addTyped(treeToArg(spliceMeth(getter withPos normalizedFun.pos, normalizedFun)), formal) - matchArgs(args1, formals1, n + 1) + val substParam = addTyped( + treeToArg(spliceMeth(getter withPos normalizedFun.pos, normalizedFun)), + formal) + matchArgs(args1, formals1.mapconserve(substParam), n + 1) } } @@ -420,8 +432,8 @@ trait Applications extends Compatibility { self: Typer with Dynamic => case EmptyTree :: args1 => tryDefault(n, args1) case arg :: args1 => - addTyped(arg, formal) - matchArgs(args1, formals1, n + 1) + val substParam = addTyped(arg, formal) + matchArgs(args1, formals1.mapconserve(substParam), n + 1) case nil => tryDefault(n, args) } @@ -477,6 +489,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic => def argType(arg: Tree, formal: Type): Type = normalize(arg.tpe, formal) def treeToArg(arg: Tree): Tree = arg def isVarArg(arg: Tree): Boolean = tpd.isWildcardStarArg(arg) + def typeOfArg(arg: Tree): Type = arg.tpe def harmonizeArgs(args: List[Tree]) = harmonize(args) } @@ -494,6 +507,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic => def argType(arg: Type, formal: Type): Type = arg def treeToArg(arg: Tree): Type = arg.tpe def isVarArg(arg: Type): Boolean = arg.isRepeatedParam + def typeOfArg(arg: Type): Type = arg def harmonizeArgs(args: List[Type]) = harmonizeTypes(args) } @@ -592,6 +606,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic => extends TypedApply(app, fun, methRef, proto.args, resultType) { def typedArg(arg: untpd.Tree, formal: Type): TypedArg = proto.typedArg(arg, formal.widenExpr) def treeToArg(arg: Tree): untpd.Tree = untpd.TypedSplice(arg) + def typeOfArg(arg: untpd.Tree) = proto.typeOfArg(arg) } /** Subclass of Application for type checking an Apply node with typed arguments. */ @@ -603,6 +618,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic => // not match the abstract method in Application and an abstract class error results. def typedArg(arg: tpd.Tree, formal: Type): TypedArg = arg def treeToArg(arg: Tree): Tree = arg + def typeOfArg(arg: Tree) = arg.tpe } /** If `app` is a `this(...)` constructor call, the this-call argument context, diff --git a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala index b588e3ae5..77d654ad8 100644 --- a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala +++ b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala @@ -237,6 +237,12 @@ object ProtoTypes { typer.adapt(targ, formal, arg) } + /** The type of the argument `arg`. + * @pre `arg` ahs been typed before + */ + def typeOfArg(arg: untpd.Tree)(implicit ctx: Context): Type = + myTypedArg(arg).tpe + private var myTupled: Type = NoType /** The same proto-type but with all arguments combined in a single tuple */ -- cgit v1.2.3