Skip to content

Commit c4be219

Browse files
committed
Handle implicits with default parameters
If an implicit parameter has a default, then that default should be taken in case no implicit argument is found.
1 parent afec2a7 commit c4be219

File tree

1 file changed

+25
-5
lines changed

1 file changed

+25
-5
lines changed

src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1435,10 +1435,15 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
14351435
wtp.paramTypes.foreach(instantiateSelected(_, tvarsToInstantiate))
14361436
val constr = ctx.typerState.constraint
14371437
def addImplicitArgs = {
1438-
def implicitArgError(msg: => String): Tree = {
1439-
ctx.error(msg, tree.pos.endPos)
1438+
val errors = new mutable.ListBuffer[() => String]
1439+
def implicitArgError(msg: => String) = {
1440+
errors += (() => msg)
14401441
EmptyTree
14411442
}
1443+
def issueErrors() = {
1444+
for (err <- errors) ctx.error(err(), tree.pos.endPos)
1445+
tree
1446+
}
14421447
val args = (wtp.paramNames, wtp.paramTypes).zipped map { (pname, formal) =>
14431448
def where = d"parameter $pname of $methodStr"
14441449
inferImplicit(formal, EmptyTree, tree.pos.endPos) match {
@@ -1450,12 +1455,27 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
14501455
implicitArgError(d"no implicit argument of type $formal found for $where" + failure.postscript)
14511456
}
14521457
}
1453-
if (args.exists(_.isEmpty)) {
1458+
if (errors.nonEmpty) {
14541459
// If there are several arguments, some arguments might already
1455-
// have influenced the context, binfing variables, but later ones
1460+
// have influenced the context, binding variables, but later ones
14561461
// might fail. In that case the constraint needs to be reset.
14571462
ctx.typerState.constraint = constr
1458-
tree
1463+
1464+
// If method has default params, fall back to regular application
1465+
// where all inferred implicits are passed as named args.
1466+
if (tree.symbol.hasDefaultParams) {
1467+
val namedArgs = (wtp.paramNames, args).zipped.flatMap { (pname, arg) =>
1468+
arg match {
1469+
case EmptyTree => Nil
1470+
case _ => untpd.NamedArg(pname, untpd.TypedSplice(arg)) :: Nil
1471+
}
1472+
}
1473+
tryEither { implicit ctx =>
1474+
typed(untpd.Apply(untpd.TypedSplice(tree), namedArgs), pt)
1475+
} { (_, _) =>
1476+
issueErrors()
1477+
}
1478+
} else issueErrors()
14591479
}
14601480
else adapt(tpd.Apply(tree, args), pt)
14611481
}

0 commit comments

Comments
 (0)