|
| 1 | +// RUN: %target-swift-emit-silgen %s | %FileCheck %s |
| 2 | +// RUN: %target-swift-frontend -emit-sil -verify %s |
| 3 | + |
| 4 | +// rdar://109161396 |
| 5 | + |
| 6 | +public protocol P {} |
| 7 | + |
| 8 | +@_moveOnly |
| 9 | +public struct M { |
| 10 | + private var x: P |
| 11 | + var other: CInt { 0 } |
| 12 | + |
| 13 | + var otherMoveOnly: M { |
| 14 | + _read { |
| 15 | + yield self |
| 16 | + } |
| 17 | + } |
| 18 | + |
| 19 | + @_silgen_name("no") |
| 20 | + init() |
| 21 | +} |
| 22 | + |
| 23 | +// CHECK-LABEL: sil [ossa] @${{.*}}4test3mut |
| 24 | +// CHECK: [[CHECK:%.*]] = mark_must_check [consumable_and_assignable] %0 |
| 25 | +// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[CHECK]] |
| 26 | +// CHECK: [[RESULT:%.*]] = apply {{.*}}([[ACCESS]]) |
| 27 | +// CHECK; end_access [[ACCESS]] |
| 28 | +// CHECK: return [[RESULT]] |
| 29 | +public func test(mut: inout M) -> CInt { |
| 30 | + return mut.other |
| 31 | +} |
| 32 | + |
| 33 | +// CHECK-LABEL: sil [ossa] @${{.*}}4test6borrow |
| 34 | +// CHECK: [[CHECK:%.*]] = mark_must_check [no_consume_or_assign] %0 |
| 35 | +// CHECK: [[RESULT:%.*]] = apply {{.*}}([[CHECK]]) |
| 36 | +// CHECK: return [[RESULT]] |
| 37 | +public func test(borrow: borrowing M) -> CInt { |
| 38 | + return borrow.other |
| 39 | +} |
| 40 | + |
| 41 | +// CHECK-LABEL: sil [ossa] @${{.*}}4test7consume |
| 42 | +// CHECK: [[BOX:%.*]] = project_box |
| 43 | +// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[BOX]] |
| 44 | +// CHECK: [[CHECK:%.*]] = mark_must_check [no_consume_or_assign] [[ACCESS]] |
| 45 | +// CHECK: [[RESULT:%.*]] = apply {{.*}}([[CHECK]]) |
| 46 | +// CHECK; end_access [[ACCESS]] |
| 47 | +// CHECK: return [[RESULT]] |
| 48 | +public func test(consume: consuming M) -> CInt { |
| 49 | + return consume.other |
| 50 | +} |
| 51 | + |
| 52 | +// CHECK-LABEL: sil [ossa] @${{.*}}4test3own |
| 53 | +// CHECK: [[CHECK:%.*]] = mark_must_check [consumable_and_assignable] %0 |
| 54 | +// CHECK: [[RESULT:%.*]] = apply {{.*}}([[CHECK]]) |
| 55 | +// CHECK: return [[RESULT]] |
| 56 | +public func test(own: __owned M) -> CInt { |
| 57 | + return own.other |
| 58 | +} |
| 59 | + |
| 60 | +func use(_: CInt, andMutate _: inout M) {} |
| 61 | +func use(_: CInt, andConsume _: consuming M) {} |
| 62 | +func borrow(_: borrowing M, andMutate _: inout M) {} |
| 63 | +func borrow(_: borrowing M, andConsume _: consuming M) {} |
| 64 | + |
| 65 | +public func testNoInterferenceGet(mut: inout M, extra: consuming M) { |
| 66 | + // This should not cause exclusivity interference, since the result of |
| 67 | + // the getter can have an independent lifetime from the borrow. |
| 68 | + use(mut.other, andMutate: &mut) |
| 69 | + use(mut.other, andConsume: mut) |
| 70 | + mut = extra |
| 71 | +} |
| 72 | + |
| 73 | +public func testInterferenceRead(mut: inout M, extra: consuming M) { |
| 74 | + // This should cause exclusivity interference, since in order to borrow |
| 75 | + // the yielded result from the `_read`, we need to keep the borrow of |
| 76 | + // the base going. |
| 77 | + borrow(mut.otherMoveOnly, andMutate: &mut) // expected-error{{}} expected-note{{}} |
| 78 | + borrow(mut.otherMoveOnly, andConsume: mut) // expected-error{{}} expected-note{{}} |
| 79 | + mut = extra |
| 80 | +} |
0 commit comments