@@ -23,7 +23,7 @@ import ProtoTypes.*
23
23
import Inferencing .*
24
24
import reporting .*
25
25
import Nullables .* , NullOpsDecorator .*
26
- import config .{Feature , SourceVersion }
26
+ import config .{Feature , MigrationVersion , SourceVersion }
27
27
28
28
import collection .mutable
29
29
import config .Printers .{overload , typr , unapp }
@@ -607,7 +607,7 @@ trait Applications extends Compatibility {
607
607
fail(TypeMismatch (methType.resultType, resultType, None ))
608
608
609
609
// match all arguments with corresponding formal parameters
610
- if success then matchArgs(orderedArgs, methType.paramInfos, 0 )
610
+ if success then matchArgs(orderedArgs, methType.paramInfos, n = 0 )
611
611
case _ =>
612
612
if (methType.isError) ok = false
613
613
else fail(em " $methString does not take parameters " )
@@ -765,13 +765,20 @@ trait Applications extends Compatibility {
765
765
}
766
766
else defaultArgument(normalizedFun, n, testOnly)
767
767
768
+ // a bug allowed empty parens to expand to implicit args, offer rewrite only on migration
769
+ def canSupplyImplicits = methodType.isImplicitMethod
770
+ && (applyKind == ApplyKind .Using || {
771
+ if args1.isEmpty then
772
+ fail(MissingImplicitParameterInEmptyArguments (methodType.paramNames(n), methString))
773
+ true
774
+ })
775
+ && ctx.mode.is(Mode .ImplicitsEnabled )
776
+
768
777
if ! defaultArg.isEmpty then
769
778
defaultArg.tpe.widen match
770
779
case _ : MethodOrPoly if testOnly => matchArgs(args1, formals1, n + 1 )
771
780
case _ => matchArgs(args1, addTyped(treeToArg(defaultArg)), n + 1 )
772
- else if (methodType.isContextualMethod || applyKind == ApplyKind .Using && methodType.isImplicitMethod)
773
- && ctx.mode.is(Mode .ImplicitsEnabled )
774
- then
781
+ else if methodType.isContextualMethod && ctx.mode.is(Mode .ImplicitsEnabled ) || canSupplyImplicits then
775
782
val implicitArg = implicitArgTree(formal, appPos.span)
776
783
matchArgs(args1, addTyped(treeToArg(implicitArg)), n + 1 )
777
784
else
@@ -1149,32 +1156,53 @@ trait Applications extends Compatibility {
1149
1156
}
1150
1157
}
1151
1158
1159
+ def tryWithUsing (fun1 : Tree , proto : FunProto )(using Context ): Option [Tree ] =
1160
+ tryEither(Option (simpleApply(fun1, proto.withApplyKind(ApplyKind .Using )))): (_, _) =>
1161
+ None
1162
+
1152
1163
/** If the applied function is an automatically inserted `apply`
1153
- * method and one of its arguments has a type mismatch , append
1154
- * a note to the error message that explains where the required
1155
- * type comes from. See #19680 and associated test case.
1164
+ * method and one of its arguments has a type mismatch , append
1165
+ * a note to the error message that explains where the required
1166
+ * type comes from. See #19680 and associated test case.
1156
1167
*/
1157
1168
def maybeAddInsertedApplyNote (failedState : TyperState , fun1 : Tree )(using Context ): Unit =
1158
1169
if fun1.symbol.name == nme.apply && fun1.span.isSynthetic then
1159
1170
fun1 match
1160
- case Select (qualifier, _) =>
1161
- def mapMessage (dia : Diagnostic ): Diagnostic =
1162
- dia match
1163
- case dia : Diagnostic .Error =>
1164
- dia.msg match
1165
- case msg : TypeMismatch =>
1166
- msg.inTree match
1167
- case Some (arg) if tree.args.exists(_.span == arg.span) =>
1168
- val noteText =
1169
- i """ The required type comes from a parameter of the automatically
1170
- |inserted `apply` method of ` ${qualifier.tpe}`. """ .stripMargin
1171
- Diagnostic .Error (msg.appendExplanation(" \n\n " + noteText), dia.pos)
1172
- case _ => dia
1173
- case msg => dia
1174
- case dia => dia
1175
- failedState.reporter.mapBufferedMessages(mapMessage)
1176
- case _ => ()
1177
- else ()
1171
+ case Select (qualifier, _) =>
1172
+ def mapMessage (dia : Diagnostic ): Diagnostic =
1173
+ dia match
1174
+ case dia : Diagnostic .Error =>
1175
+ dia.msg match
1176
+ case msg : TypeMismatch =>
1177
+ msg.inTree match
1178
+ case Some (arg) if tree.args.exists(_.span == arg.span) =>
1179
+ val noteText =
1180
+ i """ The required type comes from a parameter of the automatically
1181
+ |inserted `apply` method of ` ${qualifier.tpe}`. """ .stripMargin
1182
+ Diagnostic .Error (msg.appendExplanation(" \n\n " + noteText), dia.pos)
1183
+ case _ => dia
1184
+ case msg => dia
1185
+ case dia => dia
1186
+ failedState.reporter.mapBufferedMessages(mapMessage)
1187
+ case _ => ()
1188
+
1189
+ def maybePatchBadParensForImplicit (failedState : TyperState )(using Context ): Boolean =
1190
+ var retry = false
1191
+ failedState.reporter.mapBufferedMessages: dia =>
1192
+ dia match
1193
+ case err : Diagnostic .Error =>
1194
+ err.msg match
1195
+ case msg : MissingImplicitParameterInEmptyArguments =>
1196
+ val mv = MigrationVersion .ImplicitParamsWithoutUsing
1197
+ if mv.needsPatch then
1198
+ retry = true
1199
+ rewrites.Rewrites .patch(tree.span.withStart(tree.span.point), " " ) // f() -> f
1200
+ Diagnostic .Warning (err.msg, err.pos)
1201
+ else
1202
+ err
1203
+ case _ => err
1204
+ case dia => dia
1205
+ retry
1178
1206
1179
1207
val result = fun1.tpe match {
1180
1208
case err : ErrorType => cpy.Apply (tree)(fun1, proto.typedArgs()).withType(err)
@@ -1231,10 +1259,13 @@ trait Applications extends Compatibility {
1231
1259
errorTree(tree, em " argument to summonFrom must be a pattern matching closure " )
1232
1260
}
1233
1261
else
1234
- tryEither {
1235
- simpleApply(fun1, proto)
1236
- } {
1237
- (failedVal, failedState) =>
1262
+ tryEither(simpleApply(fun1, proto)): (failedVal, failedState) =>
1263
+ // a bug allowed empty parens to expand to implicit args, offer rewrite only on migration, then retry
1264
+ if proto.args.isEmpty && maybePatchBadParensForImplicit(failedState) then
1265
+ tryWithUsing(fun1, proto).getOrElse:
1266
+ failedState.commit()
1267
+ failedVal
1268
+ else
1238
1269
def fail =
1239
1270
maybeAddInsertedApplyNote(failedState, fun1)
1240
1271
failedState.commit()
@@ -1244,10 +1275,9 @@ trait Applications extends Compatibility {
1244
1275
// The reason we need to try both is that the decision whether to use tupled
1245
1276
// or not was already taken but might have to be revised when an implicit
1246
1277
// is inserted on the qualifier.
1247
- tryWithImplicitOnQualifier(fun1, originalProto).getOrElse(
1278
+ tryWithImplicitOnQualifier(fun1, originalProto).getOrElse:
1248
1279
if (proto eq originalProto) fail
1249
- else tryWithImplicitOnQualifier(fun1, proto).getOrElse(fail))
1250
- }
1280
+ else tryWithImplicitOnQualifier(fun1, proto).getOrElse(fail)
1251
1281
}
1252
1282
1253
1283
if result.tpe.isNothingType then
0 commit comments