aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/typer/Applications.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/dotty/tools/dotc/typer/Applications.scala')
-rw-r--r--src/dotty/tools/dotc/typer/Applications.scala32
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)
}