@@ -3707,7 +3707,6 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
37073707
37083708 private def adapt1 (tree : Tree , pt : Type , locked : TypeVars )(using Context ): Tree = {
37093709 assert(pt.exists && ! pt.isInstanceOf [ExprType ] || ctx.reporter.errorsReported, i " tree: $tree, pt: $pt" )
3710- def methodStr = err.refStr(methPart(tree).tpe)
37113710
37123711 def readapt (tree : Tree )(using Context ) = adapt(tree, pt, locked)
37133712 def readaptSimplified (tree : Tree )(using Context ) = readapt(simplify(tree, pt, locked))
@@ -3872,49 +3871,37 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
38723871 arg :: inferArgsAfter(arg)
38733872 end implicitArgs
38743873
3875- val args = implicitArgs(wtp.paramInfos, 0 , pt)
3876-
3877- def propagatedFailure (args : List [Tree ]): Type = args match {
3878- case arg :: args1 =>
3879- arg.tpe match {
3880- case ambi : AmbiguousImplicits =>
3881- propagatedFailure(args1) match {
3882- case NoType | (_ : AmbiguousImplicits ) => ambi
3883- case failed => failed
3884- }
3885- case failed : SearchFailureType => failed
3886- case _ => propagatedFailure(args1)
3887- }
3888- case Nil => NoType
3889- }
3890-
3891- val propFail = propagatedFailure(args)
3892-
3893- def issueErrors (): Tree = {
3894- def paramSymWithMethodTree (paramName : TermName ) =
3895- if tree.symbol.exists then
3896- tree.symbol.paramSymss.flatten
3897- .map(sym => sym.name -> sym)
3898- .toMap
3899- .get(paramName)
3900- .map((_, tree))
3901- else
3902- None
3874+ /** Reports errors for arguments of `appTree` that have a
3875+ * `SearchFailureType`.
3876+ */
3877+ def issueErrors (fun : Tree , args : List [Tree ]): Tree =
3878+ def firstFailure = args.tpes.find(_.isInstanceOf [SearchFailureType ]).getOrElse(NoType )
3879+ val errorType =
3880+ firstFailure match
3881+ case tp : AmbiguousImplicits =>
3882+ AmbiguousImplicits (tp.alt1, tp.alt2, tp.expectedType, tp.argument, nested = true )
3883+ case tp =>
3884+ tp
3885+ val res = untpd.Apply (fun, args).withType(errorType)
39033886
39043887 wtp.paramNames.lazyZip(wtp.paramInfos).lazyZip(args).foreach { (paramName, formal, arg) =>
3905- arg.tpe match {
3888+ arg.tpe match
39063889 case failure : SearchFailureType =>
3890+ val methodStr = err.refStr(methPart(fun).tpe)
3891+ val paramStr = implicitParamString(paramName, methodStr, fun)
3892+ val paramSym = fun.symbol.paramSymss.flatten.find(_.name == paramName)
3893+ val paramSymWithMethodCallTree = paramSym.map((_, res))
39073894 report.error(
3908- missingArgMsg(arg, formal, implicitParamString(paramName, methodStr, tree), paramSymWithMethodTree(paramName) ),
3909- tree.srcPos.endPos
3910- )
3895+ missingArgMsg(arg, formal, paramStr, paramSymWithMethodCallTree ),
3896+ tree.srcPos.endPos
3897+ )
39113898 case _ =>
3912- }
39133899 }
3914- untpd.Apply (tree, args).withType(propFail)
3915- }
39163900
3917- if (propFail.exists) {
3901+ res
3902+
3903+ val args = implicitArgs(wtp.paramInfos, 0 , pt)
3904+ if (args.tpes.exists(_.isInstanceOf [SearchFailureType ])) {
39183905 // If there are several arguments, some arguments might already
39193906 // have influenced the context, binding variables, but later ones
39203907 // might fail. In that case the constraint and instantiated variables
@@ -3923,18 +3910,31 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
39233910
39243911 // If method has default params, fall back to regular application
39253912 // where all inferred implicits are passed as named args.
3926- if hasDefaultParams && ! propFail.isInstanceOf [AmbiguousImplicits ] then
3927- val namedArgs = wtp.paramNames.lazyZip(args).flatMap { (pname, arg) =>
3928- if (arg.tpe.isError) Nil else untpd.NamedArg (pname, untpd.TypedSplice (arg)) :: Nil
3929- }
3913+ if hasDefaultParams then
3914+ // Only keep the arguments that don't have an error type, or that
3915+ // have an `AmbiguousImplicits` error type. The later ensures that a
3916+ // default argument can't override an ambiguous implicit. See tests
3917+ // `given-ambiguous-default*` and `19414*`.
3918+ val namedArgs =
3919+ wtp.paramNames.lazyZip(args)
3920+ .filter((_, arg) => ! arg.tpe.isError || arg.tpe.isInstanceOf [AmbiguousImplicits ])
3921+ .map((pname, arg) => untpd.NamedArg (pname, untpd.TypedSplice (arg)))
3922+
39303923 val app = cpy.Apply (tree)(untpd.TypedSplice (tree), namedArgs)
39313924 val needsUsing = wtp.isContextualMethod || wtp.match
39323925 case MethodType (ContextBoundParamName (_) :: _) => sourceVersion.isAtLeast(`3.4`)
39333926 case _ => false
39343927 if needsUsing then app.setApplyKind(ApplyKind .Using )
39353928 typr.println(i " try with default implicit args $app" )
3936- typed(app, pt, locked)
3937- else issueErrors()
3929+ val retyped = typed(app, pt, locked)
3930+
3931+ // If the retyped tree still has an error type and is an `Apply`
3932+ // node, we can report the errors for each argument nicely.
3933+ // Otherwise, we don't report anything here.
3934+ retyped match
3935+ case Apply (tree, args) if retyped.tpe.isError => issueErrors(tree, args)
3936+ case _ => retyped
3937+ else issueErrors(tree, args)
39383938 }
39393939 else tree match {
39403940 case tree : Block =>
0 commit comments