Skip to content

Commit 4be70a5

Browse files
committed
Merge pull request #1073 from dotty-staging/fix-#576
Handle implicits with default parameters.
2 parents 3c85915 + 5c21583 commit 4be70a5

File tree

2 files changed

+43
-5
lines changed

2 files changed

+43
-5
lines changed

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

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

tests/pos/i576.scala

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
class A
2+
3+
object Impl {
4+
def foo()(implicit x: A = null): Int = 2
5+
def test: Int = {
6+
foo()() // ok
7+
foo() // did not work before, does now
8+
}
9+
}
10+
11+
// same with multiple parameters
12+
object Impl2 {
13+
def foo()(implicit ev: Int, x: A = null): Int = 2
14+
def test: Int = {
15+
implicit val ii: Int = 1
16+
foo()
17+
}
18+
}

0 commit comments

Comments
 (0)