27
27
#include " swift/AST/TypeVisitor.h"
28
28
#include " swift/AST/ExistentialLayout.h"
29
29
#include " swift/Basic/Defer.h"
30
+ #include " swift/AST/ASTPrinter.h"
30
31
31
32
using namespace swift ;
32
33
@@ -222,6 +223,69 @@ static bool checkAdHocRequirementAccessControl(
222
223
return true ;
223
224
}
224
225
226
+ static bool diagnoseMissingAdHocProtocolRequirement (ASTContext &C, Identifier identifier, NominalTypeDecl *decl) {
227
+ assert (decl);
228
+ auto FixitLocation = decl->getBraces ().Start ;
229
+
230
+ // Prepare the indent (same as `printRequirementStub`)
231
+ StringRef ExtraIndent;
232
+ StringRef CurrentIndent =
233
+ Lexer::getIndentationForLine (C.SourceMgr , decl->getStartLoc (), &ExtraIndent);
234
+
235
+ llvm::SmallString<128 > Text;
236
+ llvm::raw_svector_ostream OS (Text);
237
+ ExtraIndentStreamPrinter Printer (OS, CurrentIndent);
238
+
239
+ Printer << (decl->getFormalAccess () == AccessLevel::Public ? " public " : " " );
240
+
241
+ if (identifier == C.Id_remoteCall ) {
242
+ Printer << " func remoteCall<Act, Err, Res>("
243
+ " on actor: Act, "
244
+ " target: RemoteCallTarget, "
245
+ " invocation: inout InvocationEncoder, "
246
+ " throwing: Err.Type, "
247
+ " returning: Res.Type) "
248
+ " async throws -> Res "
249
+ " where Act: DistributedActor, "
250
+ " Act.ID == ActorID, "
251
+ " Err: Error, "
252
+ " Res: SerializationRequirement" ;
253
+ } else if (identifier == C.Id_remoteCallVoid ) {
254
+ Printer << " func remoteCallVoid<Act, Err>("
255
+ " on actor: Act, "
256
+ " target: RemoteCallTarget, "
257
+ " invocation: inout InvocationEncoder, "
258
+ " throwing: Err.Type"
259
+ " ) async throws "
260
+ " where Act: DistributedActor, "
261
+ " Act.ID == ActorID, "
262
+ " Err: Error" ;
263
+ } else if (identifier == C.Id_recordArgument ) {
264
+ Printer << " mutating func recordArgument<Value: SerializationRequirement>(_ argument: RemoteCallArgument<Value>) throws" ;
265
+ } else if (identifier == C.Id_recordReturnType ) {
266
+ Printer << " mutating func recordReturnType<Res: SerializationRequirement>(_ resultType: Res.Type) throws" ;
267
+ } else if (identifier == C.Id_decodeNextArgument ) {
268
+ Printer << " mutating func decodeNextArgument<Argument: SerializationRequirement>() throws -> Argument" ;
269
+ } else if (identifier == C.Id_onReturn ) {
270
+ Printer << " func onReturn<Success: SerializationRequirement>(value: Success) async throws" ;
271
+ } else {
272
+ llvm_unreachable (" Unknown identifier for diagnosing ad-hoc missing requirement." );
273
+ }
274
+
275
+ // / Print the "{ <#code#> }" placeholder body
276
+ Printer << " {\n " ;
277
+ Printer << ExtraIndent << getCodePlaceholder ();
278
+ Printer << " \n }\n " ;
279
+
280
+ decl->diagnose (
281
+ diag::distributed_actor_system_conformance_missing_adhoc_requirement,
282
+ decl, identifier);
283
+ decl->diagnose (diag::missing_witnesses_general)
284
+ .fixItInsertAfter (FixitLocation, Text.str ());
285
+
286
+ return true ;
287
+ }
288
+
225
289
bool swift::checkDistributedActorSystemAdHocProtocolRequirements (
226
290
ASTContext &C,
227
291
ProtocolDecl *Proto,
@@ -238,53 +302,21 @@ bool swift::checkDistributedActorSystemAdHocProtocolRequirements(
238
302
auto remoteCallDecl =
239
303
C.getRemoteCallOnDistributedActorSystem (decl, /* isVoidReturn=*/ false );
240
304
if (!remoteCallDecl && diagnose) {
241
- auto identifier = C.Id_remoteCall ;
242
- decl->diagnose (
243
- diag::distributed_actor_system_conformance_missing_adhoc_requirement,
244
- decl, identifier);
245
- decl->diagnose (
246
- diag::note_distributed_actor_system_conformance_missing_adhoc_requirement,
247
- Proto->getName (), identifier,
248
- " func remoteCall<Act, Err, Res>(\n "
249
- " on actor: Act,\n "
250
- " target: RemoteCallTarget,\n "
251
- " invocation: inout InvocationEncoder,\n "
252
- " throwing: Err.Type,\n "
253
- " returning: Res.Type\n "
254
- " ) async throws -> Res\n "
255
- " where Act: DistributedActor,\n "
256
- " Act.ID == ActorID,\n "
257
- " Err: Error,\n "
258
- " Res: SerializationRequirement\n " );
259
- anyMissingAdHocRequirements = true ;
305
+ anyMissingAdHocRequirements = diagnoseMissingAdHocProtocolRequirement (C, C.Id_remoteCall , decl);
260
306
}
261
- if (checkAdHocRequirementAccessControl (decl, Proto, remoteCallDecl))
307
+ if (checkAdHocRequirementAccessControl (decl, Proto, remoteCallDecl)) {
262
308
anyMissingAdHocRequirements = true ;
309
+ }
263
310
264
311
// - remoteCallVoid
265
312
auto remoteCallVoidDecl =
266
313
C.getRemoteCallOnDistributedActorSystem (decl, /* isVoidReturn=*/ true );
267
314
if (!remoteCallVoidDecl && diagnose) {
268
- auto identifier = C.Id_remoteCallVoid ;
269
- decl->diagnose (
270
- diag::distributed_actor_system_conformance_missing_adhoc_requirement,
271
- decl, identifier);
272
- decl->diagnose (
273
- diag::note_distributed_actor_system_conformance_missing_adhoc_requirement,
274
- Proto->getName (), identifier,
275
- " func remoteCallVoid<Act, Err>(\n "
276
- " on actor: Act,\n "
277
- " target: RemoteCallTarget,\n "
278
- " invocation: inout InvocationEncoder,\n "
279
- " throwing: Err.Type\n "
280
- " ) async throws\n "
281
- " where Act: DistributedActor,\n "
282
- " Act.ID == ActorID,\n "
283
- " Err: Error\n " );
284
- anyMissingAdHocRequirements = true ;
315
+ anyMissingAdHocRequirements = diagnoseMissingAdHocProtocolRequirement (C, C.Id_remoteCallVoid , decl);
285
316
}
286
- if (checkAdHocRequirementAccessControl (decl, Proto, remoteCallVoidDecl))
317
+ if (checkAdHocRequirementAccessControl (decl, Proto, remoteCallVoidDecl)) {
287
318
anyMissingAdHocRequirements = true ;
319
+ }
288
320
289
321
return anyMissingAdHocRequirements;
290
322
}
@@ -295,32 +327,20 @@ bool swift::checkDistributedActorSystemAdHocProtocolRequirements(
295
327
// - recordArgument
296
328
auto recordArgumentDecl = C.getRecordArgumentOnDistributedInvocationEncoder (decl);
297
329
if (!recordArgumentDecl) {
298
- auto identifier = C.Id_recordArgument ;
299
- decl->diagnose (
300
- diag::distributed_actor_system_conformance_missing_adhoc_requirement,
301
- decl, identifier);
302
- decl->diagnose (diag::note_distributed_actor_system_conformance_missing_adhoc_requirement,
303
- Proto->getName (), identifier,
304
- " mutating func recordArgument<Value: SerializationRequirement>(_ argument: RemoteCallArgument<Value>) throws\n " );
305
- anyMissingAdHocRequirements = true ;
330
+ anyMissingAdHocRequirements = diagnoseMissingAdHocProtocolRequirement (C, C.Id_recordArgument , decl);
306
331
}
307
- if (checkAdHocRequirementAccessControl (decl, Proto, recordArgumentDecl))
332
+ if (checkAdHocRequirementAccessControl (decl, Proto, recordArgumentDecl)) {
308
333
anyMissingAdHocRequirements = true ;
334
+ }
309
335
310
336
// - recordReturnType
311
337
auto recordReturnTypeDecl = C.getRecordReturnTypeOnDistributedInvocationEncoder (decl);
312
338
if (!recordReturnTypeDecl) {
313
- auto identifier = C.Id_recordReturnType ;
314
- decl->diagnose (
315
- diag::distributed_actor_system_conformance_missing_adhoc_requirement,
316
- decl, identifier);
317
- decl->diagnose (diag::note_distributed_actor_system_conformance_missing_adhoc_requirement,
318
- Proto->getName (), identifier,
319
- " mutating func recordReturnType<Res: SerializationRequirement>(_ resultType: Res.Type) throws\n " );
320
- anyMissingAdHocRequirements = true ;
339
+ anyMissingAdHocRequirements = diagnoseMissingAdHocProtocolRequirement (C, C.Id_recordReturnType , decl);
321
340
}
322
- if (checkAdHocRequirementAccessControl (decl, Proto, recordReturnTypeDecl))
341
+ if (checkAdHocRequirementAccessControl (decl, Proto, recordReturnTypeDecl)) {
323
342
anyMissingAdHocRequirements = true ;
343
+ }
324
344
325
345
return anyMissingAdHocRequirements;
326
346
}
@@ -331,17 +351,11 @@ bool swift::checkDistributedActorSystemAdHocProtocolRequirements(
331
351
// - decodeNextArgument
332
352
auto decodeNextArgumentDecl = C.getDecodeNextArgumentOnDistributedInvocationDecoder (decl);
333
353
if (!decodeNextArgumentDecl) {
334
- auto identifier = C.Id_decodeNextArgument ;
335
- decl->diagnose (
336
- diag::distributed_actor_system_conformance_missing_adhoc_requirement,
337
- decl, identifier);
338
- decl->diagnose (diag::note_distributed_actor_system_conformance_missing_adhoc_requirement,
339
- Proto->getName (), identifier,
340
- " mutating func decodeNextArgument<Argument: SerializationRequirement>() throws -> Argument\n " );
341
- anyMissingAdHocRequirements = true ;
354
+ anyMissingAdHocRequirements = diagnoseMissingAdHocProtocolRequirement (C, C.Id_decodeNextArgument , decl);
342
355
}
343
- if (checkAdHocRequirementAccessControl (decl, Proto, decodeNextArgumentDecl))
356
+ if (checkAdHocRequirementAccessControl (decl, Proto, decodeNextArgumentDecl)) {
344
357
anyMissingAdHocRequirements = true ;
358
+ }
345
359
346
360
return anyMissingAdHocRequirements;
347
361
}
@@ -352,19 +366,11 @@ bool swift::checkDistributedActorSystemAdHocProtocolRequirements(
352
366
// - onReturn
353
367
auto onReturnDecl = C.getOnReturnOnDistributedTargetInvocationResultHandler (decl);
354
368
if (!onReturnDecl) {
355
- auto identifier = C.Id_onReturn ;
356
- decl->diagnose (
357
- diag::distributed_actor_system_conformance_missing_adhoc_requirement,
358
- decl, identifier);
359
- decl->diagnose (
360
- diag::note_distributed_actor_system_conformance_missing_adhoc_requirement,
361
- Proto->getName (), identifier,
362
- " func onReturn<Success: SerializationRequirement>(value: "
363
- " Success) async throws\n " );
364
- anyMissingAdHocRequirements = true ;
369
+ anyMissingAdHocRequirements = diagnoseMissingAdHocProtocolRequirement (C, C.Id_onReturn , decl);
365
370
}
366
- if (checkAdHocRequirementAccessControl (decl, Proto, onReturnDecl))
371
+ if (checkAdHocRequirementAccessControl (decl, Proto, onReturnDecl)) {
367
372
anyMissingAdHocRequirements = true ;
373
+ }
368
374
369
375
return anyMissingAdHocRequirements;
370
376
}
0 commit comments