@@ -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 }
@@ -602,7 +602,7 @@ trait Applications extends Compatibility {
602
602
fail(TypeMismatch (methType.resultType, resultType, None ))
603
603
604
604
// 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 )
606
606
case _ =>
607
607
if (methType.isError) ok = false
608
608
else fail(em " $methString does not take parameters " )
@@ -757,13 +757,20 @@ trait Applications extends Compatibility {
757
757
}
758
758
else defaultArgument(normalizedFun, n, testOnly)
759
759
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
+
760
769
if ! defaultArg.isEmpty then
761
770
defaultArg.tpe.widen match
762
771
case _ : MethodOrPoly if testOnly => matchArgs(args1, formals1, n + 1 )
763
772
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
767
774
val implicitArg = implicitArgTree(formal, appPos.span)
768
775
matchArgs(args1, addTyped(treeToArg(implicitArg)), n + 1 )
769
776
else
@@ -1141,32 +1148,53 @@ trait Applications extends Compatibility {
1141
1148
}
1142
1149
}
1143
1150
1151
+ def tryWithUsing (fun1 : Tree , proto : FunProto )(using Context ): Option [Tree ] =
1152
+ tryEither(Option (simpleApply(fun1, proto.withApplyKind(ApplyKind .Using )))): (_, _) =>
1153
+ None
1154
+
1144
1155
/** 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.
1148
1159
*/
1149
1160
def maybeAddInsertedApplyNote (failedState : TyperState , fun1 : Tree )(using Context ): Unit =
1150
1161
if fun1.symbol.name == nme.apply && fun1.span.isSynthetic then
1151
1162
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
1170
1198
1171
1199
val result = fun1.tpe match {
1172
1200
case err : ErrorType => cpy.Apply (tree)(fun1, proto.typedArgs()).withType(err)
@@ -1223,10 +1251,13 @@ trait Applications extends Compatibility {
1223
1251
errorTree(tree, em " argument to summonFrom must be a pattern matching closure " )
1224
1252
}
1225
1253
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
1230
1261
def fail =
1231
1262
maybeAddInsertedApplyNote(failedState, fun1)
1232
1263
failedState.commit()
@@ -1236,10 +1267,9 @@ trait Applications extends Compatibility {
1236
1267
// The reason we need to try both is that the decision whether to use tupled
1237
1268
// or not was already taken but might have to be revised when an implicit
1238
1269
// is inserted on the qualifier.
1239
- tryWithImplicitOnQualifier(fun1, originalProto).getOrElse(
1270
+ tryWithImplicitOnQualifier(fun1, originalProto).getOrElse:
1240
1271
if (proto eq originalProto) fail
1241
- else tryWithImplicitOnQualifier(fun1, proto).getOrElse(fail))
1242
- }
1272
+ else tryWithImplicitOnQualifier(fun1, proto).getOrElse(fail)
1243
1273
}
1244
1274
1245
1275
if result.tpe.isNothingType then
0 commit comments