diff options
author | Martin Odersky <odersky@gmail.com> | 2016-08-18 17:24:11 +0200 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2016-08-18 17:49:06 +0200 |
commit | d5ef867b1f89c79f8620129693e4f1e9bc6f617c (patch) | |
tree | 90b573d0452c362d6dbe6be0731f22d211d35200 /src/dotty/tools/dotc/typer/Applications.scala | |
parent | 5a5f9d7ed37ca6449ef61ee5e0f6fbf9731df795 (diff) | |
download | dotty-d5ef867b1f89c79f8620129693e4f1e9bc6f617c.tar.gz dotty-d5ef867b1f89c79f8620129693e4f1e9bc6f617c.tar.bz2 dotty-d5ef867b1f89c79f8620129693e4f1e9bc6f617c.zip |
Refinements to auto tupling
There's a nasty interaction with auto-tupling and trying to insert an implicit
on the qualifier of a call. If the original call fails, we need to "undo" any
auto-tupling decisions in calls where an implicit is inserted on the qualifier.
Also: Needed to fix canAutoTuple test so that Scala2 feature is checked instead of dotty's.
Also: Drop features in dotty.language that duplicate those in scala.language.
Diffstat (limited to 'src/dotty/tools/dotc/typer/Applications.scala')
-rw-r--r-- | src/dotty/tools/dotc/typer/Applications.scala | 32 |
1 files changed, 21 insertions, 11 deletions
diff --git a/src/dotty/tools/dotc/typer/Applications.scala b/src/dotty/tools/dotc/typer/Applications.scala index c8f41b7fa..efd12cb5e 100644 --- a/src/dotty/tools/dotc/typer/Applications.scala +++ b/src/dotty/tools/dotc/typer/Applications.scala @@ -541,17 +541,29 @@ trait Applications extends Compatibility { self: Typer with Dynamic => def typedApply(tree: untpd.Apply, pt: Type)(implicit ctx: Context): Tree = { + /** Try same application with an implicit inserted around the qualifier of the function + * part. Return an optional value to indicate success. + */ + def tryWithImplicitOnQualifier(fun1: Tree, proto: FunProto)(implicit ctx: Context): Option[Tree] = + tryInsertImplicitOnQualifier(fun1, proto) flatMap { fun2 => + tryEither { implicit ctx => + Some(typedApply( + cpy.Apply(tree)(untpd.TypedSplice(fun2), proto.typedArgs map untpd.TypedSplice), + pt)): Option[Tree] + } { (_, _) => None } + } + def realApply(implicit ctx: Context): Tree = track("realApply") { - var proto = new FunProto(tree.args, IgnoredProto(pt), this)(argCtx(tree)) - val fun1 = typedExpr(tree.fun, proto) + val originalProto = new FunProto(tree.args, IgnoredProto(pt), this)(argCtx(tree)) + val fun1 = typedExpr(tree.fun, originalProto) - // Warning: The following line is dirty and fragile. We record that auto-tupling was demanded as + // Warning: The following lines are dirty and fragile. We record that auto-tupling was demanded as // a side effect in adapt. If it was, we assume the tupled proto-type in the rest of the application. // This crucially relies on he fact that `proto` is used only in a single call of `adapt`, // otherwise we would get possible cross-talk between different `adapt` calls using the same // prototype. A cleaner alternative would be to return a modified prototype from `adapt` together with // a modified tree but this would be more convoluted and less efficient. - if (proto.isTupled) proto = proto.tupled + val proto = if (originalProto.isTupled) originalProto.tupled else originalProto // If some of the application's arguments are function literals without explicitly declared // parameter types, relate the normalized result type of the application with the @@ -580,13 +592,11 @@ trait Applications extends Compatibility { self: Typer with Dynamic => val result = app.result convertNewGenericArray(ConstFold(result)) } { (failedVal, failedState) => - val fun2 = tryInsertImplicitOnQualifier(fun1, proto) - if (fun1 eq fun2) { - failedState.commit() - failedVal - } else typedApply( - cpy.Apply(tree)(untpd.TypedSplice(fun2), proto.typedArgs map untpd.TypedSplice), pt) - } + def fail = { failedState.commit(); failedVal } + tryWithImplicitOnQualifier(fun1, originalProto).getOrElse( + if (proto eq originalProto) fail + else tryWithImplicitOnQualifier(fun1, proto).getOrElse(fail)) + } case _ => handleUnexpectedFunType(tree, fun1) } |