@@ -29,19 +29,36 @@ using namespace swift;
29
29
// / Determine whether it makes sense to infer an attribute in the given
30
30
// / context.
31
31
static bool shouldInferAttributeInContext (const DeclContext *dc) {
32
- auto sourceFile = dc->getParentSourceFile ();
33
- if (!sourceFile)
34
- return false ;
32
+ if (auto *file = dyn_cast<FileUnit>(dc->getModuleScopeContext ())) {
33
+ switch (file->getKind ()) {
34
+ case FileUnitKind::Source:
35
+ // Check what kind of source file we have.
36
+ if (auto sourceFile = dc->getParentSourceFile ()) {
37
+ switch (sourceFile->Kind ) {
38
+ case SourceFileKind::Interface:
39
+ // Interfaces have explicitly called-out ConcurrentValue conformances.
40
+ return false ;
35
41
36
- switch (sourceFile->Kind ) {
37
- case SourceFileKind::Interface:
38
- case SourceFileKind::SIL:
39
- return false ;
42
+ case SourceFileKind::Library:
43
+ case SourceFileKind::Main:
44
+ case SourceFileKind::SIL:
45
+ return true ;
46
+ }
47
+ }
48
+ break ;
40
49
41
- case SourceFileKind::Library:
42
- case SourceFileKind::Main:
43
- return true ;
50
+ case FileUnitKind::Builtin:
51
+ case FileUnitKind::SerializedAST:
52
+ case FileUnitKind::Synthesized:
53
+ return false ;
54
+
55
+ case FileUnitKind::ClangModule:
56
+ case FileUnitKind::DWARFModule:
57
+ return true ;
58
+ }
44
59
}
60
+
61
+ return false ;
45
62
}
46
63
47
64
// / Check whether the @asyncHandler attribute can be applied to the given
@@ -458,15 +475,6 @@ GlobalActorAttributeRequest::evaluate(
458
475
.highlight (globalActorAttr->getRangeWithAt ());
459
476
return None;
460
477
}
461
-
462
- // Global actors don't make sense on a stored property of a struct.
463
- if (var->hasStorage () && var->getDeclContext ()->getSelfStructDecl () &&
464
- var->isInstanceMember ()) {
465
- var->diagnose (diag::global_actor_on_struct_property, var->getName ())
466
- .highlight (globalActorAttr->getRangeWithAt ());
467
- return None;
468
- }
469
-
470
478
}
471
479
} else if (isa<ExtensionDecl>(decl)) {
472
480
// Extensions are okay.
@@ -2344,7 +2352,8 @@ ActorIsolation ActorIsolationRequest::evaluate(
2344
2352
}
2345
2353
2346
2354
// Function used when returning an inferred isolation.
2347
- auto inferredIsolation = [&](ActorIsolation inferred) {
2355
+ auto inferredIsolation = [&](
2356
+ ActorIsolation inferred, bool propagateUnsafe = false ) {
2348
2357
// Add an implicit attribute to capture the actor isolation that was
2349
2358
// inferred, so that (e.g.) it will be printed and serialized.
2350
2359
ASTContext &ctx = value->getASTContext ();
@@ -2357,13 +2366,19 @@ ActorIsolation ActorIsolationRequest::evaluate(
2357
2366
break ;
2358
2367
2359
2368
case ActorIsolation::GlobalActorUnsafe:
2360
- // Don't infer unsafe global actor isolation.
2361
- return ActorIsolation::forUnspecified ();
2369
+ if (!propagateUnsafe && !value->hasClangNode ()) {
2370
+ // Don't infer unsafe global actor isolation.
2371
+ return ActorIsolation::forUnspecified ();
2372
+ }
2373
+
2374
+ LLVM_FALLTHROUGH;
2362
2375
2363
2376
case ActorIsolation::GlobalActor: {
2364
2377
auto typeExpr = TypeExpr::createImplicit (inferred.getGlobalActor (), ctx);
2365
2378
auto attr = CustomAttr::create (
2366
2379
ctx, SourceLoc (), typeExpr, /* implicit=*/ true );
2380
+ if (inferred == ActorIsolation::GlobalActorUnsafe)
2381
+ attr->setArgIsUnsafe (true );
2367
2382
value->getAttrs ().add (attr);
2368
2383
break ;
2369
2384
}
@@ -2400,6 +2415,46 @@ ActorIsolation ActorIsolationRequest::evaluate(
2400
2415
return getActorIsolation (accessor->getStorage ());
2401
2416
}
2402
2417
2418
+ if (auto var = dyn_cast<VarDecl>(value)) {
2419
+ // If this is a variable with a property wrapper, infer from the property
2420
+ // wrapper's wrappedValue.
2421
+ if (auto wrapperInfo = var->getAttachedPropertyWrapperTypeInfo (0 )) {
2422
+ if (auto wrappedValue = wrapperInfo.valueVar ) {
2423
+ if (auto isolation = getActorIsolation (wrappedValue))
2424
+ return inferredIsolation (isolation, /* propagateUnsafe=*/ true );
2425
+ }
2426
+ }
2427
+
2428
+ // If this is the backing storage for a property wrapper, infer from the
2429
+ // type of the outermost property wrapper.
2430
+ if (auto originalVar = var->getOriginalWrappedProperty (
2431
+ PropertyWrapperSynthesizedPropertyKind::Backing)) {
2432
+ if (auto backingType =
2433
+ originalVar->getPropertyWrapperBackingPropertyType ()) {
2434
+ if (auto backingNominal = backingType->getAnyNominal ()) {
2435
+ if (!isa<ClassDecl>(backingNominal) ||
2436
+ !cast<ClassDecl>(backingNominal)->isActor ()) {
2437
+ if (auto isolation = getActorIsolation (backingNominal))
2438
+ return inferredIsolation (isolation, /* propagateUnsafe=*/ true );
2439
+ }
2440
+ }
2441
+ }
2442
+ }
2443
+
2444
+ // If this is the projected property for a property wrapper, infer from
2445
+ // the property wrapper's projectedValue.
2446
+ if (auto originalVar = var->getOriginalWrappedProperty (
2447
+ PropertyWrapperSynthesizedPropertyKind::Projection)) {
2448
+ if (auto wrapperInfo =
2449
+ originalVar->getAttachedPropertyWrapperTypeInfo (0 )) {
2450
+ if (auto projectedValue = wrapperInfo.projectedValueVar ) {
2451
+ if (auto isolation = getActorIsolation (projectedValue))
2452
+ return inferredIsolation (isolation, /* propagateUnsafe=*/ true );
2453
+ }
2454
+ }
2455
+ }
2456
+ }
2457
+
2403
2458
if (shouldInferAttributeInContext (value->getDeclContext ())) {
2404
2459
// If the declaration witnesses a protocol requirement that is isolated,
2405
2460
// use that.
@@ -2577,6 +2632,13 @@ static bool shouldDiagnoseExistingDataRaces(const DeclContext *dc) {
2577
2632
// features.
2578
2633
if (func->getAttrs ().hasAttribute <AsyncHandlerAttr>())
2579
2634
return true ;
2635
+
2636
+ // If we're in an accessor declaration, also check the storage
2637
+ // declaration.
2638
+ if (auto accessor = dyn_cast<AccessorDecl>(decl)) {
2639
+ if (getIsolationFromAttributes (accessor->getStorage ()))
2640
+ return true ;
2641
+ }
2580
2642
}
2581
2643
}
2582
2644
0 commit comments