mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
If a subscript uses a read accessor to yield a noncopyable value, we'd emit an `end_apply` that's too tightly scoped to allow for a subsequent borrowing access on the yielded value. resolves rdar://159079818
2650 lines
135 KiB
Swift
2650 lines
135 KiB
Swift
// RUN: %target-swift-emit-silgen -Xllvm -sil-print-types %s | %FileCheck %s
|
|
|
|
//////////////////
|
|
// Declarations //
|
|
//////////////////
|
|
|
|
public final class CopyableKlass {
|
|
var fd = FD()
|
|
}
|
|
|
|
public struct FD: ~Copyable {
|
|
var copyableKlass = CopyableKlass()
|
|
}
|
|
|
|
public struct NonTrivialStruct2: ~Copyable {
|
|
var fd = FD()
|
|
var copyableKlass = CopyableKlass()
|
|
}
|
|
|
|
public struct NonTrivialStruct: ~Copyable {
|
|
var fd = FD()
|
|
var nonTrivialStruct2 = NonTrivialStruct2()
|
|
var copyableKlass = CopyableKlass()
|
|
var nonTrivialCopyableStruct = NonTrivialCopyableStruct()
|
|
}
|
|
|
|
public struct NonTrivialCopyableStruct2 {
|
|
var copyableKlass = CopyableKlass()
|
|
var copyableKlass2 = CopyableKlass()
|
|
}
|
|
|
|
public struct NonTrivialCopyableStruct {
|
|
var copyableKlass = CopyableKlass()
|
|
var nonTrivialCopyableStruct2 = NonTrivialCopyableStruct2()
|
|
}
|
|
|
|
public enum NonTrivialEnum: ~Copyable {
|
|
case first
|
|
case second(CopyableKlass)
|
|
case third(NonTrivialStruct)
|
|
}
|
|
|
|
public struct AddressOnlyGeneric<T> : ~Copyable {
|
|
var t: T
|
|
}
|
|
|
|
public protocol P {
|
|
}
|
|
extension CopyableKlass : P {}
|
|
|
|
public struct AddressOnlyProtocol: ~Copyable {
|
|
var t: P = CopyableKlass()
|
|
|
|
func nonMutatingFunc() {}
|
|
mutating func mutatingFunc() {}
|
|
}
|
|
|
|
var varGlobal = NonTrivialStruct()
|
|
let letGlobal = NonTrivialStruct()
|
|
|
|
public func borrowVal(_ e : borrowing NonTrivialEnum) {}
|
|
public func borrowVal(_ e : borrowing FD) {}
|
|
public func borrowVal(_ k: borrowing CopyableKlass) {}
|
|
public func borrowVal(_ k: borrowing NonTrivialCopyableStruct) {}
|
|
public func borrowVal(_ k: borrowing NonTrivialCopyableStruct2) {}
|
|
public func borrowVal(_ s: borrowing NonTrivialStruct) {}
|
|
public func borrowVal(_ s: borrowing NonTrivialStruct2) {}
|
|
public func borrowVal<T>(_ s: borrowing AddressOnlyGeneric<T>) {}
|
|
public func borrowVal(_ s: borrowing AddressOnlyProtocol) {}
|
|
|
|
public func consumeVal(_ e : __owned NonTrivialEnum) {}
|
|
public func consumeVal(_ e : __owned FD) {}
|
|
public func consumeVal(_ k: __owned CopyableKlass) {}
|
|
public func consumeVal(_ k: __owned NonTrivialCopyableStruct) {}
|
|
public func consumeVal(_ k: __owned NonTrivialCopyableStruct2) {}
|
|
public func consumeVal(_ s: __owned NonTrivialStruct) {}
|
|
public func consumeVal(_ s: __owned NonTrivialStruct2) {}
|
|
public func consumeVal<T>(_ s: __owned AddressOnlyGeneric<T>) {}
|
|
public func consumeVal(_ s: __owned AddressOnlyProtocol) {}
|
|
|
|
var bool: Bool { false }
|
|
|
|
///////////
|
|
// Tests //
|
|
///////////
|
|
|
|
//===---
|
|
// Function Arguments
|
|
//
|
|
|
|
// CHECK-LABEL: sil [ossa] @$s8moveonly19useNonTrivialStructyyAA0cdE0VF : $@convention(thin) (@guaranteed NonTrivialStruct) -> () {
|
|
// CHECK: bb0([[ARG:%.*]] : @guaranteed $NonTrivialStruct):
|
|
// CHECK: [[COPIED_ARG:%.*]] = copy_value [[ARG]]
|
|
// CHECK: mark_unresolved_non_copyable_value [no_consume_or_assign] [[COPIED_ARG]]
|
|
// CHECK: } // end sil function '$s8moveonly19useNonTrivialStructyyAA0cdE0VF'
|
|
public func useNonTrivialStruct(_ s: borrowing NonTrivialStruct) {
|
|
borrowVal(s)
|
|
let s2 = s
|
|
let k = s.fd
|
|
let _ = k
|
|
borrowVal(s)
|
|
let _ = s2
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @$s8moveonly24useNonTrivialOwnedStructyyAA0cdF0VnF : $@convention(thin) (@owned NonTrivialStruct) -> () {
|
|
// CHECK: bb0([[ARG:%.*]] : @owned $NonTrivialStruct):
|
|
// CHECK: [[BOX:%.*]] = alloc_box
|
|
// CHECK: [[PROJECT:%.*]] = project_box [[BOX]]
|
|
// CHECK: store [[ARG]] to [init] [[PROJECT]]
|
|
// CHECK: mark_unresolved_non_copyable_value [no_consume_or_assign] [[PROJECT]]
|
|
// CHECK: } // end sil function '$s8moveonly24useNonTrivialOwnedStructyyAA0cdF0VnF'
|
|
public func useNonTrivialOwnedStruct(_ s: __owned NonTrivialStruct) {
|
|
borrowVal(s)
|
|
let s2 = s
|
|
let k = s.fd
|
|
let _ = k
|
|
borrowVal(s)
|
|
let _ = s2
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @$s8moveonly17useNonTrivialEnumyyAA0cdE0OF : $@convention(thin) (@guaranteed NonTrivialEnum) -> () {
|
|
public func useNonTrivialEnum(_ s: borrowing NonTrivialEnum) {
|
|
borrowVal(s)
|
|
let s2 = s
|
|
switch consume s {
|
|
case _:
|
|
break
|
|
}
|
|
borrowVal(s)
|
|
let _ = s2
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @$s8moveonly22useNonTrivialOwnedEnumyyAA0cdF0OnF : $@convention(thin) (@owned NonTrivialEnum) -> () {
|
|
public func useNonTrivialOwnedEnum(_ s: __owned NonTrivialEnum) {
|
|
borrowVal(s)
|
|
let s2 = s
|
|
switch consume s {
|
|
case _:
|
|
break
|
|
}
|
|
borrowVal(s)
|
|
let _ = s2
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @$s8moveonly21useAddressOnlyGenericyyAA0cdE0VyxGhlF : $@convention(thin) <T> (@in_guaranteed AddressOnlyGeneric<T>) -> () {
|
|
// CHECK: bb0([[ARG:%.*]] :
|
|
// CHECK: mark_unresolved_non_copyable_value [no_consume_or_assign] [[ARG]]
|
|
// CHECK: } // end sil function '$s8moveonly21useAddressOnlyGenericyyAA0cdE0VyxGhlF'
|
|
public func useAddressOnlyGeneric<T>(_ s: __shared AddressOnlyGeneric<T>) {
|
|
borrowVal(s)
|
|
let s2 = s
|
|
let k = s.t
|
|
let _ = k
|
|
borrowVal(s)
|
|
let _ = s2
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @$s8moveonly26useOwnedAddressOnlyGenericyyAA0deF0VyxGnlF : $@convention(thin) <T> (@in AddressOnlyGeneric<T>) -> () {
|
|
// CHECK: bb0([[ARG:%.*]] :
|
|
// CHECK: mark_unresolved_non_copyable_value [consumable_and_assignable] [[ARG]]
|
|
// CHECK: } // end sil function '$s8moveonly26useOwnedAddressOnlyGenericyyAA0deF0VyxGnlF'
|
|
public func useOwnedAddressOnlyGeneric<T>(_ s: __owned AddressOnlyGeneric<T>) {
|
|
borrowVal(s)
|
|
let s2 = s
|
|
let k = s.t
|
|
let _ = k
|
|
borrowVal(s)
|
|
let _ = s2
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @$s8moveonly22useAddressOnlyProtocolyyAA0cdE0VhF : $@convention(thin) (@in_guaranteed AddressOnlyProtocol) -> () {
|
|
// CHECK: bb0([[ARG:%.*]] :
|
|
// CHECK: mark_unresolved_non_copyable_value [no_consume_or_assign] [[ARG]]
|
|
// CHECK: } // end sil function '$s8moveonly22useAddressOnlyProtocolyyAA0cdE0VhF'
|
|
public func useAddressOnlyProtocol(_ s: __shared AddressOnlyProtocol) {
|
|
borrowVal(s)
|
|
let s2 = s
|
|
let k = s.t
|
|
let _ = k
|
|
borrowVal(s)
|
|
let _ = s2
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @$s8moveonly27useOwnedAddressOnlyProtocolyyAA0deF0VnF : $@convention(thin) (@in AddressOnlyProtocol) -> () {
|
|
// CHECK: bb0([[ARG:%.*]] :
|
|
// CHECK: mark_unresolved_non_copyable_value [consumable_and_assignable] [[ARG]]
|
|
// CHECK: } // end sil function '$s8moveonly27useOwnedAddressOnlyProtocolyyAA0deF0VnF'
|
|
public func useOwnedAddressOnlyProtocol(_ s: __owned AddressOnlyProtocol) {
|
|
borrowVal(s)
|
|
let s2 = s
|
|
let k = s.t
|
|
let _ = k
|
|
borrowVal(s)
|
|
let _ = s2
|
|
}
|
|
|
|
//===---
|
|
// Self in Init
|
|
//
|
|
|
|
//===---
|
|
// Self in Methods
|
|
//
|
|
|
|
extension NonTrivialStruct {
|
|
// CHECK-LABEL: sil hidden [ossa] @$s8moveonly16NonTrivialStructV13testNoUseSelfyyF : $@convention(method) (@guaranteed NonTrivialStruct) -> () {
|
|
// CHECK: bb0([[ARG:%.*]] : @guaranteed $NonTrivialStruct):
|
|
// CHECK: [[COPIED_ARG:%.*]] = copy_value [[ARG]]
|
|
// CHECK: mark_unresolved_non_copyable_value [no_consume_or_assign] [[COPIED_ARG]]
|
|
// CHECK: } // end sil function '$s8moveonly16NonTrivialStructV13testNoUseSelfyyF'
|
|
func testNoUseSelf() {
|
|
let x = self
|
|
let _ = x
|
|
}
|
|
}
|
|
|
|
extension NonTrivialEnum {
|
|
// CHECK-LABEL: sil hidden [ossa] @$s8moveonly14NonTrivialEnumO13testNoUseSelfyyF : $@convention(method) (@guaranteed NonTrivialEnum) -> () {
|
|
// CHECK: bb0([[ARG:%.*]] : @guaranteed $NonTrivialEnum):
|
|
// CHECK: [[COPIED_ARG:%.*]] = copy_value [[ARG]]
|
|
// CHECK: mark_unresolved_non_copyable_value [no_consume_or_assign] [[COPIED_ARG]]
|
|
// CHECK: } // end sil function '$s8moveonly14NonTrivialEnumO13testNoUseSelfyyF'
|
|
func testNoUseSelf() {
|
|
let x = self
|
|
let _ = x
|
|
}
|
|
}
|
|
|
|
extension AddressOnlyGeneric {
|
|
// CHECK-LABEL: sil hidden [ossa] @$s8moveonly18AddressOnlyGenericV13testNoUseSelfyyF : $@convention(method) <T> (@in_guaranteed AddressOnlyGeneric<T>) -> () {
|
|
// CHECK: bb0([[ARG_IN:%.*]] :
|
|
// CHECK: [[ARG:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[ARG_IN]] :
|
|
//
|
|
// CHECK: [[ALLOC_X:%.*]] = alloc_box $<τ_0_0> { let AddressOnlyGeneric<τ_0_0> } <T>, let, name "x"
|
|
// CHECK: [[X:%.*]] = begin_borrow [lexical] [var_decl] [[ALLOC_X]]
|
|
// CHECK: [[PROJECT_X:%.*]] = project_box [[X]]
|
|
// CHECK: copy_addr [[ARG]] to [init] [[PROJECT_X]]
|
|
// CHECK: [[MARKED_X:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[PROJECT_X]]
|
|
// CHECK: [[BLACKHOLE_ADDR:%.*]] = alloc_stack $AddressOnlyGeneric<T>
|
|
// CHECK: copy_addr [[MARKED_X]] to [init] [[BLACKHOLE_ADDR]]
|
|
// CHECK: destroy_addr [[BLACKHOLE_ADDR]]
|
|
// CHECK: dealloc_stack [[BLACKHOLE_ADDR]]
|
|
//
|
|
// CHECK: [[ALLOC_Y:%.*]] = alloc_box $<τ_0_0> { let AddressOnlyGeneric<τ_0_0> } <T>, let, name "y"
|
|
// CHECK: [[Y:%.*]] = begin_borrow [lexical] [var_decl] [[ALLOC_Y]]
|
|
// CHECK: [[PROJECT_Y:%.*]] = project_box [[Y]]
|
|
// CHECK: copy_addr [[ARG]] to [init] [[PROJECT_Y]]
|
|
// CHECK: [[MARKED_Y:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[PROJECT_Y]]
|
|
// CHECK: [[BLACKHOLE_ADDR:%.*]] = alloc_stack $AddressOnlyGeneric<T>
|
|
// CHECK: copy_addr [[MARKED_Y]] to [init] [[BLACKHOLE_ADDR]]
|
|
// CHECK: destroy_addr [[BLACKHOLE_ADDR]]
|
|
// CHECK: dealloc_stack [[BLACKHOLE_ADDR]]
|
|
//
|
|
// CHECK: } // end sil function '$s8moveonly18AddressOnlyGenericV13testNoUseSelfyyF'
|
|
func testNoUseSelf() {
|
|
let x = self
|
|
let _ = x
|
|
let y = self
|
|
let _ = y
|
|
}
|
|
}
|
|
|
|
extension AddressOnlyProtocol {
|
|
// CHECK-LABEL: sil hidden [ossa] @$s8moveonly19AddressOnlyProtocolV13testNoUseSelfyyF : $@convention(method) (@in_guaranteed AddressOnlyProtocol) -> () {
|
|
// CHECK: bb0([[ARG_IN:%.*]] :
|
|
// CHECK: [[ARG:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[ARG_IN]] :
|
|
//
|
|
// CHECK: [[ALLOC_X:%.*]] = alloc_box ${ let AddressOnlyProtocol }, let, name "x"
|
|
// CHECK: [[X:%.*]] = begin_borrow [lexical] [var_decl] [[ALLOC_X]]
|
|
// CHECK: [[PROJECT_X:%.*]] = project_box [[X]]
|
|
// CHECK: copy_addr [[ARG]] to [init] [[PROJECT_X]]
|
|
// CHECK: [[MARKED_X:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[PROJECT_X]]
|
|
// CHECK: [[BLACKHOLE_ADDR:%.*]] = alloc_stack $AddressOnlyProtocol
|
|
// CHECK: copy_addr [[MARKED_X]] to [init] [[BLACKHOLE_ADDR]]
|
|
// CHECK: destroy_addr [[BLACKHOLE_ADDR]]
|
|
// CHECK: dealloc_stack [[BLACKHOLE_ADDR]]
|
|
//
|
|
// CHECK: [[ALLOC_Y:%.*]] = alloc_box ${ let AddressOnlyProtocol }, let, name "y"
|
|
// CHECK: [[Y:%.*]] = begin_borrow [lexical] [var_decl] [[ALLOC_Y]]
|
|
// CHECK: [[PROJECT_Y:%.*]] = project_box [[Y]]
|
|
// CHECK: copy_addr [[ARG]] to [init] [[PROJECT_Y]]
|
|
// CHECK: [[MARKED_Y:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[PROJECT_Y]]
|
|
// CHECK: [[BLACKHOLE_ADDR:%.*]] = alloc_stack $AddressOnlyProtocol
|
|
// CHECK: copy_addr [[MARKED_Y]] to [init] [[BLACKHOLE_ADDR]]
|
|
// CHECK: destroy_addr [[BLACKHOLE_ADDR]]
|
|
// CHECK: dealloc_stack [[BLACKHOLE_ADDR]]
|
|
// CHECK: } // end sil function '$s8moveonly19AddressOnlyProtocolV13testNoUseSelfyyF'
|
|
func testNoUseSelf() {
|
|
let x = self
|
|
let _ = x
|
|
let y = self
|
|
let _ = y
|
|
}
|
|
}
|
|
|
|
///////////////////////////////
|
|
// Black Hole Initialization //
|
|
///////////////////////////////
|
|
|
|
// CHECK-LABEL: sil hidden [ossa] @$s8moveonly27blackHoleLetInitialization1yyF : $@convention(thin) () -> () {
|
|
// CHECK: [[BOX:%.*]] = alloc_box
|
|
// CHECK: [[BORROWED_BOX:%.*]] = begin_borrow [lexical] [var_decl] [[BOX]]
|
|
// CHECK: [[PROJECT:%.*]] = project_box [[BORROWED_BOX]]
|
|
// CHECK: [[FN:%.*]] = function_ref @$s8moveonly2FDVACycfC :
|
|
// CHECK: [[X:%.*]] = apply [[FN]](
|
|
// CHECK: store [[X]] to [init] [[PROJECT]]
|
|
//
|
|
// CHECK: [[MARKED:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[PROJECT]]
|
|
// CHECK: [[VALUE:%.*]] = load [copy] [[MARKED]]
|
|
// CHECK: move_value [[VALUE]]
|
|
// CHECK: } // end sil function '$s8moveonly27blackHoleLetInitialization1yyF'
|
|
func blackHoleLetInitialization1() {
|
|
let x = FD()
|
|
let _ = x
|
|
}
|
|
|
|
// CHECK-LABEL: sil hidden [ossa] @$s8moveonly27blackHoleLetInitialization2yyF : $@convention(thin) () -> () {
|
|
// CHECK: [[BOX:%.*]] = alloc_box
|
|
// CHECK: [[BORROWED_BOX:%.*]] = begin_borrow [lexical] [var_decl] [[BOX]]
|
|
// CHECK: [[PROJECT:%.*]] = project_box [[BORROWED_BOX]]
|
|
// CHECK: [[FN:%.*]] = function_ref @$s8moveonly2FDVACycfC :
|
|
// CHECK: [[X:%.*]] = apply [[FN]](
|
|
// CHECK: store [[X]] to [init] [[PROJECT]]
|
|
//
|
|
// CHECK: [[MARKED:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[PROJECT]]
|
|
// CHECK: [[VALUE:%.*]] = load [copy] [[MARKED]]
|
|
// CHECK: move_value [[VALUE]]
|
|
// CHECK: } // end sil function '$s8moveonly27blackHoleLetInitialization2yyF'
|
|
func blackHoleLetInitialization2() {
|
|
let x = FD()
|
|
var _ = x
|
|
}
|
|
|
|
// CHECK-LABEL: sil hidden [ossa] @$s8moveonly27blackHoleVarInitialization1yyF : $@convention(thin) () -> () {
|
|
// CHECK: [[BOX:%.*]] = alloc_box
|
|
// CHECK: [[BOX_BORROW:%.*]] = begin_borrow [lexical] [var_decl] [[BOX]]
|
|
// CHECK: [[PROJECT_BOX:%.*]] = project_box [[BOX_BORROW]]
|
|
// CHECK: store {{%.*}} to [init] [[PROJECT_BOX]]
|
|
// CHECK: [[FN:%.*]] = function_ref @$s8moveonly2FDVACycfC :
|
|
// CHECK: [[X:%.*]] = apply [[FN]](
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[PROJECT_BOX]]
|
|
// CHECK: [[MARKED_ADDR:%.*]] = mark_unresolved_non_copyable_value [assignable_but_not_consumable] [[ACCESS]]
|
|
// CHECK: assign [[X]] to [[MARKED_ADDR]]
|
|
//
|
|
// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PROJECT_BOX]]
|
|
// CHECK: [[MARKED_ADDR:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[READ]]
|
|
// CHECK: [[LD:%.*]] = load [copy] [[MARKED_ADDR]]
|
|
// CHECK: [[CONSUME:%.*]] = move_value [[LD]]
|
|
// CHECK: } // end sil function '$s8moveonly27blackHoleVarInitialization1yyF'
|
|
func blackHoleVarInitialization1() {
|
|
var x = FD()
|
|
x = FD()
|
|
let _ = x
|
|
}
|
|
|
|
// CHECK-LABEL: sil hidden [ossa] @$s8moveonly27blackHoleVarInitialization2yyF : $@convention(thin) () -> () {
|
|
// CHECK: [[BOX:%.*]] = alloc_box
|
|
// CHECK: [[BOX_BORROW:%.*]] = begin_borrow [lexical] [var_decl] [[BOX]]
|
|
// CHECK: [[PROJECT_BOX:%.*]] = project_box [[BOX_BORROW]]
|
|
// CHECK: store {{%.*}} to [init] [[PROJECT_BOX]]
|
|
//
|
|
// CHECK: [[FN:%.*]] = function_ref @$s8moveonly2FDVACycfC :
|
|
// CHECK: [[X:%.*]] = apply [[FN]](
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[PROJECT_BOX]]
|
|
// CHECK: [[MARKED_ADDR:%.*]] = mark_unresolved_non_copyable_value [assignable_but_not_consumable] [[ACCESS]]
|
|
// CHECK: assign [[X]] to [[MARKED_ADDR]]
|
|
//
|
|
// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PROJECT_BOX]]
|
|
// CHECK: [[MARKED_ADDR:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[READ]]
|
|
// CHECK: [[LD:%.*]] = load [copy] [[MARKED_ADDR]]
|
|
// CHECK: [[CONSUME:%.*]] = move_value [[LD]]
|
|
// CHECK: } // end sil function '$s8moveonly27blackHoleVarInitialization2yyF'
|
|
func blackHoleVarInitialization2() {
|
|
var x = FD()
|
|
x = FD()
|
|
var _ = x
|
|
}
|
|
|
|
// CHECK-LABEL: sil hidden [ossa] @$s8moveonly27blackHoleVarInitialization3yyF : $@convention(thin) () -> () {
|
|
// CHECK: [[BOX:%.*]] = alloc_box
|
|
// CHECK: [[BOX_BORROW:%.*]] = begin_borrow [lexical] [var_decl] [[BOX]]
|
|
// CHECK: [[PROJECT_BOX:%.*]] = project_box [[BOX_BORROW]]
|
|
// CHECK: store {{%.*}} to [init] [[PROJECT_BOX]]
|
|
//
|
|
// CHECK: [[FN:%.*]] = function_ref @$s8moveonly2FDVACycfC :
|
|
// CHECK: [[X:%.*]] = apply [[FN]](
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[PROJECT_BOX]]
|
|
// CHECK: [[MARKED_ADDR:%.*]] = mark_unresolved_non_copyable_value [assignable_but_not_consumable] [[ACCESS]]
|
|
// CHECK: assign [[X]] to [[MARKED_ADDR]]
|
|
//
|
|
// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PROJECT_BOX]]
|
|
// CHECK: [[MARKED_ADDR:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[READ]]
|
|
// CHECK: [[LD:%.*]] = load [copy] [[MARKED_ADDR]]
|
|
// CHECK: [[CONSUME:%.*]] = move_value [[LD]]
|
|
// CHECK: } // end sil function '$s8moveonly27blackHoleVarInitialization3yyF'
|
|
func blackHoleVarInitialization3() {
|
|
var x = FD()
|
|
x = FD()
|
|
_ = x
|
|
}
|
|
|
|
////////////////////////////////
|
|
// Borrow Function Call Tests //
|
|
////////////////////////////////
|
|
|
|
// CHECK-LABEL: sil hidden [ossa] @$s8moveonly24borrowObjectFunctionCallyyF : $@convention(thin) () -> () {
|
|
// CHECK: [[BOX:%.*]] = alloc_box
|
|
// CHECK: [[BORROW_BOX:%.*]] = begin_borrow [lexical] [var_decl] [[BOX]]
|
|
//
|
|
// CHECK: [[PROJECT:%.*]] = project_box [[BORROW_BOX]]
|
|
// CHECK: store {{%.*}} to [init] [[PROJECT]]
|
|
//
|
|
// CHECK: [[CLS:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[PROJECT]]
|
|
// CHECK: [[BORROW:%.*]] = load_borrow [[CLS]]
|
|
// CHECK: [[FN:%.*]] = function_ref @$s8moveonly9borrowValyyAA2FDVF :
|
|
// CHECK: apply [[FN]]([[BORROW]])
|
|
// CHECK: end_borrow [[BORROW]]
|
|
// CHECK: } // end sil function '$s8moveonly24borrowObjectFunctionCallyyF'
|
|
func borrowObjectFunctionCall() {
|
|
let k = FD()
|
|
borrowVal(k)
|
|
}
|
|
|
|
// CHECK-LABEL: sil hidden [ossa] @$s8moveonly29moveOnlyStructNonConsumingUseyyF : $@convention(thin) () -> () {
|
|
// CHECK: [[BOX:%.*]] = alloc_box
|
|
// CHECK: [[BORROWED_BOX:%.*]] = begin_borrow [lexical] [var_decl] [[BOX]]
|
|
// CHECK: [[PROJECT:%.*]] = project_box [[BORROWED_BOX]]
|
|
// CHECK: store {{%.*}} to [init] [[PROJECT]]
|
|
//
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[PROJECT]]
|
|
// CHECK: [[MARKED_ADDR:%.*]] = mark_unresolved_non_copyable_value [assignable_but_not_consumable]
|
|
// CHECK: assign {{%.*}} to [[MARKED_ADDR]]
|
|
//
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]]
|
|
// CHECK: [[MARKED_ADDR:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[ACCESS]]
|
|
// CHECK: [[BORROW:%.*]] = load [copy] [[MARKED_ADDR]]
|
|
// CHECK: [[FN:%.*]] = function_ref @$s8moveonly9borrowValyyAA16NonTrivialStructVF :
|
|
// CHECK: apply [[FN]]([[BORROW]])
|
|
// CHECK: destroy_value [[BORROW]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: } // end sil function '$s8moveonly29moveOnlyStructNonConsumingUseyyF'
|
|
func moveOnlyStructNonConsumingUse() {
|
|
var k = NonTrivialStruct()
|
|
k = NonTrivialStruct()
|
|
borrowVal(k)
|
|
}
|
|
|
|
// CHECK-LABEL: sil hidden [ossa] @$s8moveonly018moveOnlyStructMovecD15NonConsumingUseyyF : $@convention(thin) () -> () {
|
|
// CHECK: [[BOX:%.*]] = alloc_box
|
|
// CHECK: [[BORROW_BOX:%.*]] = begin_borrow [lexical] [var_decl]
|
|
// CHECK: [[PROJECT:%.*]] = project_box [[BORROW_BOX]]
|
|
//
|
|
// CHECK: store
|
|
// CHECK: assign
|
|
//
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]]
|
|
// CHECK: [[MARKED_ADDR:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[ACCESS]]
|
|
// CHECK: [[GEP:%.*]] = struct_element_addr [[MARKED_ADDR]] : $*NonTrivialStruct, #NonTrivialStruct.nonTrivialStruct2
|
|
// CHECK: [[BORROW:%.*]] = load [copy] [[GEP]]
|
|
// CHECK: [[FN:%.*]] = function_ref @$s8moveonly9borrowValyyAA17NonTrivialStruct2VF : $@convention(thin) (@guaranteed NonTrivialStruct2) -> ()
|
|
// CHECK: apply [[FN]]([[BORROW]])
|
|
// CHECK: destroy_value [[BORROW]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: } // end sil function '$s8moveonly018moveOnlyStructMovecD15NonConsumingUseyyF'
|
|
func moveOnlyStructMoveOnlyStructNonConsumingUse() {
|
|
var k = NonTrivialStruct()
|
|
k = NonTrivialStruct()
|
|
borrowVal(k.nonTrivialStruct2)
|
|
}
|
|
|
|
// CHECK-LABEL: sil hidden [ossa] @$s8moveonly018moveOnlyStructMovecD28CopyableKlassNonConsumingUseyyF : $@convention(thin) () -> () {
|
|
// CHECK: [[BOX:%.*]] = alloc_box
|
|
// CHECK: [[BORROW_BOX:%.*]] = begin_borrow [lexical] [var_decl]
|
|
// CHECK: [[PROJECT:%.*]] = project_box [[BORROWED_BOX]]
|
|
|
|
// CHECK: store
|
|
// CHECK: assign
|
|
//
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]]
|
|
// CHECK: [[MARKED_ADDR:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[ACCESS]]
|
|
// CHECK: [[GEP1:%.*]] = struct_element_addr [[MARKED_ADDR]] : $*NonTrivialStruct, #NonTrivialStruct.nonTrivialStruct2
|
|
// CHECK: [[GEP2:%.*]] = struct_element_addr [[GEP1]] : $*NonTrivialStruct2, #NonTrivialStruct2.copyableKlass
|
|
// CHECK: [[COPY:%.*]] = load [copy] [[GEP2]] : $*CopyableKlass
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: [[FN:%.*]] = function_ref @$s8moveonly9borrowValyyAA13CopyableKlassCF : $@convention(thin) (@guaranteed CopyableKlass) -> ()
|
|
// CHECK: apply [[FN]]([[COPY]])
|
|
// CHECK: destroy_value [[COPY]] : $CopyableKlass
|
|
// CHECK: } // end sil function '$s8moveonly018moveOnlyStructMovecD28CopyableKlassNonConsumingUseyyF'
|
|
func moveOnlyStructMoveOnlyStructCopyableKlassNonConsumingUse() {
|
|
var k = NonTrivialStruct()
|
|
k = NonTrivialStruct()
|
|
borrowVal(k.nonTrivialStruct2.copyableKlass)
|
|
}
|
|
|
|
// CHECK-LABEL: sil hidden [ossa] @$s8moveonly021moveOnlyStructSetMoveC5FieldyyF : $@convention(thin) () -> () {
|
|
// CHECK: [[BOX:%.*]] = alloc_box ${ var NonTrivialStruct }
|
|
// CHECK: [[BORROW_BOX:%.*]] = begin_borrow [lexical] [var_decl] [[BOX]]
|
|
// CHECK: [[PROJECT1:%.*]] = project_box [[BORROW_BOX]]
|
|
// CHECK: store
|
|
//
|
|
// CHECK: [[BOX2:%.*]] = alloc_box ${ let NonTrivialStruct2 }
|
|
// CHECK: [[BORROW_BOX2:%.*]] = begin_borrow [lexical] [var_decl] [[BOX2]]
|
|
// CHECK: [[PROJECT2:%.*]] = project_box [[BORROW_BOX2]]
|
|
// CHECK: store
|
|
//
|
|
// CHECK: [[MARKED_ADDR2:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[PROJECT2]] : $*NonTrivialStruct2
|
|
// CHECK: [[CONSUMED_LET:%.*]] = load [copy] [[MARKED_ADDR2]] : $*NonTrivialStruct2
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[PROJECT1]]
|
|
// CHECK: [[MARKED_ADDR1:%.*]] = mark_unresolved_non_copyable_value [assignable_but_not_consumable] [[ACCESS]]
|
|
// CHECK: [[GEP:%.*]] = struct_element_addr [[MARKED_ADDR1]] : $*NonTrivialStruct, #NonTrivialStruct.nonTrivialStruct2
|
|
// CHECK: assign [[CONSUMED_LET]] to [[GEP]] : $*NonTrivialStruct2
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: } // end sil function '$s8moveonly021moveOnlyStructSetMoveC5FieldyyF'
|
|
func moveOnlyStructSetMoveOnlyField() {
|
|
var k = NonTrivialStruct()
|
|
let new = NonTrivialStruct2()
|
|
k.nonTrivialStruct2 = new
|
|
}
|
|
|
|
// CHECK-LABEL: sil hidden [ossa] @$s8moveonly022moveOnlyStructCopyableD15NonConsumingUseyyF : $@convention(thin) () -> () {
|
|
// CHECK: [[BOX:%.*]] = alloc_box
|
|
// CHECK: [[BORROW_BOX:%.*]] = begin_borrow [lexical] [var_decl]
|
|
// CHECK: [[PROJECT:%.*]] = project_box [[BORROWED_BOX]]
|
|
//
|
|
// CHECK: store
|
|
// CHECK: assign
|
|
//
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]]
|
|
// CHECK: [[MARKED_ADDR:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[ACCESS]]
|
|
// CHECK: [[GEP:%.*]] = struct_element_addr [[MARKED_ADDR]] : $*NonTrivialStruct, #NonTrivialStruct.nonTrivialCopyableStruct
|
|
// CHECK: [[COPY:%.*]] = load [copy] [[GEP]] : $*NonTrivialCopyableStruct
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: [[FN:%.*]] = function_ref @$s8moveonly9borrowValyyAA24NonTrivialCopyableStructVF :
|
|
// CHECK: apply [[FN]]([[COPY]])
|
|
// CHECK: destroy_value [[COPY]] : $NonTrivialCopyableStruct
|
|
// CHECK: } // end sil function '$s8moveonly022moveOnlyStructCopyableD15NonConsumingUseyyF'
|
|
func moveOnlyStructCopyableStructNonConsumingUse() {
|
|
var k = NonTrivialStruct()
|
|
k = NonTrivialStruct()
|
|
borrowVal(k.nonTrivialCopyableStruct)
|
|
}
|
|
|
|
// CHECK-LABEL: sil hidden [ossa] @$s8moveonly022moveOnlyStructCopyabledE20KlassNonConsumingUseyyF : $@convention(thin) () -> () {
|
|
// CHECK: [[BOX:%.*]] = alloc_box
|
|
// CHECK: [[BORROW_BOX:%.*]] = begin_borrow [lexical] [var_decl]
|
|
// CHECK: [[PROJECT:%.*]] = project_box [[BORROWED_BOX]]
|
|
//
|
|
// CHECK: store
|
|
// CHECK: assign
|
|
//
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]]
|
|
// CHECK: [[MARKED_ADDR:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[ACCESS]]
|
|
// CHECK: [[GEP1:%.*]] = struct_element_addr [[MARKED_ADDR]] : $*NonTrivialStruct, #NonTrivialStruct.nonTrivialCopyableStruct
|
|
// CHECK: [[GEP2:%.*]] = struct_element_addr [[GEP1]] : $*NonTrivialCopyableStruct, #NonTrivialCopyableStruct.copyableKlass
|
|
// CHECK: [[COPY:%.*]] = load [copy] [[GEP2]] : $*CopyableKlass
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: [[FN:%.*]] = function_ref @$s8moveonly9borrowValyyAA13CopyableKlassCF :
|
|
// CHECK: apply [[FN]]([[COPY]])
|
|
// CHECK: destroy_value [[COPY]] : $CopyableKlass
|
|
// CHECK: } // end sil function '$s8moveonly022moveOnlyStructCopyabledE20KlassNonConsumingUseyyF'
|
|
func moveOnlyStructCopyableStructCopyableKlassNonConsumingUse() {
|
|
var k = NonTrivialStruct()
|
|
k = NonTrivialStruct()
|
|
borrowVal(k.nonTrivialCopyableStruct.copyableKlass)
|
|
}
|
|
|
|
// CHECK-LABEL: sil hidden [ossa] @$s8moveonly022moveOnlyStructCopyabledeD15NonConsumingUseyyF : $@convention(thin) () -> () {
|
|
// CHECK: [[BOX:%.*]] = alloc_box
|
|
// CHECK: [[BORROW_BOX:%.*]] = begin_borrow [lexical] [var_decl]
|
|
// CHECK: [[PROJECT:%.*]] = project_box [[BORROWED_BOX]]
|
|
//
|
|
// CHECK: store
|
|
// CHECK: assign
|
|
//
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]]
|
|
// CHECK: [[MARKED_ADDR:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[ACCESS]]
|
|
// CHECK: [[GEP1:%.*]] = struct_element_addr [[MARKED_ADDR]] : $*NonTrivialStruct, #NonTrivialStruct.nonTrivialCopyableStruct
|
|
// CHECK: [[GEP2:%.*]] = struct_element_addr [[GEP1]] : $*NonTrivialCopyableStruct, #NonTrivialCopyableStruct.nonTrivialCopyableStruct2
|
|
// CHECK: [[COPY:%.*]] = load [copy] [[GEP2]] : $*NonTrivialCopyableStruct2
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: [[FN:%.*]] = function_ref @$s8moveonly9borrowValyyAA25NonTrivialCopyableStruct2VF :
|
|
// CHECK: apply [[FN]]([[COPY]])
|
|
// CHECK: destroy_value [[COPY]] : $NonTrivialCopyableStruct2
|
|
// CHECK: } // end sil function '$s8moveonly022moveOnlyStructCopyabledeD15NonConsumingUseyyF'
|
|
func moveOnlyStructCopyableStructCopyableStructNonConsumingUse() {
|
|
var k = NonTrivialStruct()
|
|
k = NonTrivialStruct()
|
|
borrowVal(k.nonTrivialCopyableStruct.nonTrivialCopyableStruct2)
|
|
}
|
|
|
|
// CHECK-LABEL: sil hidden [ossa] @$s8moveonly022moveOnlyStructCopyablededE20KlassNonConsumingUseyyF : $@convention(thin) () -> () {
|
|
// CHECK: [[BOX:%.*]] = alloc_box
|
|
// CHECK: [[BORROW_BOX:%.*]] = begin_borrow [lexical] [var_decl]
|
|
// CHECK: [[PROJECT:%.*]] = project_box [[BORROWED_BOX]]
|
|
//
|
|
// CHECK: store
|
|
// CHECK: assign
|
|
//
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]]
|
|
// CHECK: [[MARKED_ADDR:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[ACCESS]]
|
|
// CHECK: [[GEP1:%.*]] = struct_element_addr [[MARKED_ADDR]] : $*NonTrivialStruct, #NonTrivialStruct.nonTrivialCopyableStruct
|
|
// CHECK: [[GEP2:%.*]] = struct_element_addr [[GEP1]] : $*NonTrivialCopyableStruct, #NonTrivialCopyableStruct.nonTrivialCopyableStruct2
|
|
// CHECK: [[GEP3:%.*]] = struct_element_addr [[GEP2]] : $*NonTrivialCopyableStruct2, #NonTrivialCopyableStruct2.copyableKlass
|
|
// CHECK: [[COPY:%.*]] = load [copy] [[GEP3]] : $*CopyableKlass
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: [[FN:%.*]] = function_ref @$s8moveonly9borrowValyyAA13CopyableKlassCF :
|
|
// CHECK: apply [[FN]]([[COPY]])
|
|
// CHECK: destroy_value [[COPY]] : $CopyableKlass
|
|
// CHECK: } // end sil function '$s8moveonly022moveOnlyStructCopyablededE20KlassNonConsumingUseyyF'
|
|
func moveOnlyStructCopyableStructCopyableStructCopyableKlassNonConsumingUse() {
|
|
var k = NonTrivialStruct()
|
|
k = NonTrivialStruct()
|
|
borrowVal(k.nonTrivialCopyableStruct.nonTrivialCopyableStruct2.copyableKlass)
|
|
}
|
|
|
|
// We fail here b/c we are accessing through a class.
|
|
//
|
|
// CHECK-LABEL: sil hidden [ossa] @$s8moveonly022moveOnlyStructCopyabledede9KlassMovecF15NonConsumingUseyyF : $@convention(thin) () -> () {
|
|
// CHECK: [[BOX:%.*]] = alloc_box
|
|
// CHECK: [[BORROW_BOX:%.*]] = begin_borrow [lexical] [var_decl]
|
|
// CHECK: [[PROJECT:%.*]] = project_box [[BORROWED_BOX]]
|
|
//
|
|
// CHECK: store
|
|
// CHECK: assign
|
|
//
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]]
|
|
// CHECK: [[MARKED_ADDR:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[ACCESS]]
|
|
// CHECK: [[GEP1:%.*]] = struct_element_addr [[MARKED_ADDR]] : $*NonTrivialStruct, #NonTrivialStruct.nonTrivialCopyableStruct
|
|
// CHECK: [[GEP2:%.*]] = struct_element_addr [[GEP1]] : $*NonTrivialCopyableStruct, #NonTrivialCopyableStruct.nonTrivialCopyableStruct2
|
|
// CHECK: [[GEP3:%.*]] = struct_element_addr [[GEP2]] : $*NonTrivialCopyableStruct2, #NonTrivialCopyableStruct2.copyableKlass
|
|
// CHECK: [[COPYABLE_KLASS:%.*]] = load [copy] [[GEP3]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: [[BORROWED_COPYABLE_KLASS:%.*]] = begin_borrow [[COPYABLE_KLASS]]
|
|
// CHECK: [[FIELD:%.*]] = ref_element_addr [[BORROWED_COPYABLE_KLASS]]
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [dynamic] [[FIELD]]
|
|
// CHECK: [[ACCESS_MARK:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[ACCESS]]
|
|
// CHECK: [[BORROWED_MOVEONLY_KLASS:%.*]] = load [copy] [[ACCESS_MARK]]
|
|
// CHECK: [[FN:%.*]] = function_ref @$s8moveonly9borrowValyyAA2FDVF :
|
|
// CHECK: apply [[FN]]([[BORROWED_MOVEONLY_KLASS]])
|
|
// CHECK: destroy_value [[BORROWED_MOVEONLY_KLASS]]
|
|
// CHECK: destroy_value [[COPYABLE_KLASS]]
|
|
// CHECK: } // end sil function '$s8moveonly022moveOnlyStructCopyabledede9KlassMovecF15NonConsumingUseyyF'
|
|
func moveOnlyStructCopyableStructCopyableStructCopyableKlassMoveOnlyKlassNonConsumingUse() {
|
|
var k = NonTrivialStruct()
|
|
k = NonTrivialStruct()
|
|
borrowVal(k.nonTrivialCopyableStruct.nonTrivialCopyableStruct2.copyableKlass.fd)
|
|
}
|
|
|
|
//////////////////////
|
|
// Assignment Tests //
|
|
//////////////////////
|
|
|
|
// CHECK-LABEL: sil hidden [ossa] @$s8moveonly19assignCopyableKlassyyAA0cD0CF : $@convention(thin) (@guaranteed CopyableKlass) -> () {
|
|
// CHECK: bb0([[ARG:%.*]] : @guaranteed
|
|
// CHECK: [[REF:%.*]] = ref_element_addr [[ARG]]
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [modify] [dynamic] [[REF]]
|
|
// CHECK: [[MARKED_ACCESS:%.*]] = mark_unresolved_non_copyable_value [assignable_but_not_consumable] [[ACCESS]]
|
|
// CHECK: assign {{%.*}} to [[MARKED_ACCESS]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: } // end sil function '$s8moveonly19assignCopyableKlassyyAA0cD0CF'
|
|
func assignCopyableKlass(_ x: CopyableKlass) {
|
|
x.fd = FD()
|
|
}
|
|
|
|
///////////////////////
|
|
// Enum Switch Tests //
|
|
///////////////////////
|
|
|
|
enum EnumSwitchTests {
|
|
enum E2: ~Copyable {
|
|
case lhs(CopyableKlass)
|
|
case rhs(FD)
|
|
}
|
|
|
|
enum E: ~Copyable {
|
|
case first(NonTrivialStruct2)
|
|
case second(NonTrivialStruct)
|
|
case third(CopyableKlass)
|
|
case fourth(E2)
|
|
}
|
|
}
|
|
|
|
func consumeVal(_ e: __owned EnumSwitchTests.E2) {}
|
|
|
|
var booleanGuard: Bool { false }
|
|
var booleanGuard2: Bool { false }
|
|
|
|
// CHECK-LABEL: sil hidden [ossa] @$s8moveonly15enumSwitchTest1yyAA04EnumC5TestsO1EOF : $@convention(thin) (@guaranteed EnumSwitchTests.E) -> () {
|
|
func enumSwitchTest1(_ e: borrowing EnumSwitchTests.E) {
|
|
switch consume e {
|
|
case .first:
|
|
break
|
|
case .second(let x):
|
|
borrowVal(x)
|
|
break
|
|
case .third(let y):
|
|
borrowVal(y)
|
|
break
|
|
case .fourth where booleanGuard:
|
|
break
|
|
case .fourth(.lhs(let lhs)):
|
|
borrowVal(lhs)
|
|
break
|
|
case .fourth(.rhs(let rhs)):
|
|
consumeVal(rhs)
|
|
break
|
|
}
|
|
}
|
|
|
|
//////////////////////
|
|
// Global Addr Test //
|
|
//////////////////////
|
|
|
|
// Make sure that we emit a new global_addr for each use.
|
|
// CHECK-LABEL: sil hidden [ossa] @$s8moveonly16testGlobalBorrowyyF : $@convention(thin) () -> () {
|
|
// CHECK: [[GLOBAL:%.*]] = global_addr @$s8moveonly9varGlobalAA16NonTrivialStructVvp :
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [dynamic] [[GLOBAL]]
|
|
// CHECK: [[MARKED_GLOBAL:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[ACCESS]]
|
|
// CHECK: [[LOADED_VAL:%.*]] = load [copy] [[MARKED_GLOBAL]] : $*NonTrivialStruct
|
|
// CHECK: apply {{%.*}}([[LOADED_VAL]])
|
|
// CHECK: destroy_value [[LOADED_VAL]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
//
|
|
// CHECK: [[GLOBAL:%.*]] = global_addr @$s8moveonly9varGlobalAA16NonTrivialStructVvp :
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [dynamic] [[GLOBAL]]
|
|
// CHECK: [[MARKED_GLOBAL:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[ACCESS]]
|
|
// CHECK: [[GEP:%.*]] = struct_element_addr [[MARKED_GLOBAL]]
|
|
// CHECK: [[LOADED_VAL:%.*]] = load [copy] [[GEP]] : $*NonTrivialStruct2
|
|
// CHECK: apply {{%.*}}([[LOADED_VAL]])
|
|
// CHECK: destroy_value [[LOADED_VAL]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
//
|
|
// CHECK: [[GLOBAL:%.*]] = global_addr @$s8moveonly9letGlobalAA16NonTrivialStructVvp :
|
|
// CHECK: [[MARKED_GLOBAL:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[GLOBAL]]
|
|
// CHECK: [[LOADED_VAL:%.*]] = load [copy] [[MARKED_GLOBAL]] : $*NonTrivialStruct
|
|
// CHECK: apply {{%.*}}([[LOADED_VAL]])
|
|
// CHECK: destroy_value [[LOADED_VAL]]
|
|
//
|
|
// CHECK: [[GLOBAL:%.*]] = global_addr @$s8moveonly9letGlobalAA16NonTrivialStructVvp :
|
|
// CHECK: [[MARKED_GLOBAL:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[GLOBAL]]
|
|
// CHECK: [[LOADED_VAL:%.*]] = load_borrow [[MARKED_GLOBAL]] : $*NonTrivialStruct
|
|
// CHECK: [[LOADED_GEP:%.*]] = struct_extract [[LOADED_VAL]] : $NonTrivialStruct, #NonTrivialStruct.nonTrivialStruct2
|
|
// CHECK: apply {{%.*}}([[LOADED_GEP]])
|
|
// CHECK: end_borrow [[LOADED_VAL]]
|
|
// CHECK: } // end sil function '$s8moveonly16testGlobalBorrowyyF'
|
|
func testGlobalBorrow() {
|
|
borrowVal(varGlobal)
|
|
borrowVal(varGlobal.nonTrivialStruct2)
|
|
borrowVal(letGlobal)
|
|
borrowVal(letGlobal.nonTrivialStruct2)
|
|
}
|
|
|
|
// CHECK-LABEL: sil hidden [ossa] @$s8moveonly17testGlobalConsumeyyF : $@convention(thin) () -> () {
|
|
// CHECK: [[GLOBAL:%.*]] = global_addr @$s8moveonly9varGlobalAA16NonTrivialStructVvp :
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [deinit] [dynamic] [[GLOBAL]]
|
|
// CHECK: [[MARKED_GLOBAL:%.*]] = mark_unresolved_non_copyable_value [assignable_but_not_consumable] [[ACCESS]]
|
|
// CHECK: [[LOADED_VAL:%.*]] = load [take]
|
|
// CHECK: apply {{%.*}}([[LOADED_VAL]])
|
|
// CHECK: end_access [[ACCESS]]
|
|
//
|
|
// CHECK: [[GLOBAL:%.*]] = global_addr @$s8moveonly9varGlobalAA16NonTrivialStructVvp :
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [deinit] [dynamic] [[GLOBAL]]
|
|
// CHECK: [[MARKED_GLOBAL:%.*]] = mark_unresolved_non_copyable_value [assignable_but_not_consumable] [[ACCESS]]
|
|
// CHECK: [[GEP:%.*]] = struct_element_addr [[MARKED_GLOBAL]]
|
|
// CHECK: [[LOADED_VAL:%.*]] = load [take] [[GEP]]
|
|
// CHECK: apply {{%.*}}([[LOADED_VAL]])
|
|
// CHECK: end_access [[ACCESS]]
|
|
//
|
|
// CHECK: [[GLOBAL:%.*]] = global_addr @$s8moveonly9letGlobalAA16NonTrivialStructVvp :
|
|
// CHECK: [[MARKED_GLOBAL:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[GLOBAL]]
|
|
// CHECK: [[LOADED_VAL:%.*]] = load [copy] [[MARKED_GLOBAL]]
|
|
// CHECK: apply {{%.*}}([[LOADED_VAL]])
|
|
//
|
|
// CHECK: [[GLOBAL:%.*]] = global_addr @$s8moveonly9letGlobalAA16NonTrivialStructVvp :
|
|
// CHECK: [[MARKED_GLOBAL:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[GLOBAL]]
|
|
// CHECK: [[LOADED_VAL:%.*]] = load_borrow [[MARKED_GLOBAL]]
|
|
// CHECK: [[LOADED_GEP:%.*]] = struct_extract [[LOADED_VAL]]
|
|
// CHECK: [[LOADED_GEP_COPY:%.*]] = copy_value [[LOADED_GEP]]
|
|
// CHECK: apply {{%.*}}([[LOADED_GEP_COPY]])
|
|
// CHECK: end_borrow [[LOADED_VAL]]
|
|
//
|
|
// CHECK: } // end sil function '$s8moveonly17testGlobalConsumeyyF'
|
|
func testGlobalConsume() {
|
|
consumeVal(varGlobal)
|
|
consumeVal(varGlobal.nonTrivialStruct2)
|
|
consumeVal(letGlobal)
|
|
consumeVal(letGlobal.nonTrivialStruct2)
|
|
}
|
|
|
|
// CHECK-LABEL: sil hidden [ossa] @$s8moveonly16testGlobalAssignyyF : $@convention(thin) () -> () {
|
|
// CHECK: [[GLOBAL:%.*]] = global_addr @$s8moveonly9varGlobalAA16NonTrivialStructVvp :
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [modify] [dynamic] [[GLOBAL]]
|
|
// CHECK: [[MARKED_GLOBAL:%.*]] = mark_unresolved_non_copyable_value [assignable_but_not_consumable] [[ACCESS]]
|
|
// CHECK: assign {{%.*}} to [[MARKED_GLOBAL]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
//
|
|
// CHECK: [[GLOBAL:%.*]] = global_addr @$s8moveonly9varGlobalAA16NonTrivialStructVvp :
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [modify] [dynamic] [[GLOBAL]]
|
|
// CHECK: [[MARKED_GLOBAL:%.*]] = mark_unresolved_non_copyable_value [assignable_but_not_consumable] [[ACCESS]]
|
|
// CHECK: assign {{%.*}} to [[MARKED_GLOBAL]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
//
|
|
// CHECK: [[GLOBAL:%.*]] = global_addr @$s8moveonly9varGlobalAA16NonTrivialStructVvp :
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [modify] [dynamic] [[GLOBAL]]
|
|
// CHECK: [[MARKED_GLOBAL:%.*]] = mark_unresolved_non_copyable_value [assignable_but_not_consumable] [[ACCESS]]
|
|
// CHECK: [[GEP:%.*]] = struct_element_addr [[MARKED_GLOBAL]]
|
|
// CHECK: assign {{%.*}} to [[GEP]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
//
|
|
// CHECK: [[GLOBAL:%.*]] = global_addr @$s8moveonly9varGlobalAA16NonTrivialStructVvp :
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [modify] [dynamic] [[GLOBAL]]
|
|
// CHECK: [[MARKED_GLOBAL:%.*]] = mark_unresolved_non_copyable_value [assignable_but_not_consumable] [[ACCESS]]
|
|
// CHECK: [[GEP:%.*]] = struct_element_addr [[MARKED_GLOBAL]]
|
|
// CHECK: assign {{%.*}} to [[GEP]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: } // end sil function '$s8moveonly16testGlobalAssignyyF'
|
|
func testGlobalAssign() {
|
|
varGlobal = NonTrivialStruct()
|
|
varGlobal = NonTrivialStruct()
|
|
varGlobal.nonTrivialStruct2 = NonTrivialStruct2()
|
|
varGlobal.nonTrivialStruct2 = NonTrivialStruct2()
|
|
}
|
|
|
|
/////////////////////////////////
|
|
// MARK: Closure Capture Tests //
|
|
/////////////////////////////////
|
|
|
|
// Make sure that we insert a mark_unresolved_non_copyable_value on the capture value.
|
|
// CHECK-LABEL: sil hidden [ossa] @$s8moveonly49checkMarkUnresolvedNonCopyableValueInstOnCaptured1xyAA2FDVn_tF : $@convention(thin) (@owned FD) -> () {
|
|
// CHECK: bb0([[ARG:%.*]] : @owned
|
|
// CHECK: [[BOX:%.*]] = alloc_box
|
|
// CHECK: [[PROJECT:%.*]] = project_box [[BOX]]
|
|
// CHECK: store [[ARG]] to [init] [[PROJECT]]
|
|
//
|
|
// CHECK: [[FN:%.*]] = function_ref @$s8moveonly49checkMarkUnresolvedNonCopyableValueInstOnCaptured1xyAA2FDVn_tFyyXEfU_ : $@convention(thin) @substituted <τ_0_0> (@guaranteed FD) -> @out τ_0_0 for <()>
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[PROJECT]]
|
|
// CHECK: [[VALUE:%.*]] = load [copy] [[MARK]]
|
|
// CHECK: [[CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[FN]]([[VALUE]])
|
|
// CHECK: } // end sil function '$s8moveonly49checkMarkUnresolvedNonCopyableValueInstOnCaptured1xyAA2FDVn_tF'
|
|
func checkMarkUnresolvedNonCopyableValueInstOnCaptured(x: __owned FD) {
|
|
func clodger<T>(_: () -> T) {}
|
|
clodger({ consumeVal(x) })
|
|
}
|
|
|
|
//////////////////
|
|
// Empty Struct //
|
|
//////////////////
|
|
|
|
struct EmptyStruct: ~Copyable {
|
|
// Make sure we explicitly initialize empty struct as appropriate despite the
|
|
// fact we do not have any fields.
|
|
//
|
|
// CHECK-LABEL: sil hidden [ossa] @$s8moveonly11EmptyStructVACycfC : $@convention(method) (@thin EmptyStruct.Type) -> @owned EmptyStruct {
|
|
// CHECK: [[BOX:%.*]] = alloc_box ${ var EmptyStruct }, var, name "self"
|
|
// CHECK: [[MARKED_UNINIT:%.*]] = mark_uninitialized [rootself] [[BOX]]
|
|
// CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [var_decl] [[MARKED_UNINIT]]
|
|
// CHECK: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]]
|
|
// CHECK: [[STRUCT:%.*]] = struct $EmptyStruct ()
|
|
// CHECK: store [[STRUCT]] to [init] [[PROJECT]]
|
|
// CHECK: [[MV_CHECK:%.*]] = mark_unresolved_non_copyable_value [assignable_but_not_consumable] [[PROJECT]]
|
|
// CHECK: [[LOADED_VALUE:%.*]] = load [copy] [[MV_CHECK]]
|
|
// CHECK: destroy_value [[MARKED_UNINIT]]
|
|
// CHECK: return [[LOADED_VALUE]]
|
|
// CHECK: } // end sil function '$s8moveonly11EmptyStructVACycfC'
|
|
init() {
|
|
}
|
|
}
|
|
|
|
///////////////////////////////
|
|
// Conditionally Initialized //
|
|
///////////////////////////////
|
|
|
|
// CHECK: sil hidden [ossa] @$s8moveonly31testConditionallyInitializedLetyyF : $@convention(thin) () -> () {
|
|
// CHECK: [[BOX:%.*]] = alloc_box ${ let NonTrivialStruct }, let, name "x"
|
|
// CHECK: [[MARK_UNINIT:%.*]] = mark_uninitialized [var] [[BOX]]
|
|
// CHECK: [[BORROW:%.*]] = begin_borrow [lexical] [var_decl] [[MARK_UNINIT]]
|
|
// CHECK: [[PROJECT:%.*]] = project_box [[BORROW]]
|
|
// CHECK: cond_br {{%.*}}, [[LHS_BB:bb[0-9]+]], [[RHS_BB:bb[0-9]+]]
|
|
//
|
|
// CHECK: [[LHS_BB]]:
|
|
// CHECK: [[MARKED:%.*]] = mark_unresolved_non_copyable_value [assignable_but_not_consumable] [[PROJECT]]
|
|
// CHECK: assign {{%.*}} to [[MARKED]]
|
|
// CHECK: br [[CONT_BB:bb[0-9]+]]
|
|
//
|
|
// CHECK: [[RHS_BB]]:
|
|
// CHECK: [[MARKED:%.*]] = mark_unresolved_non_copyable_value [assignable_but_not_consumable] [[PROJECT]]
|
|
// CHECK: assign {{%.*}} to [[MARKED]]
|
|
// CHECK: br [[CONT_BB:bb[0-9]+]]
|
|
//
|
|
// CHECK: [[CONT_BB]]:
|
|
// CHECK: [[MARKED:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[PROJECT]]
|
|
// CHECK: [[BORROW_LOAD:%.*]] = load [copy] [[MARKED]]
|
|
// CHECK: apply {{%.*}}([[BORROW_LOAD]])
|
|
// CHECK: destroy_value [[BORROW_LOAD]]
|
|
// CHECK: [[MARKED:%.*]] = mark_unresolved_non_copyable_value [assignable_but_not_consumable] [[PROJECT]]
|
|
// CHECK: [[TAKE_LOAD:%.*]] = load [take] [[MARKED]]
|
|
// CHECK: apply {{%.*}}([[TAKE_LOAD]])
|
|
// CHECK: } // end sil function '$s8moveonly31testConditionallyInitializedLetyyF'
|
|
func testConditionallyInitializedLet() {
|
|
let x: NonTrivialStruct
|
|
|
|
if bool {
|
|
x = NonTrivialStruct()
|
|
} else {
|
|
x = NonTrivialStruct()
|
|
}
|
|
|
|
borrowVal(x)
|
|
consumeVal(x)
|
|
}
|
|
|
|
////////////////////////
|
|
// MARK: Setter Tests //
|
|
////////////////////////
|
|
|
|
struct AddressOnlySetterTester : ~Copyable {
|
|
var a: AddressOnlyProtocol {
|
|
get { fatalError() }
|
|
|
|
// CHECK-LABEL: sil hidden [ossa] @$s8moveonly23AddressOnlySetterTesterV1aAA0bC8ProtocolVvs : $@convention(method) (@in AddressOnlyProtocol, @inout AddressOnlySetterTester) -> () {
|
|
// CHECK: bb0([[IN_ARG:%.*]] : $*AddressOnlyProtocol, [[SELF_INOUT_ARG:%.*]] : $*AddressOnlySetterTester):
|
|
// CHECK: mark_unresolved_non_copyable_value [consumable_and_assignable] [[IN_ARG]]
|
|
// CHECK: mark_unresolved_non_copyable_value [consumable_and_assignable] [[SELF_INOUT_ARG]]
|
|
// CHECK: } // end sil function '$s8moveonly23AddressOnlySetterTesterV1aAA0bC8ProtocolVvs'
|
|
set { fatalError() }
|
|
}
|
|
}
|
|
|
|
public class NonFinalClassTest {
|
|
// CHECK: sil hidden [transparent] [ossa] @$s8moveonly17NonFinalClassTestC1xAA19AddressOnlyProtocolVvs : $@convention(method) (@in AddressOnlyProtocol, @guaranteed NonFinalClassTest) -> () {
|
|
// CHECK: bb0([[INPUT:%.*]] : $*AddressOnlyProtocol, [[SELF:%.*]] : @guaranteed
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[INPUT]]
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $AddressOnlyProtocol
|
|
// CHECK: copy_addr [[MARK]] to [init] [[TEMP]]
|
|
// CHECK: [[REF:%.*]] = ref_element_addr [[SELF]]
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [modify] [dynamic] [[REF]]
|
|
// CHECK: [[MARK2:%.*]] = mark_unresolved_non_copyable_value [assignable_but_not_consumable] [[ACCESS]]
|
|
// CHECK: copy_addr [take] [[TEMP]] to [[MARK2]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: dealloc_stack [[TEMP]]
|
|
// CHECK: destroy_addr [[MARK]]
|
|
// CHECK: } // end sil function '$s8moveonly17NonFinalClassTestC1xAA19AddressOnlyProtocolVvs'
|
|
var x: AddressOnlyProtocol
|
|
init(y: consuming AddressOnlyProtocol) { self.x = y }
|
|
}
|
|
|
|
/////////////////////
|
|
// MARK: Subscript //
|
|
/////////////////////
|
|
|
|
// MARK: Getter Only
|
|
|
|
public struct LoadableSubscriptGetOnlyTester : ~Copyable {
|
|
subscript(_ i: Int) -> AddressOnlyProtocol {
|
|
get {
|
|
fatalError()
|
|
}
|
|
}
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @$s8moveonly047testSubscriptGetOnly_BaseLoadable_ResultAddressE4_VaryyF : $@convention(thin) () -> () {
|
|
// CHECK: [[BOX:%.*]] = alloc_box $
|
|
// CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [var_decl] [[BOX]]
|
|
// CHECK: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]]
|
|
//
|
|
// The get call
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]]
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[ACCESS]]
|
|
// CHECK: [[LOAD_BORROW:%.*]] = load_borrow [unchecked] [[MARK]]
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $AddressOnlyProtocol
|
|
// CHECK: [[TEMP_MARK:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP]]
|
|
// CHECK: apply {{%.*}}([[TEMP_MARK]], {{%.*}}, [[LOAD_BORROW]])
|
|
// CHECK: end_borrow [[LOAD_BORROW]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: apply {{%.*}}([[TEMP_MARK]])
|
|
// CHECK: destroy_addr [[TEMP_MARK]]
|
|
//
|
|
// Test the assignment
|
|
// CHECK: [[M2_BOX:%.*]] = alloc_box ${
|
|
// CHECK: [[M2_BORROW:%.*]] = begin_borrow [lexical] [var_decl] [[M2_BOX]]
|
|
// CHECK: [[M2_PROJECT:%.*]] = project_box [[M2_BORROW]]
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]]
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[ACCESS]]
|
|
// CHECK: [[LOAD:%.*]] = load_borrow [unchecked] [[MARK]]
|
|
// CHECK: [[STACK_ALLOC:%.*]] = alloc_stack $AddressOnlyProtocol
|
|
// CHECK: [[M_STACK_ALLOC:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[STACK_ALLOC]]
|
|
// CHECK: apply {{%.*}}([[M_STACK_ALLOC]], {{%.*}}, [[LOAD]])
|
|
// CHECK: end_borrow [[LOAD]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: copy_addr [take] [[M_STACK_ALLOC]] to [init] [[M2_PROJECT]]
|
|
// CHECK: dealloc_stack [[STACK_ALLOC]]
|
|
// CHECK: [[M2_MARK:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[M2_PROJECT]]
|
|
// CHECK: end_borrow [[M2_BORROW]]
|
|
// CHECK: destroy_value [[M2_BOX]]
|
|
// CHECK: } // end sil function '$s8moveonly047testSubscriptGetOnly_BaseLoadable_ResultAddressE4_VaryyF'
|
|
public func testSubscriptGetOnly_BaseLoadable_ResultAddressOnly_Var() {
|
|
var m = LoadableSubscriptGetOnlyTester()
|
|
m = LoadableSubscriptGetOnlyTester()
|
|
m[0].nonMutatingFunc()
|
|
let m2 = m[0]
|
|
_ = m2
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @$s8moveonly047testSubscriptGetOnly_BaseLoadable_ResultAddressE4_LetyyF : $@convention(thin) () -> () {
|
|
// CHECK: [[BOX:%.*]] = alloc_box $
|
|
// CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [var_decl] [[BOX]]
|
|
// CHECK: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]]
|
|
//
|
|
// The get call
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[PROJECT]]
|
|
// CHECK: [[LOAD_BORROW:%.*]] = load_borrow [[MARK]]
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $AddressOnlyProtocol
|
|
// CHECK: [[TEMP_MARK:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP]]
|
|
// CHECK: apply {{%.*}}([[TEMP_MARK]], {{%.*}}, [[LOAD_BORROW]])
|
|
// CHECK: apply {{%.*}}([[TEMP_MARK]])
|
|
// CHECK: destroy_addr [[TEMP_MARK]]
|
|
// CHECK: end_borrow [[LOAD_BORROW]]
|
|
// CHECK: } // end sil function '$s8moveonly047testSubscriptGetOnly_BaseLoadable_ResultAddressE4_LetyyF'
|
|
public func testSubscriptGetOnly_BaseLoadable_ResultAddressOnly_Let() {
|
|
let m = LoadableSubscriptGetOnlyTester()
|
|
m[0].nonMutatingFunc()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @$s8moveonly047testSubscriptGetOnly_BaseLoadable_ResultAddressE6_InOut1myAA0gcdE6TesterVz_tF : $@convention(thin) (@inout LoadableSubscriptGetOnlyTester) -> () {
|
|
// CHECK: bb0([[ARG:%.*]] : $*
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[ARG]]
|
|
//
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[MARK]]
|
|
// CHECK: [[LOAD_BORROW:%.*]] = load_borrow [unchecked] [[ACCESS]]
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $AddressOnlyProtocol
|
|
// CHECK: [[TEMP_MARK:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP]]
|
|
// CHECK: apply {{%.*}}([[TEMP_MARK]], {{%.*}}, [[LOAD_BORROW]])
|
|
// CHECK: end_borrow [[LOAD_BORROW]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: apply {{%.*}}([[TEMP_MARK]])
|
|
// CHECK: destroy_addr [[TEMP_MARK]]
|
|
// CHECK: } // end sil function '$s8moveonly047testSubscriptGetOnly_BaseLoadable_ResultAddressE6_InOut1myAA0gcdE6TesterVz_tF'
|
|
public func testSubscriptGetOnly_BaseLoadable_ResultAddressOnly_InOut(m: inout LoadableSubscriptGetOnlyTester) {
|
|
m[0].nonMutatingFunc()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @$s8moveonly047testSubscriptGetOnly_BaseLoadable_ResultAddressE7_GlobalyyF : $@convention(thin) () -> () {
|
|
// CHECK: [[GLOBAL_ADDR:%.*]] = global_addr @$s8moveonly36globalLoadableSubscriptGetOnlyTesterAA0cdefG0Vvp :
|
|
//
|
|
// The get call
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [dynamic] [[GLOBAL_ADDR]]
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[ACCESS]]
|
|
// CHECK: [[LOAD_BORROW:%.*]] = load_borrow [unchecked] [[MARK]]
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $AddressOnlyProtocol
|
|
// CHECK: [[TEMP_MARK:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP]]
|
|
// CHECK: apply {{%.*}}([[TEMP_MARK]], {{%.*}}, [[LOAD_BORROW]])
|
|
// CHECK: end_borrow [[LOAD_BORROW]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: apply {{%.*}}([[TEMP_MARK]])
|
|
// CHECK: destroy_addr [[TEMP_MARK]]
|
|
// CHECK: } // end sil function '$s8moveonly047testSubscriptGetOnly_BaseLoadable_ResultAddressE7_GlobalyyF'
|
|
var globalLoadableSubscriptGetOnlyTester = LoadableSubscriptGetOnlyTester()
|
|
public func testSubscriptGetOnly_BaseLoadable_ResultAddressOnly_Global() {
|
|
globalLoadableSubscriptGetOnlyTester[0].nonMutatingFunc()
|
|
}
|
|
|
|
// Make sure that we get the same behavior when we access through another noncopyable struct.
|
|
public struct LoadableSubscriptGetOnlyTesterNonCopyableStructParent : ~Copyable {
|
|
var tester = LoadableSubscriptGetOnlyTester()
|
|
var computedTester: LoadableSubscriptGetOnlyTester { fatalError() }
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @$s8moveonly077testSubscriptGetOnlyThroughNonCopyableParentStruct_BaseLoadable_ResultAddressE4_VaryyF : $@convention(thin) () -> () {
|
|
// CHECK: [[BOX:%.*]] = alloc_box $
|
|
// CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [var_decl] [[BOX]]
|
|
// CHECK: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]]
|
|
//
|
|
// The first get call
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]]
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[ACCESS]]
|
|
// CHECK: [[GEP:%.*]] = struct_element_addr [[MARK]]
|
|
// CHECK: [[LOAD_BORROW:%.*]] = load_borrow [unchecked] [[GEP]]
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $AddressOnlyProtocol
|
|
// CHECK: [[TEMP_MARK:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP]]
|
|
// CHECK: apply {{%.*}}([[TEMP_MARK]], {{%.*}}, [[LOAD_BORROW]])
|
|
// CHECK: end_borrow [[LOAD_BORROW]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: apply {{%.*}}([[TEMP_MARK]])
|
|
// CHECK: destroy_addr [[TEMP_MARK]]
|
|
//
|
|
// The second get call.
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]]
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[ACCESS]]
|
|
// CHECK: [[LOAD_BORROW:%.*]] = load_borrow [unchecked] [[MARK]]
|
|
// CHECK: [[VALUE:%.*]] = apply {{%.*}}([[LOAD_BORROW]])
|
|
//
|
|
// CHECK: [[BORROWED_VALUE:%.*]] = begin_borrow [[VALUE]]
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $AddressOnlyProtocol
|
|
// CHECK: [[TEMP_MARK:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP]]
|
|
// CHECK: apply {{%.*}}([[TEMP_MARK]], {{%.*}}, [[BORROWED_VALUE]])
|
|
// CHECK: end_borrow [[BORROWED_VALUE]]
|
|
// CHECK: end_borrow [[LOAD_BORROW]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: apply {{%.*}}([[TEMP_MARK]])
|
|
// CHECK: destroy_addr [[TEMP_MARK]]
|
|
// CHECK: destroy_value [[VALUE]]
|
|
// } // end sil function '$s8moveonly077testSubscriptGetOnlyThroughNonCopyableParentStruct_BaseLoadable_ResultAddressE4_VaryyF'
|
|
public func testSubscriptGetOnlyThroughNonCopyableParentStruct_BaseLoadable_ResultAddressOnly_Var() {
|
|
var m = LoadableSubscriptGetOnlyTesterNonCopyableStructParent()
|
|
m = LoadableSubscriptGetOnlyTesterNonCopyableStructParent()
|
|
m.tester[0].nonMutatingFunc()
|
|
m.computedTester[0].nonMutatingFunc()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @$s8moveonly077testSubscriptGetOnlyThroughNonCopyableParentStruct_BaseLoadable_ResultAddressE4_LetyyF : $@convention(thin) () -> () {
|
|
// CHECK: [[BOX:%.*]] = alloc_box ${ let L
|
|
// CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [var_decl] [[BOX]]
|
|
// CHECK: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]]
|
|
//
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[PROJECT]]
|
|
// CHECK: [[LOAD:%.*]] = load_borrow [[MARK]]
|
|
// CHECK: [[EXT:%.*]] = struct_extract [[LOAD]]
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $AddressOnlyProtocol
|
|
// CHECK: [[TEMP_MARK:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP]]
|
|
// CHECK: apply {{%.*}}([[TEMP_MARK]], {{%.*}}, [[EXT]])
|
|
// CHECK: apply {{%.*}}([[TEMP_MARK]])
|
|
// CHECK: destroy_addr [[TEMP_MARK]]
|
|
// CHECK: end_borrow [[LOAD]]
|
|
// CHECK: } // end sil function '$s8moveonly077testSubscriptGetOnlyThroughNonCopyableParentStruct_BaseLoadable_ResultAddressE4_LetyyF'
|
|
public func testSubscriptGetOnlyThroughNonCopyableParentStruct_BaseLoadable_ResultAddressOnly_Let() {
|
|
let m = LoadableSubscriptGetOnlyTesterNonCopyableStructParent()
|
|
m.tester[0].nonMutatingFunc()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @$s8moveonly077testSubscriptGetOnlyThroughNonCopyableParentStruct_BaseLoadable_ResultAddressE6_InOut1myAA0lcde6TesterghjI0Vz_tF : $@convention(thin) (@inout LoadableSubscriptGetOnlyTesterNonCopyableStructParent) -> () {
|
|
// CHECK: bb0([[ARG:%.*]] :
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[ARG]]
|
|
//
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[MARK]]
|
|
// CHECK: [[GEP:%.*]] = struct_element_addr [[ACCESS]]
|
|
// CHECK: [[LOAD:%.*]] = load_borrow [unchecked] [[GEP]]
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $AddressOnlyProtocol
|
|
// CHECK: [[TEMP_MARK:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP]]
|
|
// CHECK: apply {{%.*}}([[TEMP_MARK]], {{%.*}}, [[LOAD]])
|
|
// CHECK: end_borrow [[LOAD]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: apply {{%.*}}([[TEMP_MARK]])
|
|
// CHECK: destroy_addr [[TEMP_MARK]]
|
|
// CHECK: } // end sil function '$s8moveonly077testSubscriptGetOnlyThroughNonCopyableParentStruct_BaseLoadable_ResultAddressE6_InOut1myAA0lcde6TesterghjI0Vz_tF'
|
|
public func testSubscriptGetOnlyThroughNonCopyableParentStruct_BaseLoadable_ResultAddressOnly_InOut(m: inout LoadableSubscriptGetOnlyTesterNonCopyableStructParent) {
|
|
m.tester[0].nonMutatingFunc()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @$s8moveonly077testSubscriptGetOnlyThroughNonCopyableParentStruct_BaseLoadable_ResultAddressE7_GlobalyyF : $@convention(thin) () -> () {
|
|
// CHECK: [[GLOBAL:%.*]] = global_addr @$s8moveonly59globalLoadableSubscriptGetOnlyTesterNonCopyableStructParentAA0cdefghijK0Vvp
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [dynamic] [[GLOBAL]]
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[ACCESS]]
|
|
// CHECK: [[GEP:%.*]] = struct_element_addr [[MARK]]
|
|
// CHECK: [[LOAD:%.*]] = load_borrow [unchecked] [[GEP]]
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $AddressOnlyProtocol
|
|
// CHECK: [[TEMP_MARK:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP]]
|
|
// CHECK: apply {{%.*}}([[TEMP_MARK]], {{%.*}}, [[LOAD]])
|
|
// CHECK: end_borrow [[LOAD]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: apply {{%.*}}([[TEMP_MARK]])
|
|
// CHECK: destroy_addr [[TEMP_MARK]]
|
|
// CHECK: } // end sil function '$s8moveonly077testSubscriptGetOnlyThroughNonCopyableParentStruct_BaseLoadable_ResultAddressE7_GlobalyyF'
|
|
var globalLoadableSubscriptGetOnlyTesterNonCopyableStructParent = LoadableSubscriptGetOnlyTesterNonCopyableStructParent()
|
|
public func testSubscriptGetOnlyThroughNonCopyableParentStruct_BaseLoadable_ResultAddressOnly_Global() {
|
|
globalLoadableSubscriptGetOnlyTesterNonCopyableStructParent.tester[0].nonMutatingFunc()
|
|
}
|
|
|
|
public class LoadableSubscriptGetOnlyTesterClassParent {
|
|
var tester = LoadableSubscriptGetOnlyTester()
|
|
var computedTester: LoadableSubscriptGetOnlyTester { fatalError() }
|
|
var testerParent = LoadableSubscriptGetOnlyTesterNonCopyableStructParent()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @$s8moveonly065testSubscriptGetOnlyThroughParentClass_BaseLoadable_ResultAddressE4_VaryyF : $@convention(thin) () -> () {
|
|
// CHECK: [[BOX:%.*]] = alloc_box $
|
|
// CHECK: [[BORROW:%.*]] = begin_borrow [lexical] [var_decl] [[BOX]]
|
|
// CHECK: [[PROJECT:%.*]] = project_box [[BORROW]]
|
|
//
|
|
// First read.
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]]
|
|
// CHECK: [[COPYABLE_CLASS:%.*]] = load [copy] [[ACCESS]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: [[BORROW_COPYABLE_CLASS:%.*]] = begin_borrow [[COPYABLE_CLASS]]
|
|
// CHECK: ([[CORO_RESULT_ORIG:%.*]], [[CORO_TOKEN:%.*]]) = begin_apply {{%.*}}([[BORROW_COPYABLE_CLASS]])
|
|
// CHECK: [[CORO_RESULT_CP:%.*]] = copy_value [[CORO_RESULT_ORIG]]
|
|
// CHECK: [[CORO_RESULT_MK:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[CORO_RESULT_CP]]
|
|
// CHECK: [[CORO_RESULT:%.*]] = begin_borrow [[CORO_RESULT_MK]]
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $LoadableSubscriptGetOnlyTester
|
|
// CHECK: [[TEMP_MARK:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[TEMP]]
|
|
// CHECK: [[TEMP_MARK_BORROW:%.*]] = store_borrow [[CORO_RESULT]] to [[TEMP_MARK]]
|
|
// CHECK: [[LOAD:%.*]] = load_borrow [unchecked] [[TEMP_MARK_BORROW]]
|
|
// CHECK: [[TEMP2:%.*]] = alloc_stack $
|
|
// CHECK: [[TEMP2_MARK:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP2]]
|
|
// CHECK: apply {{%.*}}([[TEMP2_MARK]], {{%.*}}, [[LOAD]])
|
|
// CHECK: end_borrow [[LOAD]]
|
|
// CHECK: end_apply [[CORO_TOKEN]]
|
|
// CHECK: apply {{%.*}}([[TEMP2_MARK]])
|
|
// CHECK: destroy_addr [[TEMP2_MARK]]
|
|
//
|
|
// Second read.
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]]
|
|
// CHECK: [[COPYABLE_CLASS:%.*]] = load [copy] [[ACCESS]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: [[BORROW_COPYABLE_CLASS:%.*]] = begin_borrow [[COPYABLE_CLASS]]
|
|
// CHECK: ([[CORO_RESULT_ORIG:%.*]], [[CORO_TOKEN:%.*]]) = begin_apply {{%.*}}([[BORROW_COPYABLE_CLASS]])
|
|
// CHECK: [[CORO_RESULT_CP:%.*]] = copy_value [[CORO_RESULT_ORIG]]
|
|
// CHECK: [[CORO_RESULT_MK:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[CORO_RESULT_CP]]
|
|
// CHECK: [[CORO_RESULT:%.*]] = begin_borrow [[CORO_RESULT_MK]]
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $LoadableSubscriptGetOnlyTester
|
|
// CHECK: [[TEMP_MARK:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[TEMP]]
|
|
// CHECK: [[TEMP_MARK_BORROW:%.*]] = store_borrow [[CORO_RESULT]] to [[TEMP_MARK]]
|
|
// CHECK: [[GEP:%.*]] = struct_element_addr [[TEMP_MARK_BORROW]]
|
|
// CHECK: [[LOAD:%.*]] = load_borrow [unchecked] [[GEP]]
|
|
// CHECK: [[TEMP2:%.*]] = alloc_stack $
|
|
// CHECK: [[TEMP2_MARK:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP2]]
|
|
// CHECK: apply {{%.*}}([[TEMP2_MARK]], {{%.*}}, [[LOAD]])
|
|
// CHECK: end_borrow [[LOAD]]
|
|
// CHECK: end_apply [[CORO_TOKEN]]
|
|
// CHECK: apply {{%.*}}([[TEMP2_MARK]])
|
|
// CHECK: destroy_addr [[TEMP2_MARK]]
|
|
//
|
|
// Third read.
|
|
//
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]]
|
|
// CHECK: [[LOAD:%.*]] = load_borrow [unchecked] [[ACCESS]]
|
|
// CHECK: ([[CORO_RESULT_ORIG:%.*]], [[CORO_TOKEN:%.*]]) = begin_apply {{%.*}}([[LOAD]])
|
|
// CHECK: [[CORO_RESULT_CP:%.*]] = copy_value [[CORO_RESULT_ORIG]]
|
|
// CHECK: [[CORO_RESULT_MK:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[CORO_RESULT_CP]]
|
|
// CHECK: [[CORO_RESULT:%.*]] = begin_borrow [[CORO_RESULT_MK]]
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $
|
|
// CHECK: [[TEMP_MARK:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP]]
|
|
// CHECK: apply {{%.*}}([[TEMP_MARK]], {{%.*}}, [[CORO_RESULT]])
|
|
// CHECK: end_apply [[CORO_TOKEN]]
|
|
// CHECK: end_borrow [[LOAD]]
|
|
// CHECK: apply {{%.*}}([[TEMP_MARK]])
|
|
// CHECK: destroy_addr [[TEMP_MARK]]
|
|
|
|
// CHECK: } // end sil function '$s8moveonly065testSubscriptGetOnlyThroughParentClass_BaseLoadable_ResultAddressE4_VaryyF'
|
|
public func testSubscriptGetOnlyThroughParentClass_BaseLoadable_ResultAddressOnly_Var() {
|
|
var m = LoadableSubscriptGetOnlyTesterClassParent()
|
|
m = LoadableSubscriptGetOnlyTesterClassParent()
|
|
m.tester[0].nonMutatingFunc()
|
|
m.testerParent.tester[0].nonMutatingFunc()
|
|
m.computedTester[0].nonMutatingFunc()
|
|
}
|
|
|
|
// MARK: Getter + Setter.
|
|
// This is different since adding a setter changes how we codegen.
|
|
|
|
public struct LoadableSubscriptGetSetTester : ~Copyable {
|
|
subscript(_ i: Int) -> AddressOnlyProtocol {
|
|
get {
|
|
fatalError()
|
|
}
|
|
set {
|
|
fatalError()
|
|
}
|
|
}
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @$s8moveonly54testSubscriptGetSet_BaseLoadable_ResultAddressOnly_VaryyF : $@convention(thin) () -> () {
|
|
// CHECK: [[BOX:%.*]] = alloc_box $
|
|
// CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [var_decl] [[BOX]]
|
|
// CHECK: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]]
|
|
//
|
|
// The get call
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]]
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[ACCESS]]
|
|
// CHECK: [[LOAD_BORROW:%.*]] = load_borrow [[MARK]]
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $AddressOnlyProtocol
|
|
// CHECK: [[TEMP_MARK:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP]]
|
|
// CHECK: apply {{%.*}}([[TEMP_MARK]], {{%.*}}, [[LOAD_BORROW]])
|
|
// CHECK: end_borrow [[LOAD_BORROW]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: apply {{%.*}}([[TEMP_MARK]])
|
|
// CHECK: destroy_addr [[TEMP_MARK]]
|
|
//
|
|
// The assignment:
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $AddressOnlyProtocol
|
|
// CHECK: [[MARK_TEMP:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]], {{%.*}}) : $@convention(method) (@thin AddressOnlyProtocol.Type) -> @out AddressOnlyProtocol
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[PROJECT]]
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [assignable_but_not_consumable] [[ACCESS]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]], {{%.*}}, [[MARK]])
|
|
// CHECK: end_access [[ACCESS]]
|
|
//
|
|
// The mutating function call.
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[PROJECT]]
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [assignable_but_not_consumable] [[ACCESS]]
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $AddressOnlyProtocol
|
|
// CHECK: [[MARK_TEMP:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP]]
|
|
// CHECK: [[LOAD_BORROW:%.*]] = load_borrow [[MARK]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]], {{%.*}}, [[LOAD_BORROW]])
|
|
// CHECK: end_borrow [[LOAD_BORROW]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]])
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]], {{%.*}}, [[MARK]])
|
|
// CHECK: end_access [[ACCESS]]
|
|
//
|
|
// CHECK: } // end sil function '$s8moveonly54testSubscriptGetSet_BaseLoadable_ResultAddressOnly_VaryyF'
|
|
public func testSubscriptGetSet_BaseLoadable_ResultAddressOnly_Var() {
|
|
var m = LoadableSubscriptGetSetTester()
|
|
m = LoadableSubscriptGetSetTester()
|
|
m[0].nonMutatingFunc()
|
|
m[0] = AddressOnlyProtocol()
|
|
m[0].mutatingFunc()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @$s8moveonly54testSubscriptGetSet_BaseLoadable_ResultAddressOnly_LetyyF : $@convention(thin) () -> () {
|
|
// CHECK: [[BOX:%.*]] = alloc_box $
|
|
// CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [var_decl] [[BOX]]
|
|
// CHECK: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]]
|
|
//
|
|
// The get call
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[PROJECT]]
|
|
// CHECK: [[LOAD_BORROW:%.*]] = load_borrow [[MARK]]
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $AddressOnlyProtocol
|
|
// CHECK: [[MARK_TEMP:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]], {{%.*}}, [[LOAD_BORROW]])
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]])
|
|
// CHECK: destroy_addr [[MARK_TEMP]]
|
|
// CHECK: end_borrow [[LOAD_BORROW]]
|
|
// CHECK: } // end sil function '$s8moveonly54testSubscriptGetSet_BaseLoadable_ResultAddressOnly_LetyyF'
|
|
public func testSubscriptGetSet_BaseLoadable_ResultAddressOnly_Let() {
|
|
let m = LoadableSubscriptGetSetTester()
|
|
m[0].nonMutatingFunc()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @$s8moveonly56testSubscriptGetSet_BaseLoadable_ResultAddressOnly_InOut1myAA0gcdE6TesterVz_tF : $@convention(thin) (@inout LoadableSubscriptGetSetTester) -> () {
|
|
// CHECK: bb0([[ARG:%.*]] : $*
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[ARG]]
|
|
//
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[MARK]]
|
|
// CHECK: [[LOAD_BORROW:%.*]] = load_borrow [[ACCESS]]
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $AddressOnlyProtocol
|
|
// CHECK: [[MARK_TEMP:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]], {{%.*}}, [[LOAD_BORROW]])
|
|
// CHECK: end_borrow [[LOAD_BORROW]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]])
|
|
// CHECK: destroy_addr [[MARK_TEMP]]
|
|
//
|
|
// The assignment:
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $AddressOnlyProtocol
|
|
// CHECK: [[MARK_TEMP:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]], {{%.*}}) : $@convention(method) (@thin AddressOnlyProtocol.Type) -> @out AddressOnlyProtocol
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[MARK]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]], {{%.*}}, [[ACCESS]])
|
|
// CHECK: end_access [[ACCESS]]
|
|
//
|
|
// The mutating function call.
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[MARK]]
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $AddressOnlyProtocol
|
|
// CHECK: [[MARK_TEMP:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP]]
|
|
// CHECK: [[LOAD_BORROW:%.*]] = load_borrow [[ACCESS]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]], {{%.*}}, [[LOAD_BORROW]])
|
|
// CHECK: end_borrow [[LOAD_BORROW]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]])
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]], {{%.*}}, [[ACCESS]])
|
|
// CHECK: end_access [[ACCESS]]
|
|
//
|
|
// CHECK: } // end sil function '$s8moveonly56testSubscriptGetSet_BaseLoadable_ResultAddressOnly_InOut1myAA0gcdE6TesterVz_tF'
|
|
public func testSubscriptGetSet_BaseLoadable_ResultAddressOnly_InOut(m: inout LoadableSubscriptGetSetTester) {
|
|
m[0].nonMutatingFunc()
|
|
m[0] = AddressOnlyProtocol()
|
|
m[0].mutatingFunc()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @$s8moveonly57testSubscriptGetSet_BaseLoadable_ResultAddressOnly_GlobalyyF : $@convention(thin) () -> () {
|
|
// CHECK: [[GLOBAL_ADDR:%.*]] = global_addr @$s8moveonly35globalLoadableSubscriptGetSetTesterAA0cdefG0Vvp
|
|
//
|
|
// The get call
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [dynamic] [[GLOBAL_ADDR]]
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[ACCESS]]
|
|
// CHECK: [[LOAD_BORROW:%.*]] = load_borrow [[MARK]]
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $AddressOnlyProtocol
|
|
// CHECK: [[MARK_TEMP:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]], {{%.*}}, [[LOAD_BORROW]])
|
|
// CHECK: end_borrow [[LOAD_BORROW]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]])
|
|
// CHECK: destroy_addr [[MARK_TEMP]]
|
|
//
|
|
// The assignment:
|
|
// CHECK: [[GLOBAL_ADDR:%.*]] = global_addr @$s8moveonly35globalLoadableSubscriptGetSetTesterAA0cdefG0Vvp
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $AddressOnlyProtocol
|
|
// CHECK: [[MARK_TEMP:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]], {{%.*}}) : $@convention(method) (@thin AddressOnlyProtocol.Type) -> @out AddressOnlyProtocol
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [modify] [dynamic] [[GLOBAL_ADDR]]
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [assignable_but_not_consumable] [[ACCESS]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]], {{%.*}}, [[MARK]])
|
|
// CHECK: end_access [[ACCESS]]
|
|
//
|
|
// The mutating function call.
|
|
// CHECK: [[GLOBAL_ADDR:%.*]] = global_addr @$s8moveonly35globalLoadableSubscriptGetSetTesterAA0cdefG0Vvp
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [modify] [dynamic] [[GLOBAL_ADDR]]
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [assignable_but_not_consumable] [[ACCESS]]
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $AddressOnlyProtocol
|
|
// CHECK: [[MARK_TEMP:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP]]
|
|
// CHECK: [[LOAD_BORROW:%.*]] = load_borrow [[MARK]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]], {{%.*}}, [[LOAD_BORROW]])
|
|
// CHECK: end_borrow [[LOAD_BORROW]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]])
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]], {{%.*}}, [[MARK]])
|
|
// CHECK: end_access [[ACCESS]]
|
|
//
|
|
// CHECK: } // end sil function '$s8moveonly57testSubscriptGetSet_BaseLoadable_ResultAddressOnly_GlobalyyF'
|
|
var globalLoadableSubscriptGetSetTester = LoadableSubscriptGetSetTester()
|
|
public func testSubscriptGetSet_BaseLoadable_ResultAddressOnly_Global() {
|
|
globalLoadableSubscriptGetSetTester[0].nonMutatingFunc()
|
|
globalLoadableSubscriptGetSetTester[0] = AddressOnlyProtocol()
|
|
globalLoadableSubscriptGetSetTester[0].mutatingFunc()
|
|
}
|
|
|
|
// Make sure that we get the same behavior when we access through another noncopyable struct.
|
|
public struct LoadableSubscriptGetSetTesterNonCopyableStructParent : ~Copyable {
|
|
var tester = LoadableSubscriptGetSetTester()
|
|
var computedTester: LoadableSubscriptGetSetTester { fatalError() }
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @$s8moveonly84testSubscriptGetSetThroughNonCopyableParentStruct_BaseLoadable_ResultAddressOnly_VaryyF : $@convention(thin) () -> () {
|
|
// CHECK: [[BOX:%.*]] = alloc_box $
|
|
// CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [var_decl] [[BOX]]
|
|
// CHECK: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]]
|
|
//
|
|
// The first get call
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]]
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[ACCESS]]
|
|
// CHECK: [[GEP:%.*]] = struct_element_addr [[MARK]]
|
|
// CHECK: [[LOAD_BORROW:%.*]] = load_borrow [[GEP]]
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $AddressOnlyProtocol
|
|
// CHECK: [[MARK_TEMP:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]], {{%.*}}, [[LOAD_BORROW]])
|
|
// CHECK: end_borrow [[LOAD_BORROW]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]])
|
|
// CHECK: destroy_addr [[MARK_TEMP]]
|
|
//
|
|
// The mutating call.
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[PROJECT]]
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [assignable_but_not_consumable] [[ACCESS]]
|
|
// CHECK: [[GEP:%.*]] = struct_element_addr [[MARK]]
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $AddressOnlyProtocol
|
|
// CHECK: [[MARK_TEMP:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP]]
|
|
// CHECK: [[LOAD:%.*]] = load_borrow [[GEP]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]], {{%.*}}, [[LOAD]])
|
|
// CHECK: end_borrow [[LOAD]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]])
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]], {{%.*}}, [[GEP]])
|
|
// CHECK: end_access [[ACCESS]]
|
|
//
|
|
// The second get call.
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]]
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[ACCESS]]
|
|
// CHECK: [[LOAD_BORROW:%.*]] = load_borrow [unchecked] [[MARK]]
|
|
// CHECK: [[VALUE:%.*]] = apply {{%.*}}([[LOAD_BORROW]])
|
|
// CHECK: [[BORROWED_VALUE:%.*]] = begin_borrow [[VALUE]]
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $AddressOnlyProtocol
|
|
// CHECK: [[MARK_TEMP:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]], {{%.*}}, [[BORROWED_VALUE]])
|
|
// CHECK: end_borrow [[BORROWED_VALUE]]
|
|
// CHECK: end_borrow [[LOAD_BORROW]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]])
|
|
// CHECK: destroy_addr [[MARK_TEMP]]
|
|
// CHECK: destroy_value [[VALUE]]
|
|
// } // end sil function '$s8moveonly077testSubscriptGetSetThroughNonCopyableParentStruct_BaseLoadable_ResultAddressE4_VaryyF'
|
|
public func testSubscriptGetSetThroughNonCopyableParentStruct_BaseLoadable_ResultAddressOnly_Var() {
|
|
var m = LoadableSubscriptGetSetTesterNonCopyableStructParent()
|
|
m = LoadableSubscriptGetSetTesterNonCopyableStructParent()
|
|
m.tester[0].nonMutatingFunc()
|
|
m.tester[0].mutatingFunc()
|
|
m.computedTester[0].nonMutatingFunc()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @$s8moveonly84testSubscriptGetSetThroughNonCopyableParentStruct_BaseLoadable_ResultAddressOnly_LetyyF : $@convention(thin) () -> () {
|
|
// CHECK: [[BOX:%.*]] = alloc_box ${ let L
|
|
// CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [var_decl] [[BOX]]
|
|
// CHECK: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]]
|
|
//
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[PROJECT]]
|
|
// CHECK: [[LOAD:%.*]] = load_borrow [[MARK]]
|
|
// CHECK: [[EXT:%.*]] = struct_extract [[LOAD]]
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $AddressOnlyProtocol
|
|
// CHECK: [[MARK_TEMP:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]], {{%.*}}, [[EXT]])
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]])
|
|
// CHECK: destroy_addr [[MARK_TEMP]]
|
|
// CHECK: end_borrow [[LOAD]]
|
|
// CHECK: } // end sil function '$s8moveonly84testSubscriptGetSetThroughNonCopyableParentStruct_BaseLoadable_ResultAddressOnly_LetyyF'
|
|
public func testSubscriptGetSetThroughNonCopyableParentStruct_BaseLoadable_ResultAddressOnly_Let() {
|
|
let m = LoadableSubscriptGetSetTesterNonCopyableStructParent()
|
|
m.tester[0].nonMutatingFunc()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @$s8moveonly86testSubscriptGetSetThroughNonCopyableParentStruct_BaseLoadable_ResultAddressOnly_InOut1myAA0lcde6TesterghjI0Vz_tF : $@convention(thin) (@inout LoadableSubscriptGetSetTesterNonCopyableStructParent) -> () {
|
|
// CHECK: bb0([[ARG:%.*]] :
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[ARG]]
|
|
//
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[MARK]]
|
|
// CHECK: [[GEP:%.*]] = struct_element_addr [[ACCESS]]
|
|
// CHECK: [[LOAD:%.*]] = load_borrow [[GEP]]
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $AddressOnlyProtocol
|
|
// CHECK: [[MARK_TEMP:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]], {{%.*}}, [[LOAD]])
|
|
// CHECK: end_borrow [[LOAD]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]])
|
|
// CHECK: destroy_addr [[MARK_TEMP]]
|
|
//
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[MARK]]
|
|
// CHECK: [[GEP:%.*]] = struct_element_addr [[ACCESS]]
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $AddressOnlyProtocol
|
|
// CHECK: [[MARK_TEMP:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP]]
|
|
// CHECK: [[LOAD:%.*]] = load_borrow [[GEP]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]], {{%.*}}, [[LOAD]])
|
|
// CHECK: end_borrow [[LOAD]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]])
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]], {{%.*}}, [[GEP]])
|
|
// CHECK: } // end sil function '$s8moveonly86testSubscriptGetSetThroughNonCopyableParentStruct_BaseLoadable_ResultAddressOnly_InOut1myAA0lcde6TesterghjI0Vz_tF'
|
|
public func testSubscriptGetSetThroughNonCopyableParentStruct_BaseLoadable_ResultAddressOnly_InOut(m: inout LoadableSubscriptGetSetTesterNonCopyableStructParent) {
|
|
m.tester[0].nonMutatingFunc()
|
|
m.tester[0].mutatingFunc()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @$s8moveonly87testSubscriptGetSetThroughNonCopyableParentStruct_BaseLoadable_ResultAddressOnly_GlobalyyF : $@convention(thin) () -> () {
|
|
// CHECK: [[GLOBAL:%.*]] = global_addr @$s8moveonly58globalLoadableSubscriptGetSetTesterNonCopyableStructParentAA0cdefghijK0Vvp
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [dynamic] [[GLOBAL]]
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[ACCESS]]
|
|
// CHECK: [[GEP:%.*]] = struct_element_addr [[MARK]]
|
|
// CHECK: [[LOAD:%.*]] = load_borrow [[GEP]]
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $AddressOnlyProtocol
|
|
// CHECK: [[MARK_TEMP:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]], {{%.*}}, [[LOAD]])
|
|
// CHECK: end_borrow [[LOAD]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]])
|
|
// CHECK: destroy_addr [[MARK_TEMP]]
|
|
//
|
|
// CHECK: [[GLOBAL:%.*]] = global_addr @$s8moveonly58globalLoadableSubscriptGetSetTesterNonCopyableStructParentAA0cdefghijK0Vvp
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [modify] [dynamic] [[GLOBAL]]
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [assignable_but_not_consumable] [[ACCESS]]
|
|
// CHECK: [[GEP:%.*]] = struct_element_addr [[MARK]]
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $AddressOnlyProtocol
|
|
// CHECK: [[MARK_TEMP:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP]]
|
|
// CHECK: [[LOAD:%.*]] = load_borrow [[GEP]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]], {{%.*}}, [[LOAD]])
|
|
// CHECK: end_borrow [[LOAD]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]])
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]], {{%.*}}, [[GEP]])
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: } // end sil function '$s8moveonly87testSubscriptGetSetThroughNonCopyableParentStruct_BaseLoadable_ResultAddressOnly_GlobalyyF'
|
|
var globalLoadableSubscriptGetSetTesterNonCopyableStructParent = LoadableSubscriptGetSetTesterNonCopyableStructParent()
|
|
public func testSubscriptGetSetThroughNonCopyableParentStruct_BaseLoadable_ResultAddressOnly_Global() {
|
|
globalLoadableSubscriptGetSetTesterNonCopyableStructParent.tester[0].nonMutatingFunc()
|
|
globalLoadableSubscriptGetSetTesterNonCopyableStructParent.tester[0].mutatingFunc()
|
|
}
|
|
|
|
public class LoadableSubscriptGetSetTesterClassParent {
|
|
var tester = LoadableSubscriptGetSetTester()
|
|
var computedTester: LoadableSubscriptGetSetTester { fatalError() }
|
|
var computedTester2: LoadableSubscriptGetSetTester {
|
|
get { fatalError() }
|
|
set { fatalError() }
|
|
}
|
|
var testerParent = LoadableSubscriptGetSetTesterNonCopyableStructParent()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @$s8moveonly72testSubscriptGetSetThroughParentClass_BaseLoadable_ResultAddressOnly_VaryyF : $@convention(thin) () -> () {
|
|
// CHECK: [[BOX:%.*]] = alloc_box $
|
|
// CHECK: [[BORROW:%.*]] = begin_borrow [lexical] [var_decl] [[BOX]]
|
|
// CHECK: [[PROJECT:%.*]] = project_box [[BORROW]]
|
|
//
|
|
// First read.
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]]
|
|
// CHECK: [[COPYABLE_CLASS:%.*]] = load [copy] [[ACCESS]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: [[BORROW_COPYABLE_CLASS:%.*]] = begin_borrow [[COPYABLE_CLASS]]
|
|
// CHECK: ([[CORO_RESULT_ORIG:%.*]], [[CORO_TOKEN:%.*]]) = begin_apply {{%.*}}([[BORROW_COPYABLE_CLASS]])
|
|
// CHECK: [[CORO_RESULT_CP:%.*]] = copy_value [[CORO_RESULT_ORIG]]
|
|
// CHECK: [[CORO_RESULT_MK:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[CORO_RESULT_CP]]
|
|
// CHECK: [[CORO_RESULT:%.*]] = begin_borrow [[CORO_RESULT_MK]]
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $
|
|
// CHECK: [[MARK_TEMP:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]], {{%.*}}, [[CORO_RESULT]])
|
|
// CHECK: end_apply [[CORO_TOKEN]]
|
|
// CHECK: end_borrow [[BORROW_COPYABLE_CLASS]]
|
|
// CHECK: destroy_value [[COPYABLE_CLASS]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]])
|
|
// CHECK: destroy_addr [[MARK_TEMP]]
|
|
//
|
|
// First mutation.
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]]
|
|
// CHECK: [[COPYABLE_CLASS:%.*]] = load [copy] [[ACCESS]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: [[BORROW_COPYABLE_CLASS:%.*]] = begin_borrow [[COPYABLE_CLASS]]
|
|
// CHECK: ([[CORO_RESULT_ORIG:%.*]], [[CORO_TOKEN:%.*]]) = begin_apply {{%.*}}([[BORROW_COPYABLE_CLASS]])
|
|
// CHECK: [[CORO_RESULT:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[CORO_RESULT_ORIG]]
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $
|
|
// CHECK: [[MARK_TEMP:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP]]
|
|
// CHECK: [[LOAD:%.*]] = load_borrow [[CORO_RESULT]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]], {{%.*}}, [[LOAD]])
|
|
// CHECK: end_borrow [[LOAD]]
|
|
// Mutating Func
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]])
|
|
// Setter
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]], {{%.*}}, [[CORO_RESULT]])
|
|
// CHECK: end_apply [[CORO_TOKEN]]
|
|
//
|
|
// Second read.
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]]
|
|
// CHECK: [[COPYABLE_CLASS:%.*]] = load [copy] [[ACCESS]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: [[BORROW_COPYABLE_CLASS:%.*]] = begin_borrow [[COPYABLE_CLASS]]
|
|
// CHECK: ([[CORO_RESULT_ORIG:%.*]], [[CORO_TOKEN:%.*]]) = begin_apply {{%.*}}([[BORROW_COPYABLE_CLASS]])
|
|
// CHECK: [[CORO_RESULT_CP:%.*]] = copy_value [[CORO_RESULT_ORIG]]
|
|
// CHECK: [[CORO_RESULT_MK:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[CORO_RESULT_CP]]
|
|
// CHECK: [[CORO_RESULT:%.*]] = begin_borrow [[CORO_RESULT_MK]]
|
|
// CHECK: [[EXT:%.*]] = struct_extract [[CORO_RESULT]]
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $
|
|
// CHECK: [[MARK_TEMP:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]], {{%.*}}, [[EXT]])
|
|
// CHECK: end_apply [[CORO_TOKEN]]
|
|
// CHECK: end_borrow [[BORROW_COPYABLE_CLASS]]
|
|
// CHECK: destroy_value [[COPYABLE_CLASS]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]])
|
|
// CHECK: destroy_addr [[MARK_TEMP]]
|
|
//
|
|
// Second mutate
|
|
//
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]]
|
|
// CHECK: [[COPYABLE_CLASS:%.*]] = load [copy] [[ACCESS]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: [[BORROW_COPYABLE_CLASS:%.*]] = begin_borrow [[COPYABLE_CLASS]]
|
|
// CHECK: ([[CORO_RESULT_ORIG:%.*]], [[CORO_TOKEN:%.*]]) = begin_apply {{%.*}}([[BORROW_COPYABLE_CLASS]])
|
|
// CHECK: [[CORO_RESULT:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[CORO_RESULT_ORIG]]
|
|
// CHECK: [[GEP:%.*]] = struct_element_addr [[CORO_RESULT]]
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $
|
|
// CHECK: [[MARK_TEMP:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP]]
|
|
// CHECK: [[LOAD:%.*]] = load_borrow [[GEP]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]], {{%.*}}, [[LOAD]])
|
|
// CHECK: end_borrow [[LOAD]]
|
|
// Mutating func
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]])
|
|
// Setter func
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]], {{%.*}}, [[GEP]])
|
|
// CHECK: end_apply [[CORO_TOKEN]]
|
|
//
|
|
// Third read.
|
|
//
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]]
|
|
// CHECK: [[CLASS:%.*]] = load_borrow [unchecked] [[ACCESS]]
|
|
// CHECK: ([[CORO_RESULT_ORIG:%.*]], [[CORO_TOKEN:%.*]]) = begin_apply {{%.*}}([[CLASS]])
|
|
// CHECK: [[CORO_RESULT_CP:%.*]] = copy_value [[CORO_RESULT_ORIG]]
|
|
// CHECK: [[CORO_RESULT_MK:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[CORO_RESULT_CP]]
|
|
// CHECK: [[CORO_RESULT:%.*]] = begin_borrow [[CORO_RESULT_MK]]
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $
|
|
// CHECK: [[MARK_TEMP:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]], {{%.*}}, [[CORO_RESULT]])
|
|
// CHECK: end_apply [[CORO_TOKEN]]
|
|
// CHECK: end_borrow [[CLASS]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]])
|
|
// CHECK: destroy_addr [[MARK_TEMP]]
|
|
//
|
|
// First read
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]]
|
|
// CHECK: [[COPYABLE_CLASS:%.*]] = load [copy] [[ACCESS]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: [[BORROW_COPYABLE_CLASS:%.*]] = begin_borrow [[COPYABLE_CLASS]]
|
|
// CHECK: ([[CORO_RESULT_ORIG:%.*]], [[CORO_TOKEN:%.*]]) = begin_apply {{%.*}}([[BORROW_COPYABLE_CLASS]])
|
|
// CHECK: [[CORO_RESULT_CP:%.*]] = copy_value [[CORO_RESULT_ORIG]]
|
|
// CHECK: [[CORO_RESULT_MK:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[CORO_RESULT_CP]]
|
|
// CHECK: [[CORO_RESULT:%.*]] = begin_borrow [[CORO_RESULT_MK]]
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $
|
|
// CHECK: [[MARK_TEMP:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP]]
|
|
// Getter
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]], {{%.*}}, [[CORO_RESULT]])
|
|
// CHECK: end_apply [[CORO_TOKEN]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]])
|
|
// CHECK: destroy_addr [[MARK_TEMP]]
|
|
//
|
|
// Mutation
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]]
|
|
// CHECK: [[COPYABLE_CLASS:%.*]] = load [copy] [[ACCESS]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: [[BORROW_COPYABLE_CLASS:%.*]] = begin_borrow [[COPYABLE_CLASS]]
|
|
// CHECK: ([[CORO_RESULT_ORIG:%.*]], [[CORO_TOKEN:%.*]]) = begin_apply {{%.*}}([[BORROW_COPYABLE_CLASS]])
|
|
// CHECK: [[CORO_RESULT:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[CORO_RESULT_ORIG]]
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $
|
|
// CHECK: [[MARK_TEMP:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP]]
|
|
// CHECK: [[LOAD:%.*]] = load_borrow [[CORO_RESULT]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]], {{%.*}}, [[LOAD]])
|
|
// CHECK: end_borrow [[LOAD]]
|
|
// Mutating Func
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]])
|
|
// Setter
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]], {{%.*}}, [[CORO_RESULT]])
|
|
// CHECK: end_apply [[CORO_TOKEN]]
|
|
// CHECK: } // end sil function '$s8moveonly72testSubscriptGetSetThroughParentClass_BaseLoadable_ResultAddressOnly_VaryyF'
|
|
public func testSubscriptGetSetThroughParentClass_BaseLoadable_ResultAddressOnly_Var() {
|
|
var m = LoadableSubscriptGetSetTesterClassParent()
|
|
m = LoadableSubscriptGetSetTesterClassParent()
|
|
m.tester[0].nonMutatingFunc()
|
|
m.tester[0].mutatingFunc()
|
|
m.testerParent.tester[0].nonMutatingFunc()
|
|
m.testerParent.tester[0].mutatingFunc()
|
|
m.computedTester[0].nonMutatingFunc()
|
|
m.computedTester2[0].nonMutatingFunc()
|
|
m.computedTester2[0].mutatingFunc()
|
|
}
|
|
|
|
// MARK: _read and _modify
|
|
|
|
public struct LoadableSubscriptReadModifyTester : ~Copyable {
|
|
subscript(_ i: Int) -> AddressOnlyProtocol {
|
|
_read {
|
|
fatalError()
|
|
}
|
|
_modify {
|
|
fatalError()
|
|
}
|
|
}
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @$s8moveonly58testSubscriptReadModify_BaseLoadable_ResultAddressOnly_VaryyF : $@convention(thin) () -> () {
|
|
// CHECK: [[BOX:%.*]] = alloc_box $
|
|
// CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [var_decl] [[BOX]]
|
|
// CHECK: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]]
|
|
//
|
|
// The read call
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]]
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[ACCESS]]
|
|
// CHECK: [[LOAD:%.*]] = load_borrow [[MARK]]
|
|
// Eventually, we need this end_apply to be around the nonMutatingFunc.
|
|
// CHECK: ([[CORO_RESULT_ORIG:%.*]], [[CORO_TOKEN:%.*]]) = begin_apply {{%.*}}({{%.*}}, [[LOAD]])
|
|
// CHECK: [[CORO_RESULT:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[CORO_RESULT_ORIG]]
|
|
// CHECK: apply {{%.*}}([[CORO_RESULT]])
|
|
// CHECK: end_apply [[CORO_TOKEN]]
|
|
// CHECK: end_borrow [[LOAD]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
//
|
|
// The assignment:
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $AddressOnlyProtocol
|
|
// CHECK: [[MARK_TEMP:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]], {{%.*}}) : $@convention(method) (@thin AddressOnlyProtocol.Type) -> @out AddressOnlyProtocol
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[PROJECT]]
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [assignable_but_not_consumable] [[ACCESS]]
|
|
// CHECK: ([[CORO_RESULT_ORIG:%.*]], [[CORO_TOKEN:%.*]]) = begin_apply {{%.*}}({{%.*}}, [[MARK]])
|
|
// CHECK: [[CORO_RESULT:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[CORO_RESULT_ORIG]]
|
|
// CHECK: copy_addr [take] [[MARK_TEMP]] to [[CORO_RESULT]]
|
|
// CHECK: end_apply [[CORO_TOKEN]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
//
|
|
// The mutating function call.
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[PROJECT]]
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [assignable_but_not_consumable] [[ACCESS]]
|
|
// CHECK: ([[CORO_RESULT_ORIG:%.*]], [[CORO_TOKEN:%.*]]) = begin_apply {{%.*}}({{%.*}}, [[MARK]])
|
|
// CHECK: [[CORO_RESULT:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[CORO_RESULT_ORIG]]
|
|
// CHECK: apply {{%.*}}([[CORO_RESULT]])
|
|
// CHECK: end_apply [[CORO_TOKEN]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
//
|
|
// CHECK: } // end sil function '$s8moveonly58testSubscriptReadModify_BaseLoadable_ResultAddressOnly_VaryyF'
|
|
public func testSubscriptReadModify_BaseLoadable_ResultAddressOnly_Var() {
|
|
var m = LoadableSubscriptReadModifyTester()
|
|
m = LoadableSubscriptReadModifyTester()
|
|
m[0].nonMutatingFunc()
|
|
m[0] = AddressOnlyProtocol()
|
|
m[0].mutatingFunc()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @$s8moveonly58testSubscriptReadModify_BaseLoadable_ResultAddressOnly_LetyyF : $@convention(thin) () -> () {
|
|
// CHECK: [[BOX:%.*]] = alloc_box $
|
|
// CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [var_decl] [[BOX]]
|
|
// CHECK: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]]
|
|
//
|
|
// The get call
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[PROJECT]]
|
|
// CHECK: [[LOAD_BORROW:%.*]] = load_borrow [[MARK]]
|
|
// CHECK: ([[CORO_RESULT_ORIG:%.*]], [[CORO_TOKEN:%.*]]) = begin_apply {{%.*}}({{%.*}}, [[LOAD_BORROW]])
|
|
// CHECK: [[CORO_RESULT:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[CORO_RESULT_ORIG]]
|
|
// CHECK: apply {{%.*}}([[CORO_RESULT]])
|
|
// CHECK: end_apply [[CORO_TOKEN]]
|
|
// CHECK: end_borrow [[LOAD_BORROW]]
|
|
// CHECK: } // end sil function '$s8moveonly58testSubscriptReadModify_BaseLoadable_ResultAddressOnly_LetyyF'
|
|
public func testSubscriptReadModify_BaseLoadable_ResultAddressOnly_Let() {
|
|
let m = LoadableSubscriptReadModifyTester()
|
|
m[0].nonMutatingFunc()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @$s8moveonly60testSubscriptReadModify_BaseLoadable_ResultAddressOnly_InOut1myAA0gcdE6TesterVz_tF : $@convention(thin) (@inout LoadableSubscriptReadModifyTester) -> () {
|
|
// CHECK: bb0([[ARG:%.*]] : $*
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[ARG]]
|
|
//
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[MARK]]
|
|
// CHECK: [[LOAD_BORROW:%.*]] = load_borrow [[ACCESS]]
|
|
// CHECK: ([[CORO_RESULT_ORIG:%.*]], [[CORO_TOKEN:%.*]]) = begin_apply {{%.*}}({{%.*}}, [[LOAD_BORROW]])
|
|
// CHECK: [[CORO_RESULT:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[CORO_RESULT_ORIG]]
|
|
// CHECK: apply {{%.*}}([[CORO_RESULT]])
|
|
// CHECK: end_apply [[CORO_TOKEN]]
|
|
// CHECK: end_borrow [[LOAD_BORROW]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
//
|
|
// The assignment:
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $AddressOnlyProtocol
|
|
// CHECK: [[MARK_TEMP:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP]]
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[MARK]]
|
|
// CHECK: ([[CORO_RESULT_ORIG:%.*]], [[CORO_TOKEN:%.*]]) = begin_apply {{%.*}}({{%.*}}, [[ACCESS]])
|
|
// CHECK: [[CORO_RESULT:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[CORO_RESULT_ORIG]]
|
|
// CHECK: copy_addr [take] [[MARK_TEMP]] to [[CORO_RESULT]]
|
|
// CHECK: end_apply [[CORO_TOKEN]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
//
|
|
// The mutating function call.
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[MARK]]
|
|
// CHECK: ([[CORO_RESULT_ORIG:%.*]], [[CORO_TOKEN:%.*]]) = begin_apply {{%.*}}({{%.*}}, [[ACCESS]])
|
|
// CHECK: [[CORO_RESULT:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[CORO_RESULT_ORIG]]
|
|
// CHECK: apply {{%.*}}([[CORO_RESULT]])
|
|
// CHECK: end_apply [[CORO_TOKEN]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
//
|
|
// CHECK: } // end sil function '$s8moveonly60testSubscriptReadModify_BaseLoadable_ResultAddressOnly_InOut1myAA0gcdE6TesterVz_tF'
|
|
public func testSubscriptReadModify_BaseLoadable_ResultAddressOnly_InOut(m: inout LoadableSubscriptReadModifyTester) {
|
|
m[0].nonMutatingFunc()
|
|
m[0] = AddressOnlyProtocol()
|
|
m[0].mutatingFunc()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @$s8moveonly61testSubscriptReadModify_BaseLoadable_ResultAddressOnly_GlobalyyF : $@convention(thin) () -> () {
|
|
// CHECK: [[GLOBAL_ADDR:%.*]] = global_addr @$s8moveonly39globalLoadableSubscriptReadModifyTesterAA0cdefG0Vvp :
|
|
//
|
|
// The get call
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [dynamic] [[GLOBAL_ADDR]]
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[ACCESS]]
|
|
// CHECK: [[LOAD_BORROW:%.*]] = load_borrow [[MARK]]
|
|
// CHECK: ([[CORO_RESULT_ORIG:%.*]], [[CORO_TOKEN:%.*]]) = begin_apply {{%.*}}({{%.*}}, [[LOAD_BORROW]])
|
|
// CHECK: [[CORO_RESULT:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[CORO_RESULT_ORIG]]
|
|
// CHECK: apply {{%.*}}([[CORO_RESULT]])
|
|
// CHECK: end_apply [[CORO_TOKEN]]
|
|
// CHECK: end_borrow [[LOAD_BORROW]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
//
|
|
// The assignment:
|
|
// CHECK: [[GLOBAL_ADDR:%.*]] = global_addr @$s8moveonly39globalLoadableSubscriptReadModifyTesterAA0cdefG0Vvp :
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $AddressOnlyProtocol
|
|
// CHECK: [[MARK_TEMP:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]], {{%.*}}) : $@convention(method) (@thin AddressOnlyProtocol.Type) -> @out AddressOnlyProtocol
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [modify] [dynamic] [[GLOBAL_ADDR]]
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [assignable_but_not_consumable] [[ACCESS]]
|
|
// CHECK: ([[CORO_RESULT_ORIG:%.*]], [[CORO_TOKEN:%.*]]) = begin_apply {{%.*}}({{%.*}}, [[MARK]])
|
|
// CHECK: [[CORO_RESULT:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[CORO_RESULT_ORIG]]
|
|
// CHECK: copy_addr [take] [[MARK_TEMP]] to [[CORO_RESULT]]
|
|
// CHECK: end_apply [[CORO_TOKEN]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
//
|
|
// The mutating function call.
|
|
// CHECK: [[GLOBAL_ADDR:%.*]] = global_addr @$s8moveonly39globalLoadableSubscriptReadModifyTesterAA0cdefG0Vvp :
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [modify] [dynamic] [[GLOBAL_ADDR]]
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [assignable_but_not_consumable] [[ACCESS]]
|
|
// CHECK: ([[CORO_RESULT_ORIG:%.*]], [[CORO_TOKEN:%.*]]) = begin_apply {{%.*}}({{%.*}}, [[MARK]])
|
|
// CHECK: [[CORO_RESULT:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[CORO_RESULT_ORIG]]
|
|
// CHECK: apply {{%.*}}([[CORO_RESULT]])
|
|
// CHECK: end_apply [[CORO_TOKEN]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
//
|
|
// CHECK: } // end sil function '$s8moveonly61testSubscriptReadModify_BaseLoadable_ResultAddressOnly_GlobalyyF'
|
|
var globalLoadableSubscriptReadModifyTester = LoadableSubscriptReadModifyTester()
|
|
public func testSubscriptReadModify_BaseLoadable_ResultAddressOnly_Global() {
|
|
globalLoadableSubscriptReadModifyTester[0].nonMutatingFunc()
|
|
globalLoadableSubscriptReadModifyTester[0] = AddressOnlyProtocol()
|
|
globalLoadableSubscriptReadModifyTester[0].mutatingFunc()
|
|
}
|
|
|
|
// Make sure that we get the same behavior when we access through another noncopyable struct.
|
|
public struct LoadableSubscriptReadModifyTesterNonCopyableStructParent : ~Copyable {
|
|
var tester = LoadableSubscriptReadModifyTester()
|
|
var computedTester: LoadableSubscriptReadModifyTester { fatalError() }
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @$s8moveonly88testSubscriptReadModifyThroughNonCopyableParentStruct_BaseLoadable_ResultAddressOnly_VaryyF : $@convention(thin) () -> () {
|
|
// CHECK: [[BOX:%.*]] = alloc_box $
|
|
// CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [var_decl] [[BOX]]
|
|
// CHECK: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]]
|
|
//
|
|
// The first get call
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]]
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[ACCESS]]
|
|
// CHECK: [[GEP:%.*]] = struct_element_addr [[MARK]]
|
|
// CHECK: [[LOAD_BORROW:%.*]] = load_borrow [[GEP]]
|
|
// CHECK: ([[CORO_RESULT_ORIG:%.*]], [[CORO_TOKEN:%.*]]) = begin_apply {{%.*}}({{%.*}}, [[LOAD_BORROW]])
|
|
// CHECK: [[CORO_RESULT:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[CORO_RESULT_ORIG]]
|
|
// CHECK: apply {{%.*}}([[CORO_RESULT]])
|
|
// CHECK: end_apply [[CORO_TOKEN]]
|
|
// CHECK: end_borrow [[LOAD_BORROW]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
//
|
|
// The mutating call.
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[PROJECT]]
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [assignable_but_not_consumable] [[ACCESS]]
|
|
// CHECK: [[GEP:%.*]] = struct_element_addr [[MARK]]
|
|
// CHECK: ([[CORO_RESULT_ORIG:%.*]], [[CORO_TOKEN:%.*]]) = begin_apply {{%.*}}({{%.*}}, [[GEP]])
|
|
// CHECK: [[CORO_RESULT:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[CORO_RESULT_ORIG]]
|
|
// CHECK: apply {{%.*}}([[CORO_RESULT]])
|
|
// CHECK: end_apply [[CORO_TOKEN]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
//
|
|
// The second get call.
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]]
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[ACCESS]]
|
|
// CHECK: [[LOAD_BORROW:%.*]] = load_borrow [unchecked] [[MARK]]
|
|
// CHECK: [[VALUE:%.*]] = apply {{%.*}}([[LOAD_BORROW]])
|
|
// CHECK: [[BORROWED_VALUE:%.*]] = begin_borrow [[VALUE]]
|
|
// CHECK: ([[CORO_RESULT_ORIG:%.*]], [[CORO_TOKEN:%.*]]) = begin_apply {{%.*}}({{%.*}}, [[BORROWED_VALUE]])
|
|
// CHECK: [[CORO_RESULT:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[CORO_RESULT_ORIG]]
|
|
// CHECK: apply {{%.*}}([[CORO_RESULT]])
|
|
// CHECK: end_apply [[CORO_TOKEN]]
|
|
// CHECK: end_borrow [[BORROWED_VALUE]]
|
|
// CHECK: end_borrow [[LOAD_BORROW]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
// } // end sil function '$s8moveonly88testSubscriptReadModifyThroughNonCopyableParentStruct_BaseLoadable_ResultAddressOnly_VaryyF'
|
|
public func testSubscriptReadModifyThroughNonCopyableParentStruct_BaseLoadable_ResultAddressOnly_Var() {
|
|
var m = LoadableSubscriptReadModifyTesterNonCopyableStructParent()
|
|
m = LoadableSubscriptReadModifyTesterNonCopyableStructParent()
|
|
m.tester[0].nonMutatingFunc()
|
|
m.tester[0].mutatingFunc()
|
|
m.computedTester[0].nonMutatingFunc()
|
|
}
|
|
|
|
|
|
// CHECK-LABEL: sil [ossa] @$s8moveonly88testSubscriptReadModifyThroughNonCopyableParentStruct_BaseLoadable_ResultAddressOnly_LetyyF : $@convention(thin) () -> () {
|
|
// CHECK: [[BOX:%.*]] = alloc_box ${ let L
|
|
// CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [var_decl] [[BOX]]
|
|
// CHECK: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]]
|
|
//
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[PROJECT]]
|
|
// CHECK: [[LOAD:%.*]] = load_borrow [[MARK]]
|
|
// CHECK: [[EXT:%.*]] = struct_extract [[LOAD]]
|
|
// CHECK: ([[CORO_RESULT_ORIG:%.*]], [[CORO_TOKEN:%.*]]) = begin_apply {{%.*}}({{%.*}}, [[EXT]])
|
|
// CHECK: [[CORO_RESULT:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[CORO_RESULT_ORIG]]
|
|
// CHECK: apply {{%.*}}([[CORO_RESULT]])
|
|
// CHECK: end_apply [[CORO_TOKEN]]
|
|
// CHECK: end_borrow [[LOAD]]
|
|
// CHECK: } // end sil function '$s8moveonly88testSubscriptReadModifyThroughNonCopyableParentStruct_BaseLoadable_ResultAddressOnly_LetyyF'
|
|
public func testSubscriptReadModifyThroughNonCopyableParentStruct_BaseLoadable_ResultAddressOnly_Let() {
|
|
let m = LoadableSubscriptReadModifyTesterNonCopyableStructParent()
|
|
m.tester[0].nonMutatingFunc()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @$s8moveonly90testSubscriptReadModifyThroughNonCopyableParentStruct_BaseLoadable_ResultAddressOnly_InOut1myAA0lcde6TesterghjI0Vz_tF : $@convention(thin) (@inout LoadableSubscriptReadModifyTesterNonCopyableStructParent) -> () {
|
|
// CHECK: bb0([[ARG:%.*]] :
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[ARG]]
|
|
//
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[MARK]]
|
|
// CHECK: [[GEP:%.*]] = struct_element_addr [[ACCESS]]
|
|
// CHECK: [[LOAD:%.*]] = load_borrow [[GEP]]
|
|
// CHECK: ([[CORO_RESULT_ORIG:%.*]], [[CORO_TOKEN:%.*]]) = begin_apply {{%.*}}({{%.*}}, [[LOAD]])
|
|
// CHECK: [[CORO_RESULT:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[CORO_RESULT_ORIG]]
|
|
// CHECK: apply {{%.*}}([[CORO_RESULT]])
|
|
// CHECK: end_apply [[CORO_TOKEN]]
|
|
// CHECK: end_borrow [[LOAD]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
//
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[MARK]]
|
|
// CHECK: [[GEP:%.*]] = struct_element_addr [[ACCESS]]
|
|
// CHECK: ([[CORO_RESULT_ORIG:%.*]], [[CORO_TOKEN:%.*]]) = begin_apply {{%.*}}({{%.*}}, [[GEP]])
|
|
// CHECK: [[CORO_RESULT:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[CORO_RESULT_ORIG]]
|
|
// CHECK: apply {{%.*}}([[CORO_RESULT]])
|
|
// CHECK: end_apply [[CORO_TOKEN]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: } // end sil function '$s8moveonly90testSubscriptReadModifyThroughNonCopyableParentStruct_BaseLoadable_ResultAddressOnly_InOut1myAA0lcde6TesterghjI0Vz_tF'
|
|
public func testSubscriptReadModifyThroughNonCopyableParentStruct_BaseLoadable_ResultAddressOnly_InOut(m: inout LoadableSubscriptReadModifyTesterNonCopyableStructParent) {
|
|
m.tester[0].nonMutatingFunc()
|
|
m.tester[0].mutatingFunc()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @$s8moveonly91testSubscriptReadModifyThroughNonCopyableParentStruct_BaseLoadable_ResultAddressOnly_GlobalyyF : $@convention(thin) () -> () {
|
|
// CHECK: [[GLOBAL:%.*]] = global_addr @$s8moveonly62globalLoadableSubscriptReadModifyTesterNonCopyableStructParentAA0cdefghijK0Vvp :
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [dynamic] [[GLOBAL]]
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[ACCESS]]
|
|
// CHECK: [[GEP:%.*]] = struct_element_addr [[MARK]]
|
|
// CHECK: [[LOAD:%.*]] = load_borrow [[GEP]]
|
|
// CHECK: ([[CORO_RESULT_ORIG:%.*]], [[CORO_TOKEN:%.*]]) = begin_apply {{%.*}}({{%.*}}, [[LOAD]])
|
|
// CHECK: [[CORO_RESULT:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[CORO_RESULT_ORIG]]
|
|
// CHECK: apply {{%.*}}([[CORO_RESULT]])
|
|
// CHECK: end_apply [[CORO_TOKEN]]
|
|
// CHECK: end_borrow [[LOAD]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
//
|
|
// CHECK: [[GLOBAL:%.*]] = global_addr @$s8moveonly62globalLoadableSubscriptReadModifyTesterNonCopyableStructParentAA0cdefghijK0Vvp :
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [modify] [dynamic] [[GLOBAL]]
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [assignable_but_not_consumable] [[ACCESS]]
|
|
// CHECK: [[GEP:%.*]] = struct_element_addr [[MARK]]
|
|
// CHECK: ([[CORO_RESULT_ORIG:%.*]], [[CORO_TOKEN:%.*]]) = begin_apply {{%.*}}({{%.*}}, [[GEP]])
|
|
// CHECK: [[CORO_RESULT:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[CORO_RESULT_ORIG]]
|
|
// CHECK: apply {{%.*}}([[CORO_RESULT]])
|
|
// CHECK: end_apply [[CORO_TOKEN]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: } // end sil function '$s8moveonly91testSubscriptReadModifyThroughNonCopyableParentStruct_BaseLoadable_ResultAddressOnly_GlobalyyF'
|
|
var globalLoadableSubscriptReadModifyTesterNonCopyableStructParent = LoadableSubscriptReadModifyTesterNonCopyableStructParent()
|
|
public func testSubscriptReadModifyThroughNonCopyableParentStruct_BaseLoadable_ResultAddressOnly_Global() {
|
|
globalLoadableSubscriptReadModifyTesterNonCopyableStructParent.tester[0].nonMutatingFunc()
|
|
globalLoadableSubscriptReadModifyTesterNonCopyableStructParent.tester[0].mutatingFunc()
|
|
}
|
|
|
|
public class LoadableSubscriptReadModifyTesterClassParent {
|
|
var tester = LoadableSubscriptReadModifyTester()
|
|
var computedTester: LoadableSubscriptReadModifyTester { fatalError() }
|
|
var computedTester2: LoadableSubscriptReadModifyTester {
|
|
get { fatalError() }
|
|
set { fatalError() }
|
|
}
|
|
var testerParent = LoadableSubscriptReadModifyTesterNonCopyableStructParent()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @$s8moveonly76testSubscriptReadModifyThroughParentClass_BaseLoadable_ResultAddressOnly_VaryyF : $@convention(thin) () -> () {
|
|
// CHECK: [[BOX:%.*]] = alloc_box $
|
|
// CHECK: [[BORROW:%.*]] = begin_borrow [lexical] [var_decl] [[BOX]]
|
|
// CHECK: [[PROJECT:%.*]] = project_box [[BORROW]]
|
|
//
|
|
// First read.
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]]
|
|
// CHECK: [[COPYABLE_CLASS:%.*]] = load [copy] [[ACCESS]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: [[BORROW_COPYABLE_CLASS:%.*]] = begin_borrow [[COPYABLE_CLASS]]
|
|
// CHECK: ([[CORO_RESULT_ORIG:%.*]], [[CORO_TOKEN:%.*]]) = begin_apply {{%.*}}([[BORROW_COPYABLE_CLASS]])
|
|
// CHECK: [[CORO_RESULT_CP:%.*]] = copy_value [[CORO_RESULT_ORIG]]
|
|
// CHECK: [[CORO_RESULT_MK:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[CORO_RESULT_CP]]
|
|
// CHECK: [[CORO_RESULT:%.*]] = begin_borrow [[CORO_RESULT_MK]]
|
|
// CHECK: ([[CORO_RESULT_2_ORIG:%.*]], [[CORO_TOKEN_2:%.*]]) = begin_apply {{%.*}}({{%.*}}, [[CORO_RESULT]])
|
|
// CHECK: [[CORO_RESULT_2:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[CORO_RESULT_2_ORIG]]
|
|
// CHECK: apply {{%.*}}([[CORO_RESULT_2]])
|
|
// CHECK: end_apply [[CORO_TOKEN_2]]
|
|
// CHECK: end_apply [[CORO_TOKEN]]
|
|
// CHECK: end_borrow [[BORROW_COPYABLE_CLASS]]
|
|
// CHECK: destroy_value [[COPYABLE_CLASS]]
|
|
//
|
|
// First mutation.
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]]
|
|
// CHECK: [[COPYABLE_CLASS:%.*]] = load [copy] [[ACCESS]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: [[BORROW_COPYABLE_CLASS:%.*]] = begin_borrow [[COPYABLE_CLASS]]
|
|
// CHECK: ([[CORO_RESULT_ORIG:%.*]], [[CORO_TOKEN:%.*]]) = begin_apply {{%.*}}([[BORROW_COPYABLE_CLASS]])
|
|
// CHECK: [[CORO_RESULT:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[CORO_RESULT_ORIG]]
|
|
// CHECK: ([[CORO_RESULT_2_ORIG:%.*]], [[CORO_TOKEN_2:%.*]]) = begin_apply {{%.*}}({{%.*}}, [[CORO_RESULT]])
|
|
// CHECK: [[CORO_RESULT_2:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[CORO_RESULT_2_ORIG]]
|
|
// CHECK: apply {{%.*}}([[CORO_RESULT_2]])
|
|
// CHECK: end_apply [[CORO_TOKEN_2]]
|
|
// CHECK: end_apply [[CORO_TOKEN]]
|
|
// CHECK: end_borrow [[BORROW_COPYABLE_CLASS]]
|
|
// CHECK: destroy_value [[COPYABLE_CLASS]]
|
|
//
|
|
// Second read.
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]]
|
|
// CHECK: [[COPYABLE_CLASS:%.*]] = load [copy] [[ACCESS]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: [[BORROW_COPYABLE_CLASS:%.*]] = begin_borrow [[COPYABLE_CLASS]]
|
|
// CHECK: ([[CORO_RESULT_ORIG:%.*]], [[CORO_TOKEN:%.*]]) = begin_apply {{%.*}}([[BORROW_COPYABLE_CLASS]])
|
|
// CHECK: [[CORO_RESULT_CP:%.*]] = copy_value [[CORO_RESULT_ORIG]]
|
|
// CHECK: [[CORO_RESULT_MK:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[CORO_RESULT_CP]]
|
|
// CHECK: [[CORO_RESULT:%.*]] = begin_borrow [[CORO_RESULT_MK]]
|
|
// CHECK: [[EXT:%.*]] = struct_extract [[CORO_RESULT]]
|
|
// CHECK: ([[CORO_RESULT_ORIG_2:%.*]], [[CORO_TOKEN_2:%.*]]) = begin_apply {{%.*}}({{%.*}}, [[EXT]])
|
|
// CHECK: [[CORO_RESULT_2:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[CORO_RESULT_ORIG_2]]
|
|
// CHECK: apply {{%.*}}([[CORO_RESULT_2]])
|
|
// CHECK: end_apply [[CORO_TOKEN_2]]
|
|
// CHECK: end_apply [[CORO_TOKEN]]
|
|
// CHECK: end_borrow [[BORROW_COPYABLE_CLASS]]
|
|
// CHECK: destroy_value [[COPYABLE_CLASS]]
|
|
//
|
|
// Second mutate
|
|
//
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]]
|
|
// CHECK: [[COPYABLE_CLASS:%.*]] = load [copy] [[ACCESS]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: [[BORROW_COPYABLE_CLASS:%.*]] = begin_borrow [[COPYABLE_CLASS]]
|
|
// CHECK: ([[CORO_RESULT_ORIG:%.*]], [[CORO_TOKEN:%.*]]) = begin_apply {{%.*}}([[BORROW_COPYABLE_CLASS]])
|
|
// CHECK: [[CORO_RESULT:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[CORO_RESULT_ORIG]]
|
|
// CHECK: [[GEP:%.*]] = struct_element_addr [[CORO_RESULT]]
|
|
// CHECK: ([[CORO_RESULT_2_ORIG:%.*]], [[CORO_TOKEN_2:%.*]]) = begin_apply {{%.*}}({{%.*}}, [[GEP]])
|
|
// CHECK: [[CORO_RESULT_2:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[CORO_RESULT_2_ORIG]]
|
|
// Mutating func
|
|
// CHECK: apply {{%.*}}([[CORO_RESULT_2]])
|
|
// CHECK: end_apply [[CORO_TOKEN_2]]
|
|
// CHECK: end_apply [[CORO_TOKEN]]
|
|
// CHECK: end_borrow [[BORROW_COPYABLE_CLASS]]
|
|
// CHECK: destroy_value [[COPYABLE_CLASS]]
|
|
//
|
|
// Third read.
|
|
//
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]]
|
|
// CHECK: [[CLASS:%.*]] = load_borrow [unchecked] [[ACCESS]]
|
|
// CHECK: ([[CORO_RESULT_ORIG:%.*]], [[CORO_TOKEN:%.*]]) = begin_apply {{%.*}}([[CLASS]])
|
|
// CHECK: [[CORO_RESULT_CP:%.*]] = copy_value [[CORO_RESULT_ORIG]]
|
|
// CHECK: [[CORO_RESULT_MK:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[CORO_RESULT_CP]]
|
|
// CHECK: [[CORO_RESULT:%.*]] = begin_borrow [[CORO_RESULT_MK]]
|
|
// CHECK: ([[CORO_RESULT2_ORIG:%.*]], [[CORO_TOKEN2:%.*]]) = begin_apply {{%.*}}({{%.*}}, [[CORO_RESULT]])
|
|
// CHECK: [[CORO_RESULT2:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[CORO_RESULT2_ORIG]]
|
|
// CHECK: apply {{%.*}}([[CORO_RESULT2]])
|
|
// CHECK: end_apply [[CORO_TOKEN2]]
|
|
// CHECK: end_apply [[CORO_TOKEN]]
|
|
// CHECK: end_borrow [[BORROW]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
//
|
|
// First read
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]]
|
|
// CHECK: [[COPYABLE_CLASS:%.*]] = load [copy] [[ACCESS]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: [[BORROW_COPYABLE_CLASS:%.*]] = begin_borrow [[COPYABLE_CLASS]]
|
|
// CHECK: ([[CORO_RESULT_ORIG:%.*]], [[CORO_TOKEN:%.*]]) = begin_apply {{%.*}}([[BORROW_COPYABLE_CLASS]])
|
|
// CHECK: [[CORO_RESULT_CP:%.*]] = copy_value [[CORO_RESULT_ORIG]]
|
|
// CHECK: [[CORO_RESULT_MK:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[CORO_RESULT_CP]]
|
|
// CHECK: [[CORO_RESULT:%.*]] = begin_borrow [[CORO_RESULT_MK]]
|
|
// CHECK: ([[CORO_RESULT_2_ORIG:%.*]], [[CORO_TOKEN_2:%.*]]) = begin_apply {{%.*}}({{%.*}}, [[CORO_RESULT]])
|
|
// CHECK: [[CORO_RESULT_2:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[CORO_RESULT_2_ORIG]]
|
|
// CHECK: apply {{%.*}}([[CORO_RESULT_2]])
|
|
// CHECK: end_apply [[CORO_TOKEN_2]]
|
|
// CHECK: end_apply [[CORO_TOKEN]]
|
|
//
|
|
// Mutation
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]]
|
|
// CHECK: [[COPYABLE_CLASS:%.*]] = load [copy] [[ACCESS]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: [[BORROW_COPYABLE_CLASS:%.*]] = begin_borrow [[COPYABLE_CLASS]]
|
|
// CHECK: ([[CORO_RESULT_ORIG:%.*]], [[CORO_TOKEN:%.*]]) = begin_apply {{%.*}}([[BORROW_COPYABLE_CLASS]])
|
|
// CHECK: [[CORO_RESULT:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[CORO_RESULT_ORIG]]
|
|
// CHECK: ([[CORO_RESULT_2_ORIG:%.*]], [[CORO_TOKEN_2:%.*]]) = begin_apply {{%.*}}({{%.*}}, [[CORO_RESULT]])
|
|
// CHECK: [[CORO_RESULT_2:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[CORO_RESULT_2_ORIG]]
|
|
// CHECK: apply {{%.*}}([[CORO_RESULT_2]])
|
|
// CHECK: end_apply [[CORO_TOKEN_2]]
|
|
// CHECK: end_apply [[CORO_TOKEN]]
|
|
// CHECK: } // end sil function '$s8moveonly76testSubscriptReadModifyThroughParentClass_BaseLoadable_ResultAddressOnly_VaryyF'
|
|
public func testSubscriptReadModifyThroughParentClass_BaseLoadable_ResultAddressOnly_Var() {
|
|
var m = LoadableSubscriptReadModifyTesterClassParent()
|
|
m = LoadableSubscriptReadModifyTesterClassParent()
|
|
m.tester[0].nonMutatingFunc()
|
|
m.tester[0].mutatingFunc()
|
|
m.testerParent.tester[0].nonMutatingFunc()
|
|
m.testerParent.tester[0].mutatingFunc()
|
|
m.computedTester[0].nonMutatingFunc()
|
|
m.computedTester2[0].nonMutatingFunc()
|
|
m.computedTester2[0].mutatingFunc()
|
|
}
|
|
|
|
// MARK: get and _modify
|
|
|
|
public struct LoadableSubscriptGetModifyTester : ~Copyable {
|
|
subscript(_ i: Int) -> AddressOnlyProtocol {
|
|
get {
|
|
fatalError()
|
|
}
|
|
_modify {
|
|
fatalError()
|
|
}
|
|
}
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @$s8moveonly57testSubscriptGetModify_BaseLoadable_ResultAddressOnly_VaryyF : $@convention(thin) () -> () {
|
|
// CHECK: [[BOX:%.*]] = alloc_box $
|
|
// CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [var_decl] [[BOX]]
|
|
// CHECK: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]]
|
|
//
|
|
// The get call
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]]
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[ACCESS]]
|
|
// CHECK: [[LOAD_BORROW:%.*]] = load_borrow [[MARK]]
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $AddressOnlyProtocol
|
|
// CHECK: [[MARK_TEMP:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]], {{%.*}}, [[LOAD_BORROW]])
|
|
// CHECK: end_borrow [[LOAD_BORROW]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]])
|
|
// CHECK: destroy_addr [[MARK_TEMP]]
|
|
//
|
|
// The assignment:
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $AddressOnlyProtocol
|
|
// CHECK: [[MARK_TEMP:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]], {{%.*}}) : $@convention(method) (@thin AddressOnlyProtocol.Type) -> @out AddressOnlyProtocol
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[PROJECT]]
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [assignable_but_not_consumable] [[ACCESS]]
|
|
// CHECK: ([[CORO_RESULT_ORIG:%.*]], [[CORO_TOKEN:%.*]]) = begin_apply {{%.*}}({{%.*}}, [[MARK]])
|
|
// CHECK: [[CORO_RESULT:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[CORO_RESULT_ORIG]]
|
|
// CHECK: copy_addr [take] [[MARK_TEMP]] to [[CORO_RESULT]]
|
|
// CHECK: end_apply [[CORO_TOKEN]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
//
|
|
// The mutating function call.
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[PROJECT]]
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [assignable_but_not_consumable] [[ACCESS]]
|
|
// CHECK: ([[CORO_RESULT_ORIG:%.*]], [[CORO_TOKEN:%.*]]) = begin_apply {{%.*}}({{%.*}}, [[MARK]])
|
|
// CHECK: [[CORO_RESULT:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[CORO_RESULT_ORIG]]
|
|
// CHECK: apply {{%.*}}([[CORO_RESULT]])
|
|
// CHECK: end_apply [[CORO_TOKEN]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
//
|
|
// CHECK: } // end sil function '$s8moveonly57testSubscriptGetModify_BaseLoadable_ResultAddressOnly_VaryyF'
|
|
public func testSubscriptGetModify_BaseLoadable_ResultAddressOnly_Var() {
|
|
var m = LoadableSubscriptGetModifyTester()
|
|
m = LoadableSubscriptGetModifyTester()
|
|
m[0].nonMutatingFunc()
|
|
m[0] = AddressOnlyProtocol()
|
|
m[0].mutatingFunc()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @$s8moveonly57testSubscriptGetModify_BaseLoadable_ResultAddressOnly_LetyyF : $@convention(thin) () -> () {
|
|
// CHECK: [[BOX:%.*]] = alloc_box $
|
|
// CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [var_decl] [[BOX]]
|
|
// CHECK: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]]
|
|
//
|
|
// The get call
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[PROJECT]]
|
|
// CHECK: [[LOAD_BORROW:%.*]] = load_borrow [[MARK]]
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $AddressOnlyProtocol
|
|
// CHECK: [[MARK_TEMP:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]], {{%.*}}, [[LOAD_BORROW]])
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]])
|
|
// CHECK: destroy_addr [[MARK_TEMP]]
|
|
// CHECK: end_borrow [[LOAD_BORROW]]
|
|
// CHECK: } // end sil function '$s8moveonly57testSubscriptGetModify_BaseLoadable_ResultAddressOnly_LetyyF'
|
|
public func testSubscriptGetModify_BaseLoadable_ResultAddressOnly_Let() {
|
|
let m = LoadableSubscriptGetModifyTester()
|
|
m[0].nonMutatingFunc()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @$s8moveonly59testSubscriptGetModify_BaseLoadable_ResultAddressOnly_InOut1myAA0gcdE6TesterVz_tF : $@convention(thin) (@inout LoadableSubscriptGetModifyTester) -> () {
|
|
// CHECK: bb0([[ARG:%.*]] : $*
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[ARG]]
|
|
//
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[MARK]]
|
|
// CHECK: [[LOAD_BORROW:%.*]] = load_borrow [[ACCESS]]
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $AddressOnlyProtocol
|
|
// CHECK: [[MARK_TEMP:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]], {{%.*}}, [[LOAD_BORROW]])
|
|
// CHECK: end_borrow [[LOAD_BORROW]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]])
|
|
// CHECK: destroy_addr [[MARK_TEMP]]
|
|
//
|
|
// The assignment:
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $AddressOnlyProtocol
|
|
// CHECK: [[MARK_TEMP:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]], {{%.*}}) : $@convention(method) (@thin AddressOnlyProtocol.Type) -> @out AddressOnlyProtocol
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[MARK]]
|
|
// CHECK: ([[CORO_RESULT_ORIG:%.*]], [[CORO_TOKEN:%.*]]) = begin_apply {{%.*}}({{%.*}}, [[ACCESS]])
|
|
// CHECK: [[CORO_RESULT:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[CORO_RESULT_ORIG]]
|
|
// CHECK: copy_addr [take] [[MARK_TEMP]] to [[CORO_RESULT]]
|
|
// CHECK: end_apply [[CORO_TOKEN]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
//
|
|
// The mutating function call.
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[MARK]]
|
|
// CHECK: ([[CORO_RESULT_ORIG:%.*]], [[CORO_TOKEN:%.*]]) = begin_apply {{%.*}}({{%.*}}, [[ACCESS]])
|
|
// CHECK: [[CORO_RESULT:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[CORO_RESULT_ORIG]]
|
|
// CHECK: apply {{%.*}}([[CORO_RESULT]])
|
|
// CHECK: end_apply [[CORO_TOKEN]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
//
|
|
// CHECK: } // end sil function '$s8moveonly59testSubscriptGetModify_BaseLoadable_ResultAddressOnly_InOut1myAA0gcdE6TesterVz_tF'
|
|
public func testSubscriptGetModify_BaseLoadable_ResultAddressOnly_InOut(m: inout LoadableSubscriptGetModifyTester) {
|
|
m[0].nonMutatingFunc()
|
|
m[0] = AddressOnlyProtocol()
|
|
m[0].mutatingFunc()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @$s8moveonly60testSubscriptGetModify_BaseLoadable_ResultAddressOnly_GlobalyyF : $@convention(thin) () -> () {
|
|
// CHECK: [[GLOBAL_ADDR:%.*]] = global_addr @$s8moveonly38globalLoadableSubscriptGetModifyTesterAA0cdefG0Vvp :
|
|
//
|
|
// The get call
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [dynamic] [[GLOBAL_ADDR]]
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[ACCESS]]
|
|
// CHECK: [[LOAD_BORROW:%.*]] = load_borrow [[MARK]]
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $AddressOnlyProtocol
|
|
// CHECK: [[MARK_TEMP:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]], {{%.*}}, [[LOAD_BORROW]])
|
|
// CHECK: end_borrow [[LOAD_BORROW]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]])
|
|
// CHECK: destroy_addr [[MARK_TEMP]]
|
|
//
|
|
// The assignment:
|
|
// CHECK: [[GLOBAL_ADDR:%.*]] = global_addr @$s8moveonly38globalLoadableSubscriptGetModifyTesterAA0cdefG0Vvp :
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $AddressOnlyProtocol
|
|
// CHECK: [[MARK_TEMP:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]], {{%.*}}) : $@convention(method) (@thin AddressOnlyProtocol.Type) -> @out AddressOnlyProtocol
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [modify] [dynamic] [[GLOBAL_ADDR]]
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [assignable_but_not_consumable] [[ACCESS]]
|
|
// CHECK: ([[CORO_RESULT_ORIG:%.*]], [[CORO_TOKEN:%.*]]) = begin_apply {{%.*}}({{%.*}}, [[MARK]])
|
|
// CHECK: [[CORO_RESULT:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[CORO_RESULT_ORIG]]
|
|
// CHECK: copy_addr [take] [[MARK_TEMP]] to [[CORO_RESULT]]
|
|
// CHECK: end_apply [[CORO_TOKEN]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
//
|
|
// The mutating function call.
|
|
// CHECK: [[GLOBAL_ADDR:%.*]] = global_addr @$s8moveonly38globalLoadableSubscriptGetModifyTesterAA0cdefG0Vvp :
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [modify] [dynamic] [[GLOBAL_ADDR]]
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [assignable_but_not_consumable] [[ACCESS]]
|
|
// CHECK: ([[CORO_RESULT_ORIG:%.*]], [[CORO_TOKEN:%.*]]) = begin_apply {{%.*}}({{%.*}}, [[MARK]])
|
|
// CHECK: [[CORO_RESULT:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[CORO_RESULT_ORIG]]
|
|
// CHECK: apply {{%.*}}([[CORO_RESULT]])
|
|
// CHECK: end_apply [[CORO_TOKEN]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
//
|
|
// CHECK: } // end sil function '$s8moveonly60testSubscriptGetModify_BaseLoadable_ResultAddressOnly_GlobalyyF'
|
|
var globalLoadableSubscriptGetModifyTester = LoadableSubscriptGetModifyTester()
|
|
public func testSubscriptGetModify_BaseLoadable_ResultAddressOnly_Global() {
|
|
globalLoadableSubscriptGetModifyTester[0].nonMutatingFunc()
|
|
globalLoadableSubscriptGetModifyTester[0] = AddressOnlyProtocol()
|
|
globalLoadableSubscriptGetModifyTester[0].mutatingFunc()
|
|
}
|
|
|
|
// Make sure that we get the same behavior when we access through another noncopyable struct.
|
|
public struct LoadableSubscriptGetModifyTesterNonCopyableStructParent : ~Copyable {
|
|
var tester = LoadableSubscriptGetModifyTester()
|
|
var computedTester: LoadableSubscriptGetModifyTester { fatalError() }
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @$s8moveonly87testSubscriptGetModifyThroughNonCopyableParentStruct_BaseLoadable_ResultAddressOnly_VaryyF : $@convention(thin) () -> () {
|
|
// CHECK: [[BOX:%.*]] = alloc_box $
|
|
// CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [var_decl] [[BOX]]
|
|
// CHECK: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]]
|
|
//
|
|
// The first get call
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]]
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[ACCESS]]
|
|
// CHECK: [[GEP:%.*]] = struct_element_addr [[MARK]]
|
|
// CHECK: [[LOAD_BORROW:%.*]] = load_borrow [[GEP]]
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $AddressOnlyProtocol
|
|
// CHECK: [[MARK_TEMP:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]], {{%.*}}, [[LOAD_BORROW]])
|
|
// CHECK: end_borrow [[LOAD_BORROW]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]])
|
|
// CHECK: destroy_addr [[MARK_TEMP]]
|
|
//
|
|
// The mutating call.
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[PROJECT]]
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [assignable_but_not_consumable] [[ACCESS]]
|
|
// CHECK: [[GEP:%.*]] = struct_element_addr [[MARK]]
|
|
// CHECK: ([[CORO_RESULT_ORIG:%.*]], [[CORO_TOKEN:%.*]]) = begin_apply {{%.*}}({{%.*}}, [[GEP]])
|
|
// CHECK: [[CORO_RESULT:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[CORO_RESULT_ORIG]]
|
|
// CHECK: apply {{%.*}}([[CORO_RESULT]])
|
|
// CHECK: end_apply [[CORO_TOKEN]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
//
|
|
// The second get call.
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]]
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[ACCESS]]
|
|
// CHECK: [[LOAD_BORROW:%.*]] = load_borrow [unchecked] [[MARK]]
|
|
// CHECK: [[VALUE:%.*]] = apply {{%.*}}([[LOAD_BORROW]])
|
|
// CHECK: [[BORROWED_VALUE:%.*]] = begin_borrow [[VALUE]]
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $AddressOnlyProtocol
|
|
// CHECK: [[MARK_TEMP:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]], {{%.*}}, [[BORROWED_VALUE]])
|
|
// CHECK: end_borrow [[BORROWED_VALUE]]
|
|
// CHECK: end_borrow [[LOAD_BORROW]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]])
|
|
// CHECK: destroy_addr [[MARK_TEMP]]
|
|
// CHECK: destroy_value [[VALUE]]
|
|
// } // end sil function '$s8moveonly077testSubscriptGetModifyThroughNonCopyableParentStruct_BaseLoadable_ResultAddressE4_VaryyF'
|
|
public func testSubscriptGetModifyThroughNonCopyableParentStruct_BaseLoadable_ResultAddressOnly_Var() {
|
|
var m = LoadableSubscriptGetModifyTesterNonCopyableStructParent()
|
|
m = LoadableSubscriptGetModifyTesterNonCopyableStructParent()
|
|
m.tester[0].nonMutatingFunc()
|
|
m.tester[0].mutatingFunc()
|
|
m.computedTester[0].nonMutatingFunc()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @$s8moveonly87testSubscriptGetModifyThroughNonCopyableParentStruct_BaseLoadable_ResultAddressOnly_LetyyF : $@convention(thin) () -> () {
|
|
// CHECK: [[BOX:%.*]] = alloc_box ${ let L
|
|
// CHECK: [[BOX_LIFETIME:%.*]] = begin_borrow [lexical] [var_decl] [[BOX]]
|
|
// CHECK: [[PROJECT:%.*]] = project_box [[BOX_LIFETIME]]
|
|
//
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[PROJECT]]
|
|
// CHECK: [[LOAD:%.*]] = load_borrow [[MARK]]
|
|
// CHECK: [[EXT:%.*]] = struct_extract [[LOAD]]
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $AddressOnlyProtocol
|
|
// CHECK: [[MARK_TEMP:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]], {{%.*}}, [[EXT]])
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]])
|
|
// CHECK: destroy_addr [[MARK_TEMP]]
|
|
// CHECK: end_borrow [[LOAD]]
|
|
// CHECK: } // end sil function '$s8moveonly87testSubscriptGetModifyThroughNonCopyableParentStruct_BaseLoadable_ResultAddressOnly_LetyyF'
|
|
public func testSubscriptGetModifyThroughNonCopyableParentStruct_BaseLoadable_ResultAddressOnly_Let() {
|
|
let m = LoadableSubscriptGetModifyTesterNonCopyableStructParent()
|
|
m.tester[0].nonMutatingFunc()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @$s8moveonly90testSubscriptGetModifyThroughNonCopyableParentStruct_BaseLoadable_ResultAddressOnly_GlobalyyF : $@convention(thin) () -> () {
|
|
// CHECK: [[GLOBAL:%.*]] = global_addr @$s8moveonly61globalLoadableSubscriptGetModifyTesterNonCopyableStructParentAA0cdefghijK0Vvp :
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [dynamic] [[GLOBAL]]
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[ACCESS]]
|
|
// CHECK: [[GEP:%.*]] = struct_element_addr [[MARK]]
|
|
// CHECK: [[LOAD:%.*]] = load_borrow [[GEP]]
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $AddressOnlyProtocol
|
|
// CHECK: [[MARK_TEMP:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]], {{%.*}}, [[LOAD]])
|
|
// CHECK: end_borrow [[LOAD]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]])
|
|
// CHECK: destroy_addr [[MARK_TEMP]]
|
|
//
|
|
// CHECK: [[GLOBAL:%.*]] = global_addr @$s8moveonly61globalLoadableSubscriptGetModifyTesterNonCopyableStructParentAA0cdefghijK0Vvp :
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [modify] [dynamic] [[GLOBAL]]
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [assignable_but_not_consumable] [[ACCESS]]
|
|
// CHECK: [[GEP:%.*]] = struct_element_addr [[MARK]]
|
|
// CHECK: ([[CORO_RESULT_ORIG:%.*]], [[CORO_TOKEN:%.*]]) = begin_apply {{%.*}}({{%.*}}, [[GEP]])
|
|
// CHECK: [[CORO_RESULT:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[CORO_RESULT_ORIG]]
|
|
// CHECK: apply {{%.*}}([[CORO_RESULT]])
|
|
// CHECK: end_apply [[CORO_TOKEN]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: } // end sil function '$s8moveonly90testSubscriptGetModifyThroughNonCopyableParentStruct_BaseLoadable_ResultAddressOnly_GlobalyyF'
|
|
var globalLoadableSubscriptGetModifyTesterNonCopyableStructParent = LoadableSubscriptGetModifyTesterNonCopyableStructParent()
|
|
public func testSubscriptGetModifyThroughNonCopyableParentStruct_BaseLoadable_ResultAddressOnly_Global() {
|
|
globalLoadableSubscriptGetModifyTesterNonCopyableStructParent.tester[0].nonMutatingFunc()
|
|
globalLoadableSubscriptGetModifyTesterNonCopyableStructParent.tester[0].mutatingFunc()
|
|
}
|
|
|
|
public class LoadableSubscriptGetModifyTesterClassParent {
|
|
var tester = LoadableSubscriptGetModifyTester()
|
|
var computedTester: LoadableSubscriptGetModifyTester { fatalError() }
|
|
var computedTester2: LoadableSubscriptGetModifyTester {
|
|
get { fatalError() }
|
|
set { fatalError() }
|
|
}
|
|
var testerParent = LoadableSubscriptGetModifyTesterNonCopyableStructParent()
|
|
}
|
|
|
|
// CHECK-LABEL: sil [ossa] @$s8moveonly75testSubscriptGetModifyThroughParentClass_BaseLoadable_ResultAddressOnly_VaryyF : $@convention(thin) () -> () {
|
|
// CHECK: [[BOX:%.*]] = alloc_box $
|
|
// CHECK: [[BORROW:%.*]] = begin_borrow [lexical] [var_decl] [[BOX]]
|
|
// CHECK: [[PROJECT:%.*]] = project_box [[BORROW]]
|
|
//
|
|
// First read.
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]]
|
|
// CHECK: [[COPYABLE_CLASS:%.*]] = load [copy] [[ACCESS]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: [[BORROW_COPYABLE_CLASS:%.*]] = begin_borrow [[COPYABLE_CLASS]]
|
|
// CHECK: ([[CORO_RESULT_ORIG:%.*]], [[CORO_TOKEN:%.*]]) = begin_apply {{%.*}}([[BORROW_COPYABLE_CLASS]])
|
|
// CHECK: [[CORO_RESULT_CP:%.*]] = copy_value [[CORO_RESULT_ORIG]]
|
|
// CHECK: [[CORO_RESULT_MK:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[CORO_RESULT_CP]]
|
|
// CHECK: [[CORO_RESULT:%.*]] = begin_borrow [[CORO_RESULT_MK]]
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $
|
|
// CHECK: [[MARK_TEMP:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]], {{%.*}}, [[CORO_RESULT]])
|
|
// CHECK: end_apply [[CORO_TOKEN]]
|
|
// CHECK: end_borrow [[BORROW_COPYABLE_CLASS]]
|
|
// CHECK: destroy_value [[COPYABLE_CLASS]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]])
|
|
// CHECK: destroy_addr [[MARK_TEMP]]
|
|
//
|
|
// First mutation.
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]]
|
|
// CHECK: [[COPYABLE_CLASS:%.*]] = load [copy] [[ACCESS]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: [[BORROW_COPYABLE_CLASS:%.*]] = begin_borrow [[COPYABLE_CLASS]]
|
|
// CHECK: ([[CORO_RESULT_ORIG:%.*]], [[CORO_TOKEN:%.*]]) = begin_apply {{%.*}}([[BORROW_COPYABLE_CLASS]])
|
|
// CHECK: [[CORO_RESULT:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[CORO_RESULT_ORIG]]
|
|
// CHECK: ([[CORO_RESULT_2_ORIG:%.*]], [[CORO_TOKEN_2:%.*]]) = begin_apply {{%.*}}({{%.*}}, [[CORO_RESULT]])
|
|
// CHECK: [[CORO_RESULT_2:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[CORO_RESULT_2_ORIG]]
|
|
// CHECK: apply {{%.*}}([[CORO_RESULT_2]])
|
|
// CHECK: end_apply [[CORO_TOKEN_2]]
|
|
// CHECK: end_apply [[CORO_TOKEN]]
|
|
//
|
|
// Second read.
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]]
|
|
// CHECK: [[COPYABLE_CLASS:%.*]] = load [copy] [[ACCESS]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: [[BORROW_COPYABLE_CLASS:%.*]] = begin_borrow [[COPYABLE_CLASS]]
|
|
// CHECK: ([[CORO_RESULT_ORIG:%.*]], [[CORO_TOKEN:%.*]]) = begin_apply {{%.*}}([[BORROW_COPYABLE_CLASS]])
|
|
// CHECK: [[CORO_RESULT_CP:%.*]] = copy_value [[CORO_RESULT_ORIG]]
|
|
// CHECK: [[CORO_RESULT_MK:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[CORO_RESULT_CP]]
|
|
// CHECK: [[CORO_RESULT:%.*]] = begin_borrow [[CORO_RESULT_MK]]
|
|
// CHECK: [[EXT:%.*]] = struct_extract [[CORO_RESULT]]
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $
|
|
// CHECK: [[MARK_TEMP:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]], {{%.*}}, [[EXT]])
|
|
// CHECK: end_apply [[CORO_TOKEN]]
|
|
// CHECK: end_borrow [[BORROW_COPYABLE_CLASS]]
|
|
// CHECK: destroy_value [[COPYABLE_CLASS]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]])
|
|
// CHECK: destroy_addr [[MARK_TEMP]]
|
|
//
|
|
// Second mutate
|
|
//
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]]
|
|
// CHECK: [[COPYABLE_CLASS:%.*]] = load [copy] [[ACCESS]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: [[BORROW_COPYABLE_CLASS:%.*]] = begin_borrow [[COPYABLE_CLASS]]
|
|
// CHECK: ([[CORO_RESULT_ORIG:%.*]], [[CORO_TOKEN:%.*]]) = begin_apply {{%.*}}([[BORROW_COPYABLE_CLASS]])
|
|
// CHECK: [[CORO_RESULT:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[CORO_RESULT_ORIG]]
|
|
// CHECK: [[GEP:%.*]] = struct_element_addr [[CORO_RESULT]]
|
|
// CHECK: ([[CORO_RESULT_2_ORIG:%.*]], [[CORO_TOKEN_2:%.*]]) = begin_apply {{%.*}}({{%.*}}, [[GEP]])
|
|
// CHECK: [[CORO_RESULT_2:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[CORO_RESULT_2_ORIG]]
|
|
// CHECK: apply {{%.*}}([[CORO_RESULT_2]])
|
|
// CHECK: end_apply [[CORO_TOKEN_2]]
|
|
// CHECK: end_apply [[CORO_TOKEN]]
|
|
//
|
|
// Third read.
|
|
//
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]]
|
|
// CHECK: [[CLASS:%.*]] = load_borrow [unchecked] [[ACCESS]]
|
|
// CHECK: ([[CORO_RESULT_ORIG:%.*]], [[CORO_TOKEN:%.*]]) = begin_apply {{%.*}}([[CLASS]])
|
|
// CHECK: [[CORO_RESULT_CP:%.*]] = copy_value [[CORO_RESULT_ORIG]]
|
|
// CHECK: [[CORO_RESULT_MK:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[CORO_RESULT_CP]]
|
|
// CHECK: [[CORO_RESULT:%.*]] = begin_borrow [[CORO_RESULT_MK]]
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $
|
|
// CHECK: [[MARK_TEMP:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]], {{%.*}}, [[CORO_RESULT]])
|
|
// CHECK: end_apply [[CORO_TOKEN]]
|
|
// CHECK: end_borrow [[CLASS]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]])
|
|
// CHECK: destroy_addr [[MARK_TEMP]]
|
|
//
|
|
// First read
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]]
|
|
// CHECK: [[COPYABLE_CLASS:%.*]] = load [copy] [[ACCESS]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: [[BORROW_COPYABLE_CLASS:%.*]] = begin_borrow [[COPYABLE_CLASS]]
|
|
// CHECK: ([[CORO_RESULT_ORIG:%.*]], [[CORO_TOKEN:%.*]]) = begin_apply {{%.*}}([[BORROW_COPYABLE_CLASS]])
|
|
// CHECK: [[CORO_RESULT_CP:%.*]] = copy_value [[CORO_RESULT_ORIG]]
|
|
// CHECK: [[CORO_RESULT_MK:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[CORO_RESULT_CP]]
|
|
// CHECK: [[CORO_RESULT:%.*]] = begin_borrow [[CORO_RESULT_MK]]
|
|
// CHECK: [[TEMP:%.*]] = alloc_stack $
|
|
// CHECK: [[MARK_TEMP:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[TEMP]]
|
|
// Getter
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]], {{%.*}}, [[CORO_RESULT]])
|
|
// CHECK: end_apply [[CORO_TOKEN]]
|
|
// CHECK: apply {{%.*}}([[MARK_TEMP]])
|
|
// CHECK: destroy_addr [[MARK_TEMP]]
|
|
//
|
|
// Mutation
|
|
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJECT]]
|
|
// CHECK: [[COPYABLE_CLASS:%.*]] = load [copy] [[ACCESS]]
|
|
// CHECK: end_access [[ACCESS]]
|
|
// CHECK: [[BORROW_COPYABLE_CLASS:%.*]] = begin_borrow [[COPYABLE_CLASS]]
|
|
// CHECK: ([[CORO_RESULT_ORIG:%.*]], [[CORO_TOKEN:%.*]]) = begin_apply {{%.*}}([[BORROW_COPYABLE_CLASS]])
|
|
// CHECK: [[CORO_RESULT:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[CORO_RESULT_ORIG]]
|
|
// CHECK: ([[CORO_RESULT_2_ORIG:%.*]], [[CORO_TOKEN_2:%.*]]) = begin_apply {{%.*}}({{%.*}}, [[CORO_RESULT]])
|
|
// CHECK: [[CORO_RESULT_2:%.*]] = mark_unresolved_non_copyable_value [consumable_and_assignable] [[CORO_RESULT_2_ORIG]]
|
|
// CHECK: apply {{%.*}}([[CORO_RESULT_2]])
|
|
// CHECK: end_apply [[CORO_TOKEN_2]]
|
|
// CHECK: end_apply [[CORO_TOKEN]]
|
|
// CHECK: } // end sil function '$s8moveonly75testSubscriptGetModifyThroughParentClass_BaseLoadable_ResultAddressOnly_VaryyF'
|
|
public func testSubscriptGetModifyThroughParentClass_BaseLoadable_ResultAddressOnly_Var() {
|
|
var m = LoadableSubscriptGetModifyTesterClassParent()
|
|
m = LoadableSubscriptGetModifyTesterClassParent()
|
|
m.tester[0].nonMutatingFunc()
|
|
m.tester[0].mutatingFunc()
|
|
m.testerParent.tester[0].nonMutatingFunc()
|
|
m.testerParent.tester[0].mutatingFunc()
|
|
m.computedTester[0].nonMutatingFunc()
|
|
m.computedTester2[0].nonMutatingFunc()
|
|
m.computedTester2[0].mutatingFunc()
|
|
}
|
|
|
|
//////////////////////////////
|
|
// MARK: Capture Self Tests //
|
|
//////////////////////////////
|
|
|
|
func testSelfCaptureHandledCorrectly() {
|
|
struct E {
|
|
var a: [Int] = []
|
|
}
|
|
|
|
struct Test : ~Copyable {
|
|
var e: E
|
|
|
|
// Test that we capture inits by address.
|
|
//
|
|
// CHECK-LABEL: sil private [ossa] @$s8moveonly31testSelfCaptureHandledCorrectlyyyF4TestL_VADycfC : $@convention(method) (@thin Test.Type) -> @owned Test {
|
|
// CHECK: [[BOX:%.*]] = alloc_box ${ var Test }
|
|
// CHECK: [[MARK_UNINIT:%.*]] = mark_uninitialized [rootself] [[BOX]]
|
|
// CHECK: [[BORROW:%.*]] = begin_borrow [lexical] [var_decl] [[MARK_UNINIT]]
|
|
// CHECK: [[PROJECT:%.*]] = project_box [[BORROW]]
|
|
// CHECK: apply {{%.*}}([[PROJECT]])
|
|
// CHECK: } // end sil function '$s8moveonly31testSelfCaptureHandledCorrectlyyyF4TestL_VADycfC'
|
|
init() {
|
|
e = E()
|
|
func capture() {
|
|
let e = self.e
|
|
}
|
|
capture()
|
|
}
|
|
|
|
// CHECK-LABEL: sil private [ossa] @$s8moveonly31testSelfCaptureHandledCorrectlyyyF4TestL_V22captureByLocalFunctionyyF : $@convention(method) (@guaranteed Test) -> () {
|
|
// CHECK: bb0([[ARG:%.*]] : @guaranteed $Test):
|
|
// CHECK: [[COPY:%.*]] = copy_value [[ARG]]
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[COPY]]
|
|
// CHECK: [[BORROW:%.*]] = begin_borrow [[MARK]]
|
|
// CHECK: apply {{%.*}}([[BORROW]])
|
|
// CHECK: end_borrow [[BORROW]]
|
|
// CHECK: destroy_value [[MARK]]
|
|
// CHECK: } // end sil function '$s8moveonly31testSelfCaptureHandledCorrectlyyyF4TestL_V22captureByLocalFunctionyyF'
|
|
func captureByLocalFunction() {
|
|
func capture() {
|
|
let e = self.e
|
|
}
|
|
capture()
|
|
}
|
|
|
|
// CHECK-LABEL: sil private [ossa] @$s8moveonly31testSelfCaptureHandledCorrectlyyyF4TestL_V17captureByLocalLetyyF : $@convention(method) (@guaranteed Test) -> () {
|
|
// CHECK: bb0([[ARG:%.*]] : @guaranteed $Test):
|
|
// CHECK: [[COPY:%.*]] = copy_value [[ARG]]
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[COPY]]
|
|
// CHECK: [[COPY2:%.*]] = copy_value [[MARK]]
|
|
// CHECK: [[PAI:%.*]] = partial_apply [callee_guaranteed] {{%.*}}([[COPY2]])
|
|
// CHECK: destroy_value [[MARK]]
|
|
// CHECK: } // end sil function '$s8moveonly31testSelfCaptureHandledCorrectlyyyF4TestL_V17captureByLocalLetyyF'
|
|
func captureByLocalLet() {
|
|
let f = {
|
|
let e = self.e
|
|
}
|
|
|
|
f()
|
|
}
|
|
|
|
// CHECK-LABEL: sil private [ossa] @$s8moveonly31testSelfCaptureHandledCorrectlyyyF4TestL_V17captureByLocalVaryyF : $@convention(method) (@guaranteed Test) -> () {
|
|
// CHECK: bb0([[ARG:%.*]] : @guaranteed $Test):
|
|
// CHECK: [[COPY:%.*]] = copy_value [[ARG]]
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[COPY]]
|
|
// CHECK: [[COPY2:%.*]] = copy_value [[MARK]]
|
|
// CHECK: [[PAI:%.*]] = partial_apply [callee_guaranteed] {{%.*}}([[COPY2]])
|
|
// CHECK: destroy_value [[MARK]]
|
|
// CHECK: } // end sil function '$s8moveonly31testSelfCaptureHandledCorrectlyyyF4TestL_V17captureByLocalVaryyF'
|
|
func captureByLocalVar() {
|
|
var f = {}
|
|
f = {
|
|
let e = self.e
|
|
}
|
|
f()
|
|
}
|
|
|
|
// CHECK-LABEL: sil private [ossa] @$s8moveonly31testSelfCaptureHandledCorrectlyyyF4TestL_V27captureByNonEscapingClosureyyF : $@convention(method) (@guaranteed Test) -> () {
|
|
// CHECK: bb0([[ARG:%.*]] : @guaranteed $Test):
|
|
// CHECK: [[COPY:%.*]] = copy_value [[ARG]]
|
|
// CHECK: [[MARK:%.*]] = mark_unresolved_non_copyable_value [no_consume_or_assign] [[COPY]]
|
|
// CHECK: [[COPY2:%.*]] = copy_value [[MARK]]
|
|
// CHECK: [[PAI:%.*]] = partial_apply [callee_guaranteed] {{%.*}}([[COPY2]])
|
|
// CHECK: destroy_value [[MARK]]
|
|
// CHECK: } // end sil function '$s8moveonly31testSelfCaptureHandledCorrectlyyyF4TestL_V27captureByNonEscapingClosureyyF'
|
|
func captureByNonEscapingClosure() {
|
|
func useClosure(_ f: () -> ()) {}
|
|
useClosure {
|
|
let e = self.e
|
|
}
|
|
}
|
|
}
|
|
}
|