i have witnessed some code that is producing a runtime exclusivity violation, but it seems to only surface the runtime error when compiled with optimizations enabled. unfortunately i have not, as yet, found a small reproducer, but the gist is like:
func update(_ value: inout Value) {
// self, value both structs
value = Value(param: self.param) // traps within the (non-memberwise) init
}
is this an outcome that is expected (dynamic exclusivity violations differ based on optimization level), or should i try to reduce the issue to see if there's a bug?
Exclusivity violations are defined by the language. They can be hidden by optimization simply because optimization can prove that accesses are redundant. But never the other way around. If -O causes a trap, that's always worthy of a bug report. I can't tell whether the inout value is a member of self here. It would be great if you can come up with a reproducer, but I know hard that is with Swift.
// build with:
//
// swiftc -parse-as-library -Onone
// => does not trap
// swiftc -parse-as-library -O
// => traps with exclusivity violation
import Observation
struct MyState {
var _prop: String
var prop: String
{
@storageRestrictions(initializes: _prop)
init(initialValue) {
_prop = initialValue
}
get {
return _prop
}
}
let registrar = ObservationRegistrar()
init(prop: String) {
self.prop = prop // crashes
// self._prop = prop // does not
}
}
class Node {
var state = MyState(prop: "initial value")
func update(_ body: (inout MyState) -> Void) {
body(&state)
}
}
func test_exclusivity() {
let node = Node()
node.update { state in
state = MyState(prop: "new value")
}
}
@main
enum App {
static func main() {
test_exclusivity()
}
}
i have not yet dissected things enough to determine if it can be reproduced without the Observation code. to confirm, per your previous message, the fact that an exclusivity violation is not reported with -Onone but is with -O is a bug that i should file?
seems it is not related to Observation specifically (unsurprising), but appears to be reproducible when the client code contains certain types from a module built with library evolution:
// evo.swift
//
// build the following with something like:
// swiftc -emit-module -module-name LibraryEvoModule -emit-library -enable-library-evolution evo.swift -o build/libLibraryEvoModule.dylib
public struct ResilientStruct {
public init() {}
}
// exclusivity.swift
//
// build with something like:
// swiftc -parse-as-library -O -I build -L build -lLibraryEvoModule exclusive.swift
//
// traps if built with -O, doesn't if built with -Onone
import LibraryEvoModule
struct MyState {
var _prop: String
var prop: String
{
@storageRestrictions(initializes: _prop)
init(initialValue) {
_prop = initialValue
}
get {
return _prop
}
}
let resilient = ResilientStruct()
init(prop: String) {
self.prop = prop // crashes
// self._prop = prop // does not
}
}
class Node {
var state = MyState(prop: "initial value")
func update(_ body: (inout MyState) -> Void) {
body(&state)
}
}
func test_exclusivity() {
let node = Node()
node.update { state in
state = MyState(prop: "new value")
}
}
@main
enum App {
static func main() {
test_exclusivity()
}
}
it also appears to reproduce if the stored property is of certain types from the stdlib's Concurrency module, e.g. AsyncStream, ContinuousClock, etc.