mirror of
https://github.com/apple/swift.git
synced 2026-06-20 15:42:51 +02:00
[SILGen] Respect stored property's explicit global actor isolation in its initializer
Previously, when generating SIL for a stored property initializer, we would
use the enclosing context's isolation rather than the property's own explicit
isolation. For example:
@MainActor
struct S {
@CustomActor var x = NS() // initializer was incorrectly MainActor-isolated
}
Now the initializer correctly uses the property's explicit @CustomActor isolation
instead of inheriting @MainActor from the struct.
This is implemented by checking for an explicit global actor isolation on the
VarDecl in SILDeclRef::getActorIsolation() before falling back to
getActorIsolationOfContext().
This commit is contained in:
@@ -2067,5 +2067,13 @@ ActorIsolation SILDeclRef::getActorIsolation() const {
|
||||
return param->getInitializerIsolation();
|
||||
}
|
||||
|
||||
// If we have a stored property initializer for a VarDecl with an explicit
|
||||
// isolation, match that explicit isolation.
|
||||
if (isStoredPropertyInitializer()) {
|
||||
if (auto isolation = swift::getActorIsolation(cast<VarDecl>(getDecl()));
|
||||
isolation && isolation.isGlobalActor())
|
||||
return isolation;
|
||||
}
|
||||
|
||||
return getActorIsolationOfContext(getInnermostDeclContext());
|
||||
}
|
||||
|
||||
@@ -11,6 +11,15 @@
|
||||
|
||||
func useValueAsync<T>(_ t: T) async {}
|
||||
|
||||
actor CustomActorInstance {}
|
||||
|
||||
@globalActor
|
||||
struct CustomActor {
|
||||
static let shared = CustomActorInstance()
|
||||
}
|
||||
|
||||
class NonSendableKlass {}
|
||||
|
||||
/////////////////
|
||||
// MARK: Tests //
|
||||
/////////////////
|
||||
@@ -32,3 +41,101 @@ func useValueAsync<T>(_ t: T) async {}
|
||||
await useValueAsync(erased) // expected-error {{sending 'erased' risks causing data races}}
|
||||
// expected-note @-1 {{sending main actor-isolated 'erased' to nonisolated global function 'useValueAsync' risks causing data races between nonisolated and main actor-isolated uses}}
|
||||
}
|
||||
|
||||
@MainActor
|
||||
struct MainActorStruct {
|
||||
// CHECK: variable initialization expression of MainActorStruct.mainActorField
|
||||
// CHECK-NEXT: Isolation: global_actor. type: MainActor
|
||||
// CHECK: MainActorStruct.mainActorField.getter
|
||||
// CHECK-NEXT: Isolation: global_actor. type: MainActor
|
||||
// CHECK: MainActorStruct.mainActorField.setter
|
||||
// CHECK-NEXT: Isolation: global_actor. type: MainActor
|
||||
var mainActorField = NonSendableKlass()
|
||||
|
||||
// CHECK: variable initialization expression of MainActorStruct.customActorField
|
||||
// CHECK-NEXT: Isolation: global_actor. type: CustomActor
|
||||
// CHECK: MainActorStruct.customActorField.getter
|
||||
// CHECK-NEXT: Isolation: global_actor. type: CustomActor
|
||||
// CHECK: MainActorStruct.customActorField.setter
|
||||
// CHECK-NEXT: Isolation: global_actor. type: CustomActor
|
||||
@CustomActor var customActorField = NonSendableKlass()
|
||||
|
||||
nonisolated init() {}
|
||||
}
|
||||
|
||||
struct NonisolatedStruct {
|
||||
// CHECK: variable initialization expression of NonisolatedStruct.nonisolatedField
|
||||
// CHECK-NEXT: Isolation: unspecified
|
||||
// CHECK: NonisolatedStruct.nonisolatedField.getter
|
||||
// CHECK-NEXT: Isolation: unspecified
|
||||
// CHECK: NonisolatedStruct.nonisolatedField.setter
|
||||
// CHECK-NEXT: Isolation: unspecified
|
||||
var nonisolatedField = NonSendableKlass()
|
||||
|
||||
// CHECK: variable initialization expression of NonisolatedStruct.mainActorField
|
||||
// CHECK-NEXT: Isolation: global_actor. type: MainActor
|
||||
// CHECK: NonisolatedStruct.mainActorField.getter
|
||||
// CHECK-NEXT: Isolation: global_actor. type: MainActor
|
||||
// CHECK: NonisolatedStruct.mainActorField.setter
|
||||
// CHECK-NEXT: Isolation: global_actor. type: MainActor
|
||||
@MainActor var mainActorField = NonSendableKlass()
|
||||
|
||||
// CHECK: variable initialization expression of NonisolatedStruct.customActorField
|
||||
// CHECK-NEXT: Isolation: global_actor. type: CustomActor
|
||||
// CHECK: NonisolatedStruct.customActorField.getter
|
||||
// CHECK-NEXT: Isolation: global_actor. type: CustomActor
|
||||
// CHECK: NonisolatedStruct.customActorField.setter
|
||||
// CHECK-NEXT: Isolation: global_actor. type: CustomActor
|
||||
@CustomActor var customActorField = NonSendableKlass()
|
||||
|
||||
nonisolated init() {}
|
||||
}
|
||||
|
||||
@MainActor
|
||||
struct MainActorKlass {
|
||||
// CHECK: variable initialization expression of MainActorKlass.mainActorField
|
||||
// CHECK-NEXT: Isolation: global_actor. type: MainActor
|
||||
// CHECK: MainActorKlass.mainActorField.getter
|
||||
// CHECK-NEXT: Isolation: global_actor. type: MainActor
|
||||
// CHECK: MainActorKlass.mainActorField.setter
|
||||
// CHECK-NEXT: Isolation: global_actor. type: MainActor
|
||||
var mainActorField = NonSendableKlass()
|
||||
|
||||
// CHECK: variable initialization expression of MainActorKlass.customActorField
|
||||
// CHECK-NEXT: Isolation: global_actor. type: CustomActor
|
||||
// CHECK: MainActorKlass.customActorField.getter
|
||||
// CHECK-NEXT: Isolation: global_actor. type: CustomActor
|
||||
// CHECK: MainActorKlass.customActorField.setter
|
||||
// CHECK-NEXT: Isolation: global_actor. type: CustomActor
|
||||
@CustomActor var customActorField = NonSendableKlass()
|
||||
|
||||
nonisolated init() {}
|
||||
}
|
||||
|
||||
struct NonisolatedKlass {
|
||||
// CHECK: variable initialization expression of NonisolatedKlass.nonisolatedField
|
||||
// CHECK-NEXT: Isolation: unspecified
|
||||
// CHECK: NonisolatedKlass.nonisolatedField.getter
|
||||
// CHECK-NEXT: Isolation: unspecified
|
||||
// CHECK: NonisolatedKlass.nonisolatedField.setter
|
||||
// CHECK-NEXT: Isolation: unspecified
|
||||
var nonisolatedField = NonSendableKlass()
|
||||
|
||||
// CHECK: variable initialization expression of NonisolatedKlass.mainActorField
|
||||
// CHECK-NEXT: Isolation: global_actor. type: MainActor
|
||||
// CHECK: NonisolatedKlass.mainActorField.getter
|
||||
// CHECK-NEXT: Isolation: global_actor. type: MainActor
|
||||
// CHECK: NonisolatedKlass.mainActorField.setter
|
||||
// CHECK-NEXT: Isolation: global_actor. type: MainActor
|
||||
@MainActor var mainActorField = NonSendableKlass()
|
||||
|
||||
// CHECK: variable initialization expression of NonisolatedKlass.customActorField
|
||||
// CHECK-NEXT: Isolation: global_actor. type: CustomActor
|
||||
// CHECK: NonisolatedKlass.customActorField.getter
|
||||
// CHECK-NEXT: Isolation: global_actor. type: CustomActor
|
||||
// CHECK: NonisolatedKlass.customActorField.setter
|
||||
// CHECK-NEXT: Isolation: global_actor. type: CustomActor
|
||||
@CustomActor var customActorField = NonSendableKlass()
|
||||
|
||||
nonisolated init() {}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user