@@ -23,7 +23,7 @@ import ProtoTypes.*
2323import Inferencing .*
2424import reporting .*
2525import Nullables .* , NullOpsDecorator .*
26- import config .{Feature , SourceVersion }
26+ import config .{Feature , MigrationVersion , SourceVersion }
2727
2828import collection .mutable
2929import config .Printers .{overload , typr , unapp }
@@ -602,7 +602,7 @@ trait Applications extends Compatibility {
602602 fail(TypeMismatch (methType.resultType, resultType, None ))
603603
604604 // match all arguments with corresponding formal parameters
605- if success then matchArgs(orderedArgs, methType.paramInfos, 0 )
605+ if success then matchArgs(orderedArgs, methType.paramInfos, n = 0 )
606606 case _ =>
607607 if (methType.isError) ok = false
608608 else fail(em " $methString does not take parameters " )
@@ -757,13 +757,20 @@ trait Applications extends Compatibility {
757757 }
758758 else defaultArgument(normalizedFun, n, testOnly)
759759
760+ // a bug allowed empty parens to expand to implicit args, offer rewrite only on migration
761+ def canSupplyImplicits = methodType.isImplicitMethod
762+ && (applyKind == ApplyKind .Using || {
763+ if args1.isEmpty then
764+ fail(MissingImplicitParameterInEmptyArguments (methodType.paramNames(n), methString))
765+ true
766+ })
767+ && ctx.mode.is(Mode .ImplicitsEnabled )
768+
760769 if ! defaultArg.isEmpty then
761770 defaultArg.tpe.widen match
762771 case _ : MethodOrPoly if testOnly => matchArgs(args1, formals1, n + 1 )
763772 case _ => matchArgs(args1, addTyped(treeToArg(defaultArg)), n + 1 )
764- else if (methodType.isContextualMethod || applyKind == ApplyKind .Using && methodType.isImplicitMethod)
765- && ctx.mode.is(Mode .ImplicitsEnabled )
766- then
773+ else if methodType.isContextualMethod && ctx.mode.is(Mode .ImplicitsEnabled ) || canSupplyImplicits then
767774 val implicitArg = implicitArgTree(formal, appPos.span)
768775 matchArgs(args1, addTyped(treeToArg(implicitArg)), n + 1 )
769776 else
@@ -1141,32 +1148,53 @@ trait Applications extends Compatibility {
11411148 }
11421149 }
11431150
1151+ def tryWithUsing (fun1 : Tree , proto : FunProto )(using Context ): Option [Tree ] =
1152+ tryEither(Option (simpleApply(fun1, proto.withApplyKind(ApplyKind .Using )))): (_, _) =>
1153+ None
1154+
11441155 /** If the applied function is an automatically inserted `apply`
1145- * method and one of its arguments has a type mismatch , append
1146- * a note to the error message that explains where the required
1147- * type comes from. See #19680 and associated test case.
1156+ * method and one of its arguments has a type mismatch , append
1157+ * a note to the error message that explains where the required
1158+ * type comes from. See #19680 and associated test case.
11481159 */
11491160 def maybeAddInsertedApplyNote (failedState : TyperState , fun1 : Tree )(using Context ): Unit =
11501161 if fun1.symbol.name == nme.apply && fun1.span.isSynthetic then
11511162 fun1 match
1152- case Select (qualifier, _) =>
1153- def mapMessage (dia : Diagnostic ): Diagnostic =
1154- dia match
1155- case dia : Diagnostic .Error =>
1156- dia.msg match
1157- case msg : TypeMismatch =>
1158- msg.inTree match
1159- case Some (arg) if tree.args.exists(_.span == arg.span) =>
1160- val noteText =
1161- i """ The required type comes from a parameter of the automatically
1162- |inserted `apply` method of ` ${qualifier.tpe}`. """ .stripMargin
1163- Diagnostic .Error (msg.appendExplanation(" \n\n " + noteText), dia.pos)
1164- case _ => dia
1165- case msg => dia
1166- case dia => dia
1167- failedState.reporter.mapBufferedMessages(mapMessage)
1168- case _ => ()
1169- else ()
1163+ case Select (qualifier, _) =>
1164+ def mapMessage (dia : Diagnostic ): Diagnostic =
1165+ dia match
1166+ case dia : Diagnostic .Error =>
1167+ dia.msg match
1168+ case msg : TypeMismatch =>
1169+ msg.inTree match
1170+ case Some (arg) if tree.args.exists(_.span == arg.span) =>
1171+ val noteText =
1172+ i """ The required type comes from a parameter of the automatically
1173+ |inserted `apply` method of ` ${qualifier.tpe}`. """ .stripMargin
1174+ Diagnostic .Error (msg.appendExplanation(" \n\n " + noteText), dia.pos)
1175+ case _ => dia
1176+ case msg => dia
1177+ case dia => dia
1178+ failedState.reporter.mapBufferedMessages(mapMessage)
1179+ case _ => ()
1180+
1181+ def maybePatchBadParensForImplicit (failedState : TyperState )(using Context ): Boolean =
1182+ var retry = false
1183+ failedState.reporter.mapBufferedMessages: dia =>
1184+ dia match
1185+ case err : Diagnostic .Error =>
1186+ err.msg match
1187+ case msg : MissingImplicitParameterInEmptyArguments =>
1188+ val mv = MigrationVersion .ImplicitParamsWithoutUsing
1189+ if mv.needsPatch then
1190+ retry = true
1191+ rewrites.Rewrites .patch(tree.span.withStart(tree.span.point), " " ) // f() -> f
1192+ Diagnostic .Warning (err.msg, err.pos)
1193+ else
1194+ err
1195+ case _ => err
1196+ case dia => dia
1197+ retry
11701198
11711199 val result = fun1.tpe match {
11721200 case err : ErrorType => cpy.Apply (tree)(fun1, proto.typedArgs()).withType(err)
@@ -1223,10 +1251,13 @@ trait Applications extends Compatibility {
12231251 errorTree(tree, em " argument to summonFrom must be a pattern matching closure " )
12241252 }
12251253 else
1226- tryEither {
1227- simpleApply(fun1, proto)
1228- } {
1229- (failedVal, failedState) =>
1254+ tryEither(simpleApply(fun1, proto)): (failedVal, failedState) =>
1255+ // a bug allowed empty parens to expand to implicit args, offer rewrite only on migration, then retry
1256+ if proto.args.isEmpty && maybePatchBadParensForImplicit(failedState) then
1257+ tryWithUsing(fun1, proto).getOrElse:
1258+ failedState.commit()
1259+ failedVal
1260+ else
12301261 def fail =
12311262 maybeAddInsertedApplyNote(failedState, fun1)
12321263 failedState.commit()
@@ -1236,10 +1267,9 @@ trait Applications extends Compatibility {
12361267 // The reason we need to try both is that the decision whether to use tupled
12371268 // or not was already taken but might have to be revised when an implicit
12381269 // is inserted on the qualifier.
1239- tryWithImplicitOnQualifier(fun1, originalProto).getOrElse(
1270+ tryWithImplicitOnQualifier(fun1, originalProto).getOrElse:
12401271 if (proto eq originalProto) fail
1241- else tryWithImplicitOnQualifier(fun1, proto).getOrElse(fail))
1242- }
1272+ else tryWithImplicitOnQualifier(fun1, proto).getOrElse(fail)
12431273 }
12441274
12451275 if result.tpe.isNothingType then
0 commit comments