@@ -36,7 +36,6 @@ import util.{Property, SimpleIdentityMap, SrcPos}
3636import  Applications .{tupleComponentTypes , wrapDefs , defaultArgument }
3737
3838import  collection .mutable 
39- import  annotation .tailrec 
4039import  Implicits .* 
4140import  util .Stats .record 
4241import  config .Printers .{gadts , typr }
@@ -52,7 +51,8 @@ import config.Config
5251import  config .MigrationVersion 
5352import  transform .CheckUnused .OriginalName 
5453
55- import  scala .annotation .constructorOnly 
54+ import  scala .annotation .{unchecked  as  _ , * }
55+ import  dotty .tools .dotc .util .chaining .* 
5656
5757object  Typer  {
5858
@@ -4239,6 +4239,12 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
42394239
42404240      def  addImplicitArgs (using  Context ) = 
42414241        def  hasDefaultParams  =  methPart(tree).symbol.hasDefaultParams
4242+         def  findDefaultArgument (argIndex : Int ):  Tree  = 
4243+           def  appPart (t : Tree ):  Tree  =  t match 
4244+             case  Block (_, expr)      =>  appPart(expr)
4245+             case  Inlined (_, _, expr) =>  appPart(expr)
4246+             case  t =>  t
4247+           defaultArgument(appPart(tree), n =  argIndex, testOnly =  false )
42424248        def  implicitArgs (formals : List [Type ], argIndex : Int , pt : Type ):  List [Tree ] =  formals match 
42434249          case  Nil  =>  Nil 
42444250          case  formal ::  formals1 => 
@@ -4260,13 +4266,8 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
42604266                then  implicitArgs(formals, argIndex, pt1)
42614267                else  arg ::  implicitArgs(formals1, argIndex +  1 , pt1)
42624268              case  failed : SearchFailureType  => 
4263-                 lazy  val  defaultArg  = 
4264-                   def  appPart (t : Tree ):  Tree  =  t match 
4265-                     case  Block (stats, expr) =>  appPart(expr)
4266-                     case  Inlined (_, _, expr) =>  appPart(expr)
4267-                     case  _ =>  t
4268-                   defaultArgument(appPart(tree), argIndex, testOnly =  false )
4269-                     .showing(i " default argument: for  $formal,  $tree,  $argIndex =  $result" , typr)
4269+                 lazy  val  defaultArg  =  findDefaultArgument(argIndex)
4270+                   .showing(i " default argument: for  $formal,  $tree,  $argIndex =  $result" , typr)
42704271                if  ! hasDefaultParams ||  defaultArg.isEmpty then 
42714272                  //  no need to search further, the adapt fails in any case
42724273                  //  the reason why we continue inferring arguments in case of an AmbiguousImplicits
@@ -4288,44 +4289,44 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
42884289                arg ::  inferArgsAfter(arg)
42894290        end  implicitArgs 
42904291
4291-         /**  Reports errors for arguments of `appTree` that have a 
4292-           * `SearchFailureType`. 
4293-           */  
4294-         def  issueErrors (fun : Tree , args : List [Tree ]):  Tree  = 
4295-           //  Prefer other errors over ambiguities. If nested in outer searches a missing
4296-           //  implicit can be healed by simply dropping this alternative and trying something
4297-           //  else. But an ambiguity is sticky and propagates outwards. If we have both
4298-           //  a missing implicit on one argument and an ambiguity on another the whole
4299-           //  branch should be classified as a missing implicit.
4300-           val  firstNonAmbiguous  =  args.tpes.find(tp =>  tp.isError &&  ! tp.isInstanceOf [AmbiguousImplicits ])
4301-           def  firstError  =  args.tpes.find(_.isInstanceOf [SearchFailureType ]).getOrElse(NoType )
4302-           def  firstFailure  =  firstNonAmbiguous.getOrElse(firstError)
4303-           val  errorType  = 
4304-             firstFailure match 
4305-               case  tp : AmbiguousImplicits  => 
4306-                 AmbiguousImplicits (tp.alt1, tp.alt2, tp.expectedType, tp.argument, nested =  true )
4307-               case  tp => 
4308-                 tp
4309-           val  res  =  untpd.Apply (fun, args).withType(errorType)
4310- 
4311-           wtp.paramNames.lazyZip(wtp.paramInfos).lazyZip(args).foreach { (paramName, formal, arg) => 
4312-             arg.tpe match 
4313-               case  failure : SearchFailureType  => 
4314-                 val  methodStr  =  err.refStr(methPart(fun).tpe)
4315-                 val  paramStr  =  implicitParamString(paramName, methodStr, fun)
4316-                 val  paramSym  =  fun.symbol.paramSymss.flatten.find(_.name ==  paramName)
4317-                 val  paramSymWithMethodCallTree  =  paramSym.map((_, res))
4318-                 report.error(
4319-                    missingArgMsg(arg, formal, paramStr, paramSymWithMethodCallTree),
4320-                    tree.srcPos.endPos
4321-                  )
4322-               case  _ => 
4323-           }
4324- 
4325-           res
4292+         //  Pick a failure type to propagate, if any.
4293+         //  Prefer other errors over ambiguities. If nested in outer searches a missing
4294+         //  implicit can be healed by simply dropping this alternative and trying something
4295+         //  else. But an ambiguity is sticky and propagates outwards. If we have both
4296+         //  a missing implicit on one argument and an ambiguity on another the whole
4297+         //  branch should be classified as a missing implicit.
4298+         def  propagatedFailure (args : List [Tree ]):  Type  =  args match 
4299+           case  arg ::  args =>  arg.tpe match 
4300+             case  ambi : AmbiguousImplicits  =>  propagatedFailure(args) match 
4301+               case  NoType  |  (_ : AmbiguousImplicits ) =>  ambi
4302+               case  failed =>  failed
4303+             case  failed : SearchFailureType  =>  failed
4304+             case  _ =>  propagatedFailure(args)
4305+           case  Nil  =>  NoType 
4306+ 
4307+         /**  Reports errors for arguments of `appTree` that have a `SearchFailureType`. 
4308+          */  
4309+         def  issueErrors (fun : Tree , args : List [Tree ], failureType : Type ):  Tree  = 
4310+           val  errorType  =  failureType match 
4311+             case  ai : AmbiguousImplicits  =>  ai.asNested
4312+             case  tp =>  tp
4313+           untpd.Apply (fun, args)
4314+             .withType(errorType)
4315+             .tap:  res => 
4316+               wtp.paramNames.lazyZip(wtp.paramInfos).lazyZip(args).foreach:  (paramName, formal, arg) => 
4317+                 arg.tpe match 
4318+                 case  failure : SearchFailureType  => 
4319+                   val  methodStr  =  err.refStr(methPart(fun).tpe)
4320+                   val  paramStr  =  implicitParamString(paramName, methodStr, fun)
4321+                   val  paramSym  =  fun.symbol.paramSymss.flatten.find(_.name ==  paramName)
4322+                   val  paramSymWithMethodCallTree  =  paramSym.map((_, res))
4323+                   val  msg  =  missingArgMsg(arg, formal, paramStr, paramSymWithMethodCallTree)
4324+                   report.error(msg, tree.srcPos.endPos)
4325+                 case  _ => 
43264326
43274327        val  args  =  implicitArgs(wtp.paramInfos, 0 , pt)
4328-         if  (args.tpes.exists(_.isInstanceOf [SearchFailureType ])) {
4328+         val  failureType  =  propagatedFailure(args)
4329+         if  failureType.exists then 
43294330          //  If there are several arguments, some arguments might already
43304331          //  have influenced the context, binding variables, but later ones
43314332          //  might fail. In that case the constraint and instantiated variables
@@ -4334,32 +4335,40 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
43344335
43354336          //  If method has default params, fall back to regular application
43364337          //  where all inferred implicits are passed as named args.
4337-           if  hasDefaultParams then 
4338+           if  hasDefaultParams &&   ! failureType. isInstanceOf [ AmbiguousImplicits ]  then 
43384339            //  Only keep the arguments that don't have an error type, or that
4339-             //  have an `AmbiguousImplicits` error type. The later  ensures that a
4340+             //  have an `AmbiguousImplicits` error type. The latter  ensures that a
43404341            //  default argument can't override an ambiguous implicit. See tests
43414342            //  `given-ambiguous-default*` and `19414*`.
43424343            val  namedArgs  = 
4343-               wtp.paramNames.lazyZip(args)
4344-                 .filter((_, arg) =>  ! arg.tpe.isError ||  arg.tpe.isInstanceOf [AmbiguousImplicits ])
4345-                 .map((pname, arg) =>  untpd.NamedArg (pname, untpd.TypedSplice (arg)))
4346- 
4347-             val  app  =  cpy.Apply (tree)(untpd.TypedSplice (tree), namedArgs)
4348-             val  needsUsing  =  wtp.isContextualMethod ||  wtp.match 
4349-               case  MethodType (ContextBoundParamName (_) ::  _) =>  sourceVersion.isAtLeast(`3.4`)
4350-               case  _ =>  false 
4351-             if  needsUsing then  app.setApplyKind(ApplyKind .Using )
4352-             typr.println(i " try with default implicit args  $app" )
4353-             val  retyped  =  typed(app, pt, locked)
4354- 
4355-             //  If the retyped tree still has an error type and is an `Apply`
4356-             //  node, we can report the errors for each argument nicely.
4357-             //  Otherwise, we don't report anything here.
4358-             retyped match 
4359-               case  Apply (tree, args) if  retyped.tpe.isError =>  issueErrors(tree, args)
4360-               case  _ =>  retyped
4361-           else  issueErrors(tree, args)
4362-         }
4344+               wtp.paramNames.lazyZip(args).collect: 
4345+                 case  (pname, arg) if  ! arg.tpe.isError ||  arg.tpe.isInstanceOf [AmbiguousImplicits ] => 
4346+                   untpd.NamedArg (pname, untpd.TypedSplice (arg))
4347+               .toList
4348+             val  usingDefaultArgs  = 
4349+               wtp.paramNames.zipWithIndex
4350+                 .exists((n, i) =>  ! namedArgs.exists(_.name ==  n) &&  ! findDefaultArgument(i).isEmpty)
4351+ 
4352+             if  ! usingDefaultArgs then 
4353+               issueErrors(tree, args, failureType)
4354+             else 
4355+               val  app  =  cpy.Apply (tree)(untpd.TypedSplice (tree), namedArgs)
4356+               //  old-style implicit needs to be marked using so that implicits are searched
4357+               val  needsUsing  =  wtp.isImplicitMethod ||  wtp.match 
4358+                 case  MethodType (ContextBoundParamName (_) ::  _) =>  sourceVersion.isAtLeast(`3.4`)
4359+                 case  _ =>  false 
4360+               if  needsUsing then  app.setApplyKind(ApplyKind .Using )
4361+               typr.println(i " try with default implicit args  $app" )
4362+               //  If the retyped tree still has an error type and is an `Apply`
4363+               //  node, we can report the errors for each argument nicely.
4364+               //  Otherwise, we don't report anything here.
4365+               typed(app, pt, locked) match 
4366+                 case  retyped @  Apply (tree, args) if  retyped.tpe.isError => 
4367+                   propagatedFailure(args) match 
4368+                   case  sft : SearchFailureType  =>  issueErrors(tree, args, sft)
4369+                   case  _ =>  issueErrors(tree, args, retyped.tpe)
4370+                 case  retyped =>  retyped
4371+           else  issueErrors(tree, args, failureType)
43634372        else 
43644373          inContext(origCtx): 
43654374            //  Reset context in case it was set to a supercall context before.
0 commit comments