@@ -372,6 +372,15 @@ GlobalActorAttributeRequest::evaluate(
372
372
if (decl->getDeclContext ()->getParentSourceFile () == nullptr )
373
373
return result;
374
374
375
+ auto isInstancePropertyOfStruct = [](VarDecl *var) {
376
+ if (var->isStatic ())
377
+ return false ;
378
+
379
+ auto *nominal = var->getDeclContext ()->getSelfNominalTypeDecl ();
380
+ return isa_and_nonnull<StructDecl>(nominal) &&
381
+ !isWrappedValueOfPropWrapper (var);
382
+ };
383
+
375
384
auto globalActorAttr = result->first ;
376
385
if (auto nominal = dyn_cast<NominalTypeDecl>(decl)) {
377
386
// Nominal types are okay...
@@ -405,25 +414,53 @@ GlobalActorAttributeRequest::evaluate(
405
414
}
406
415
407
416
// ... and not if it's the instance storage of a struct
408
- if (!var->isStatic () && var->isOrdinaryStoredProperty ()) {
409
- if (auto *nominal = var->getDeclContext ()->getSelfNominalTypeDecl ()) {
410
- if (isa<StructDecl>(nominal) && !isWrappedValueOfPropWrapper (var)) {
411
-
412
- var->diagnose (diag::global_actor_on_storage_of_value_type,
413
- var->getName ())
414
- .highlight (globalActorAttr->getRangeWithAt ())
415
- .warnUntilSwiftVersion (6 );
416
-
417
- // In Swift 6, once the diag above is an error, it is disallowed.
418
- if (var->getASTContext ().isSwiftVersionAtLeast (6 ))
419
- return llvm::None;
420
- }
421
- }
417
+ if (var->isOrdinaryStoredProperty () && isInstancePropertyOfStruct (var)) {
418
+ var->diagnose (diag::global_actor_on_storage_of_value_type,
419
+ var->getName ())
420
+ .highlight (globalActorAttr->getRangeWithAt ())
421
+ .warnUntilSwiftVersion (6 );
422
+
423
+ // In Swift 6, once the diag above is an error, it is disallowed.
424
+ if (var->getASTContext ().isSwiftVersionAtLeast (6 ))
425
+ return llvm::None;
422
426
}
423
427
}
424
428
} else if (isa<ExtensionDecl>(decl)) {
425
429
// Extensions are okay.
426
430
} else if (isa<ConstructorDecl>(decl) || isa<FuncDecl>(decl)) {
431
+ // None of the accessors/addressors besides a getter are allowed
432
+ // to have a global actor attribute.
433
+ if (auto *accessor = dyn_cast<AccessorDecl>(decl)) {
434
+ if (!accessor->isGetter ()) {
435
+ decl->diagnose (diag::global_actor_disallowed,
436
+ decl->getDescriptiveKind ())
437
+ .fixItRemove (globalActorAttr->getRangeWithAt ());
438
+
439
+ auto *storage = accessor->getStorage ();
440
+ // Let's suggest to move the attribute to the storage if
441
+ // this is an accessor/addressor of a property of subscript.
442
+ if (storage->getDeclContext ()->isTypeContext ()) {
443
+ // If enclosing declaration has a global actor,
444
+ // skip the suggestion.
445
+ if (storage->getGlobalActorAttr ())
446
+ return llvm::None;
447
+
448
+ // Global actor attribute cannot be applied to
449
+ // an instance property of a struct.
450
+ if (auto *var = dyn_cast<VarDecl>(storage)) {
451
+ if (isInstancePropertyOfStruct (var))
452
+ return llvm::None;
453
+ }
454
+
455
+ decl->diagnose (diag::move_global_actor_attr_to_storage_decl, storage)
456
+ .fixItInsert (
457
+ storage->getAttributeInsertionLoc (/* forModifier=*/ false ),
458
+ llvm::Twine (" @" , result->second ->getNameStr ()).str ());
459
+ }
460
+
461
+ return llvm::None;
462
+ }
463
+ }
427
464
// Functions are okay.
428
465
} else {
429
466
// Everything else is disallowed.
0 commit comments