mirror of
https://github.com/apple/swift.git
synced 2026-10-24 20:15:56 +02:00
`LifetimeDependenceScopeFixup` can insert `end_cow_mutation_addr` on a struct address containing multiple COW fields, `SimplifyEndCOWMutationAddr` lowers it to an `end_cow_mutation` on the struct. `skipStructAndExtract()` in COWOpts was unconditionally looking through `struct_extract` and `destructure_struct` instructions when tracing from `begin_cow_mutation` back to `end_cow_mutation`. COWOpts would then trace from a `begin_cow_mutation` on one field, through `struct_extract`, to the `end_cow_mutation` on the `struct` that was placed for a different field's mutation. This caused COWOpts to incorrectly conclude the buffer was uniquely referenced and fold the uniqueness check to true, breaking COW semantics. The fix restricts `skipStructAndExtract` to only look through `struct_extract` and `destructure_struct` when the struct type has exactly one stored property. Resolves rdar://172670647
40 lines
698 B
Swift
40 lines
698 B
Swift
// RUN: %target-run-simple-swift(-O)
|
|
|
|
// REQUIRES: executable_test
|
|
|
|
struct S {
|
|
var c: ContiguousArray<Int>
|
|
var a: ContiguousArray<UInt64>
|
|
var b: ContiguousArray<UInt64>
|
|
|
|
init(n: Int) {
|
|
c = .init(repeating: 0, count: n)
|
|
a = .init(repeating: 0, count: n)
|
|
b = .init(repeating: 0, count: n)
|
|
}
|
|
|
|
mutating func bump(n: Int) {
|
|
do {
|
|
var s = a.mutableSpan
|
|
for i in 0 ..< n { s[i] &+= 1 }
|
|
}
|
|
do {
|
|
var s = b.mutableSpan
|
|
for i in 0 ..< n { s[i] &+= 1 }
|
|
}
|
|
}
|
|
}
|
|
|
|
@inline(never)
|
|
func run() -> (UInt64, UInt64) {
|
|
var x = S(n: 3)
|
|
let snapshot = Array(x.b)
|
|
x.bump(n: 3)
|
|
|
|
return (x.b[0], snapshot[0])
|
|
}
|
|
|
|
let (a, b) = run()
|
|
precondition(a != b)
|
|
|