Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -7119,6 +7119,8 @@ ERROR(ownership_specifier_copyable,none,
ERROR(self_ownership_specifier_copyable,none,
"%0 is not yet valid on %1s in a Copyable type",
(SelfAccessKind, DescriptiveDeclKind))
ERROR(ownership_specifier_nonescaping_closure,none,
"'%0' cannot be applied to nonescaping closure", (StringRef))

//------------------------------------------------------------------------------
// MARK: Runtime discoverable attributes (@runtimeMetadata)
Expand Down
38 changes: 24 additions & 14 deletions lib/Sema/TypeCheckType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4283,20 +4283,30 @@ TypeResolver::resolveOwnershipTypeRepr(OwnershipTypeRepr *repr,
if (result->hasError())
return result;

// Unless we have the experimental no-implicit-copy feature enabled, Copyable
// types can't use 'consuming' or 'borrowing' ownership specifiers.
if (!getASTContext().LangOpts.hasFeature(Feature::NoImplicitCopy)) {
if (!result->isPureMoveOnly()) {
// Prevent copyable types from using the non-underscored ownership parameter
// specifiers, other than 'inout'.
switch (ownershipRepr->getSpecifier()) {
case ParamSpecifier::Default:
case ParamSpecifier::InOut:
case ParamSpecifier::LegacyShared:
case ParamSpecifier::LegacyOwned:break;

case ParamSpecifier::Borrowing:
case ParamSpecifier::Consuming:
// Check for illegal combinations of ownership specifiers and types.
switch (ownershipRepr->getSpecifier()) {
case ParamSpecifier::Default:
case ParamSpecifier::InOut:
case ParamSpecifier::LegacyShared:
case ParamSpecifier::LegacyOwned:
break;

case ParamSpecifier::Consuming:
if (auto *fnTy = result->getAs<FunctionType>()) {
if (fnTy->isNoEscape()) {
diagnoseInvalid(ownershipRepr,
ownershipRepr->getLoc(),
diag::ownership_specifier_nonescaping_closure,
ownershipRepr->getSpecifierSpelling());
return ErrorType::get(getASTContext());
}
}
SWIFT_FALLTHROUGH;
case ParamSpecifier::Borrowing:
// Unless we have the experimental no-implicit-copy feature enabled, Copyable
// types can't use 'consuming' or 'borrowing' ownership specifiers.
if (!getASTContext().LangOpts.hasFeature(Feature::NoImplicitCopy)) {
if (!result->isPureMoveOnly()) {
diagnoseInvalid(ownershipRepr,
ownershipRepr->getLoc(),
diag::ownership_specifier_copyable);
Expand Down
6 changes: 6 additions & 0 deletions test/Parse/ownership_modifiers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -101,3 +101,9 @@ enum Exercising {
__consuming get { 0 }
}
}

func consumingClosure1(_ f: consuming () -> ()) { } // expected-error {{'consuming' cannot be applied to nonescaping closure}}
func consumingClosure2(_ f: consuming @escaping () -> ()) { } // expected-error {{Copyable types cannot be 'consuming' or 'borrowing' yet}}

func borrowingClosure1(_ f: borrowing () -> ()) { } // expected-error {{Copyable types cannot be 'consuming' or 'borrowing' yet}}
func borrowingClosure2(_ f: borrowing @escaping () -> ()) { } // expected-error {{Copyable types cannot be 'consuming' or 'borrowing' yet}}
253 changes: 0 additions & 253 deletions test/SILGen/moveonly_escaping_closure.swift
Original file line number Diff line number Diff line change
Expand Up @@ -257,71 +257,6 @@ func testInOutVarClosureCaptureVar(_ f: inout () -> ()) {
f()
}

// CHECK-LABEL: sil hidden [ossa] @$s16moveonly_closure38testConsumingNoEscapeClosureCaptureVaryyyyXEnF : $@convention(thin) (@owned @noescape @callee_guaranteed () -> ()) -> () {
// CHECK: bb0([[ARG:%.*]] : @_eagerMove @owned
// CHECK: [[FUNC_BOX:%.*]] = alloc_box ${ var @noescape @callee_guaranteed () -> () }
// CHECK: [[FUNC_PROJECT:%.*]] = project_box [[FUNC_BOX]]
// CHECK: store [[ARG]] to [init] [[FUNC_PROJECT]]
//
// CHECK: [[BOX:%.*]] = alloc_box ${ var SingleElt }
// CHECK: [[PROJECT:%.*]] = project_box [[BOX]]
// CHECK: [[CLOSURE:%.*]] = function_ref @$s16moveonly_closure38testConsumingNoEscapeClosureCaptureVaryyyyXEnFyyXEfU_ : $@convention(thin) (@inout_aliasable SingleElt) -> ()
// CHECK: [[PAI:%.*]] = partial_apply [callee_guaranteed] [[CLOSURE]]([[PROJECT]])
// CHECK: [[NO_ESCAPE:%.*]] = convert_escape_to_noescape [not_guaranteed] [[PAI]]
// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[FUNC_PROJECT]]
// CHECK: assign [[NO_ESCAPE]] to [[ACCESS]]
// CHECK: end_access [[ACCESS]]
// CHECK: } // end sil function '$s16moveonly_closure38testConsumingNoEscapeClosureCaptureVaryyyyXEnF'
//
// CHECK-LABEL: sil private [ossa] @$s16moveonly_closure38testConsumingNoEscapeClosureCaptureVaryyyyXEnFyyXEfU_ : $@convention(thin) (@inout_aliasable SingleElt) -> () {
// CHECK: bb0([[ARG:%.*]] :
// CHECK: [[CHECK:%.*]] = mark_must_check [consumable_and_assignable] [[ARG]]
//
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[CHECK]]
// CHECK: [[LOADED:%.*]] = load [copy] [[ACCESS]]
// CHECK: apply {{%.*}}([[LOADED]])
// CHECK: destroy_value [[LOADED]]
// CHECK: end_access [[ACCESS]]
//
// CHECK: [[ACCESS:%.*]] = begin_access [deinit] [unknown] [[CHECK]]
// CHECK: [[LOADED:%.*]] = load [take] [[ACCESS]]
// CHECK: apply {{%.*}}([[LOADED]])
// CHECK: end_access [[ACCESS]]
//
// CHECK: [[ACCESS:%.*]] = begin_access [deinit] [unknown] [[CHECK]]
// CHECK: [[LOADED:%.*]] = load [take] [[ACCESS]]
// CHECK: apply {{%.*}}([[LOADED]])
// CHECK: end_access [[ACCESS]]
//
// CHECK: [[READ_ACCESS:%.*]] = begin_access [read] [unknown] [[CHECK]]
// CHECK: [[LOADED_READ:%.*]] = load [copy] [[READ_ACCESS]]
// CHECK: [[DEINIT_ACCESS:%.*]] = begin_access [deinit] [unknown] [[CHECK]]
// CHECK: [[LOADED_TAKE:%.*]] = load [take] [[DEINIT_ACCESS]]
// CHECK: apply {{%.*}}([[LOADED_READ]], [[LOADED_TAKE]])
// CHECK: end_access [[DEINIT_ACCESS]]
// CHECK: destroy_value [[LOADED_READ]]
// CHECK: end_access [[READ_ACCESS]]
// CHECK: } // end sil function '$s16moveonly_closure38testConsumingNoEscapeClosureCaptureVaryyyyXEnFyyXEfU_'
func testConsumingNoEscapeClosureCaptureVar(_ f: consuming () -> ()) {
var x = SingleElt()
// expected-error @-1 {{'x' used after consume}}
// expected-error @-2 {{'x' used after consume}}
// expected-error @-3 {{'x' consumed more than once}}
x = SingleElt()
f = {
borrowVal(x)
consumeVal(x) // expected-note {{consuming use here}}
consumeVal(x) // expected-note {{consuming use here}}
// expected-note @-1 {{consuming use here}}
borrowConsumeVal(x, x)
// expected-note @-1 {{consuming use here}}
// expected-note @-2 {{consuming use here}}
// expected-note @-3 {{non-consuming use here}}
// expected-error @-4 {{overlapping accesses to 'x', but deinitialization requires exclusive access}}
// expected-note @-5 {{conflicting access is here}}
}
f()
}

// CHECK-LABEL: sil hidden [ossa] @$s16moveonly_closure36testConsumingEscapeClosureCaptureVaryyyycnF : $@convention(thin) (@owned @callee_guaranteed () -> ()) -> () {
// CHECK: bb0([[ARG:%.*]] : @_eagerMove @owned
Expand Down Expand Up @@ -579,39 +514,6 @@ func testInOutVarClosureCaptureLet(_ f: inout () -> ()) {
f()
}

// CHECK-LABEL: sil hidden [ossa] @$s16moveonly_closure38testConsumingNoEscapeClosureCaptureLetyyyyXEnF : $@convention(thin) (@owned @noescape @callee_guaranteed () -> ()) -> () {
// CHECK: bb0([[ARG:%.*]] :
// CHECK: [[FUNC_BOX:%.*]] = alloc_box ${ var @noescape @callee_guaranteed () -> () }
// CHECK: [[FUNC_PROJECT:%.*]] = project_box [[FUNC_BOX]]
// CHECK: store [[ARG]] to [init] [[FUNC_PROJECT]]
//
// CHECK: [[BOX:%.*]] = alloc_box ${ let SingleElt }
// CHECK: [[PROJECT:%.*]] = project_box [[BOX]]
// CHECK: [[CLOSURE:%.*]] = function_ref @$s16moveonly_closure38testConsumingNoEscapeClosureCaptureLetyyyyXEnFyyXEfU_ : $@convention(thin) (@guaranteed SingleElt) -> ()
// CHECK: [[MARKED:%.*]] = mark_must_check [assignable_but_not_consumable] [[PROJECT]]
// CHECK: [[LOADED_VALUE:%.*]] = load [copy] [[MARKED]]
// CHECK: [[PAI:%.*]] = partial_apply [callee_guaranteed] [[CLOSURE]]([[LOADED_VALUE]])
// CHECK: [[NO_ESCAPE:%.*]] = convert_escape_to_noescape [not_guaranteed] [[PAI]]
// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[FUNC_PROJECT]]
// CHECK: assign [[NO_ESCAPE]] to [[ACCESS]]
// CHECK: end_access [[ACCESS]]
// CHECK: } // end sil function '$s16moveonly_closure38testConsumingNoEscapeClosureCaptureLetyyyyXEnF'
//
// CHECK-LABEL: sil private [ossa] @$s16moveonly_closure38testConsumingNoEscapeClosureCaptureLetyyyyXEnFyyXEfU_ : $@convention(thin) (@guaranteed SingleElt) -> () {
// CHECK: bb0([[ARG:%.*]] :
// CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
// CHECK: [[CHECK:%.*]] = mark_must_check [no_consume_or_assign] [[ARG_COPY]]
// CHECK: } // end sil function '$s16moveonly_closure38testConsumingNoEscapeClosureCaptureLetyyyyXEnFyyXEfU_'
func testConsumingNoEscapeClosureCaptureLet(_ f: consuming () -> ()) {
let x = SingleElt() // expected-error {{'x' consumed and used at the same time}}
f = {
borrowVal(x)
consumeVal(x)
consumeVal(x)
borrowConsumeVal(x, x) // expected-note {{consuming and non-consuming uses here}}
}
f()
}

// CHECK-LABEL: sil hidden [ossa] @$s16moveonly_closure36testConsumingEscapeClosureCaptureLetyyyycnF : $@convention(thin) (@owned @callee_guaranteed () -> ()) -> () {
// CHECK: bb0([[ARG:%.*]] : @_eagerMove @owned
Expand Down Expand Up @@ -869,63 +771,6 @@ func testInOutVarClosureCaptureInOut(_ f: inout () -> (), _ x: inout SingleElt)
f()
}

// CHECK-LABEL: sil hidden [ossa] @$s16moveonly_closure40testConsumingNoEscapeClosureCaptureInOutyyyyXEn_AA9SingleEltVztF : $@convention(thin) (@owned @noescape @callee_guaranteed () -> (), @inout SingleElt) -> () {
// CHECK: bb0([[OWNED_F:%.*]] : @_eagerMove @owned $@noescape @callee_guaranteed () -> (), [[PROJECT:%.*]] : $*SingleElt):
// CHECK: [[FUNC_BOX:%.*]] = alloc_box ${ var @noescape @callee_guaranteed () -> () }
// CHECK: [[FUNC_PROJECT:%.*]] = project_box [[FUNC_BOX]]
// CHECK: store [[OWNED_F]] to [init] [[FUNC_PROJECT]]
//
// CHECK: [[MARKED_PROJECT:%.*]] = mark_must_check [consumable_and_assignable] [[PROJECT]]
// CHECK: [[CLOSURE:%.*]] = function_ref @$s16moveonly_closure40testConsumingNoEscapeClosureCaptureInOutyyyyXEn_AA9SingleEltVztFyyXEfU_ : $@convention(thin) (@inout_aliasable SingleElt) -> ()
// CHECK: [[PAI:%.*]] = partial_apply [callee_guaranteed] [[CLOSURE]]([[MARKED_PROJECT]])
// CHECK: [[NO_ESCAPE:%.*]] = convert_escape_to_noescape [not_guaranteed] [[PAI]]
// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[FUNC_PROJECT]]
// CHECK: assign [[NO_ESCAPE]] to [[ACCESS]]
// CHECK: end_access [[ACCESS]]
// CHECK: } // end sil function '$s16moveonly_closure40testConsumingNoEscapeClosureCaptureInOutyyyyXEn_AA9SingleEltVztF'
//
// CHECK-LABEL: sil private [ossa] @$s16moveonly_closure40testConsumingNoEscapeClosureCaptureInOutyyyyXEn_AA9SingleEltVztFyyXEfU_ : $@convention(thin) (@inout_aliasable SingleElt) -> () {
// CHECK: bb0([[PROJECT:%.*]] : @closureCapture
// CHECK: [[MARKED:%.*]] = mark_must_check [consumable_and_assignable] [[PROJECT]]
//
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[MARKED]]
// CHECK: [[LOADED:%.*]] = load [copy] [[ACCESS]]
// CHECK: apply {{%.*}}([[LOADED]])
// CHECK: destroy_value [[LOADED]]
//
// CHECK: [[ACCESS:%.*]] = begin_access [deinit] [unknown] [[MARKED]]
// CHECK: [[LOADED:%.*]] = load [take] [[ACCESS]]
// CHECK: apply {{%.*}}([[LOADED]])
//
// CHECK: [[ACCESS:%.*]] = begin_access [deinit] [unknown] [[MARKED]]
// CHECK: [[LOADED:%.*]] = load [take] [[ACCESS]]
// CHECK: apply {{%.*}}([[LOADED]])
//
// CHECK: [[READ_ACCESS:%.*]] = begin_access [read] [unknown] [[MARKED]]
// CHECK: [[LOADED_READ:%.*]] = load [copy] [[READ_ACCESS]]
// CHECK: [[TAKE_ACCESS:%.*]] = begin_access [deinit] [unknown] [[MARKED]]
// CHECK: [[LOADED_TAKE:%.*]] = load [take] [[TAKE_ACCESS]]
// CHECK: apply {{%.*}}([[LOADED_READ]], [[LOADED_TAKE]])
// CHECK: } // end sil function '$s16moveonly_closure40testConsumingNoEscapeClosureCaptureInOutyyyyXEn_AA9SingleEltVztFyyXEfU_'
func testConsumingNoEscapeClosureCaptureInOut(_ f: consuming () -> (), _ x: inout SingleElt) {
// expected-error @-1 {{'x' consumed but not reinitialized before end of function}}
// expected-error @-2 {{'x' used after consume}}
// expected-error @-3 {{'x' consumed more than once}}
// expected-error @-4 {{'x' used after consume}}
f = { // expected-note {{consuming use here}}
borrowVal(x)
consumeVal(x) // expected-note {{consuming use here}}
consumeVal(x) // expected-note {{consuming use here}}
// expected-note @-1 {{consuming use here}}
borrowConsumeVal(x, x)
// expected-error @-1 {{overlapping accesses to 'x', but deinitialization requires exclusive access}}
// expected-note @-2 {{conflicting access is here}}
// expected-note @-3 {{non-consuming use here}}
// expected-note @-4 {{non-consuming use here}}
// expected-note @-5 {{consuming use here}}
}
f()
}

// CHECK-LABEL: sil hidden [ossa] @$s16moveonly_closure38testConsumingEscapeClosureCaptureInOutyyyycn_AA9SingleEltVztF : $@convention(thin) (@owned @callee_guaranteed () -> (), @inout SingleElt) -> () {
// CHECK: bb0([[FUNC_ARG:%.*]] : @_eagerMove @owned $@callee_guaranteed () -> (), [[PROJECT:%.*]] : $*SingleElt):
Expand Down Expand Up @@ -1159,70 +1004,6 @@ func testLocalVarClosureCaptureConsuming(_ x: consuming SingleElt) {
f()
}

// CHECK-LABEL: sil hidden [ossa] @$s16moveonly_closure035testConsumingNoEscapeClosureCaptureD0yyyyXEn_AA9SingleEltVntF : $@convention(thin) (@owned @noescape @callee_guaranteed () -> (), @owned SingleElt) -> () {
// CHECK: bb0([[F:%.*]] : @_eagerMove @owned $@noescape @callee_guaranteed () -> (),
// CHECK: [[FUNC_BOX:%.*]] = alloc_box ${ var @noescape @callee_guaranteed () -> () }
// CHECK: [[FUNC_PROJECT:%.*]] = project_box [[FUNC_BOX]]
// CHECK: store [[F]] to [init] [[FUNC_PROJECT]]
//
// CHECK: [[BOX:%.*]] = alloc_box ${ var SingleElt }
// CHECK: [[PROJECT:%.*]] = project_box [[BOX]]
// CHECK: [[CLOSURE:%.*]] = function_ref @$s16moveonly_closure035testConsumingNoEscapeClosureCaptureD0yyyyXEn_AA9SingleEltVntFyyXEfU_ : $@convention(thin) (@inout_aliasable SingleElt) -> ()
// CHECK: [[PAI:%.*]] = partial_apply [callee_guaranteed] [[CLOSURE]]([[PROJECT]])
// CHECK: [[NO_ESCAPE:%.*]] = convert_escape_to_noescape [not_guaranteed] [[PAI]]
// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[FUNC_PROJECT]]
// CHECK: assign [[NO_ESCAPE]] to [[ACCESS]]
// CHECK: end_access [[ACCESS]]
// CHECK: } // end sil function '$s16moveonly_closure035testConsumingNoEscapeClosureCaptureD0yyyyXEn_AA9SingleEltVntF'
//
// CHECK-LABEL: sil private [ossa] @$s16moveonly_closure035testConsumingNoEscapeClosureCaptureD0yyyyXEn_AA9SingleEltVntFyyXEfU_ : $@convention(thin) (@inout_aliasable SingleElt) -> () {
// CHECK: bb0([[ARG:%.*]] :
// CHECK: [[CHECK:%.*]] = mark_must_check [consumable_and_assignable] [[ARG]]
//
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[CHECK]]
// CHECK: [[LOADED:%.*]] = load [copy] [[ACCESS]]
// CHECK: apply {{%.*}}([[LOADED]])
// CHECK: destroy_value [[LOADED]]
// CHECK: end_access [[ACCESS]]
//
// CHECK: [[ACCESS:%.*]] = begin_access [deinit] [unknown] [[CHECK]]
// CHECK: [[LOADED:%.*]] = load [take] [[ACCESS]]
// CHECK: apply {{%.*}}([[LOADED]])
// CHECK: end_access [[ACCESS]]
//
// CHECK: [[ACCESS:%.*]] = begin_access [deinit] [unknown] [[CHECK]]
// CHECK: [[LOADED:%.*]] = load [take] [[ACCESS]]
// CHECK: apply {{%.*}}([[LOADED]])
// CHECK: end_access [[ACCESS]]
//
// CHECK: [[READ_ACCESS:%.*]] = begin_access [read] [unknown] [[CHECK]]
// CHECK: [[LOADED_READ:%.*]] = load [copy] [[READ_ACCESS]]
// CHECK: [[DEINIT_ACCESS:%.*]] = begin_access [deinit] [unknown] [[CHECK]]
// CHECK: [[LOADED_TAKE:%.*]] = load [take] [[DEINIT_ACCESS]]
// CHECK: apply {{%.*}}([[LOADED_READ]], [[LOADED_TAKE]])
// CHECK: end_access [[DEINIT_ACCESS]]
// CHECK: destroy_value [[LOADED_READ]]
// CHECK: end_access [[READ_ACCESS]]
// CHECK: } // end sil function '$s16moveonly_closure035testConsumingNoEscapeClosureCaptureD0yyyyXEn_AA9SingleEltVntFyyXEfU_'
func testConsumingNoEscapeClosureCaptureConsuming(_ f: consuming () -> (),
_ x: consuming SingleElt) {
// expected-error @-1 {{'x' consumed more than once}}
// expected-error @-2 {{'x' used after consume}}
// expected-error @-3 {{'x' used after consume}}
f = {
borrowVal(x)
consumeVal(x) // expected-note {{consuming use here}}
consumeVal(x) // expected-note {{consuming use here}}
// expected-note @-1 {{consuming use here}}
borrowConsumeVal(x, x)
// expected-note @-1 {{consuming use here}}
// expected-note @-2 {{consuming use here}}
// expected-note @-3 {{non-consuming use here}}
// expected-error @-4 {{overlapping accesses to 'x', but deinitialization requires exclusive access}}
// expected-note @-5 {{conflicting access is here}}
}
f()
}

// CHECK-LABEL: sil hidden [ossa] @$s16moveonly_closure033testConsumingEscapeClosureCaptureD0yyyycn_AA9SingleEltVntF : $@convention(thin) (@owned @callee_guaranteed () -> (), @owned SingleElt) -> () {
// CHECK: bb0([[ARG:%.*]] : @_eagerMove @owned $@callee_guaranteed () -> (),
Expand Down Expand Up @@ -1474,40 +1255,6 @@ func testInOutVarClosureCaptureOwned(_ f: inout () -> (), _ x: __owned SingleElt
f()
}

// CHECK-LABEL: sil hidden [ossa] @$s16moveonly_closure40testConsumingNoEscapeClosureCaptureOwnedyyyyXEn_AA9SingleEltVntF : $@convention(thin) (@owned @noescape @callee_guaranteed () -> (), @owned SingleElt) -> () {
// CHECK: bb0([[ARG:%.*]] : @_eagerMove @owned $@noescape @callee_guaranteed () -> (),
// CHECK: [[FUNC_BOX:%.*]] = alloc_box ${ var @noescape @callee_guaranteed () -> () }
// CHECK: [[FUNC_PROJECT:%.*]] = project_box [[FUNC_BOX]]
// CHECK: store [[ARG]] to [init] [[FUNC_PROJECT]]
//
// CHECK: [[BOX:%.*]] = alloc_box ${ let SingleElt }
// CHECK: [[PROJECT:%.*]] = project_box [[BOX]]
// CHECK: [[CLOSURE:%.*]] = function_ref @$s16moveonly_closure40testConsumingNoEscapeClosureCaptureOwnedyyyyXEn_AA9SingleEltVntFyyXEfU_ : $@convention(thin) (@guaranteed SingleElt) -> ()
// CHECK: [[MARKED:%.*]] = mark_must_check [assignable_but_not_consumable] [[PROJECT]]
// CHECK: [[LOADED_VALUE:%.*]] = load [copy] [[MARKED]]
// CHECK: [[PAI:%.*]] = partial_apply [callee_guaranteed] [[CLOSURE]]([[LOADED_VALUE]])
// CHECK: [[NO_ESCAPE:%.*]] = convert_escape_to_noescape [not_guaranteed] [[PAI]]
// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[FUNC_PROJECT]]
// CHECK: assign [[NO_ESCAPE]] to [[ACCESS]]
// CHECK: end_access [[ACCESS]]
// CHECK: } // end sil function '$s16moveonly_closure40testConsumingNoEscapeClosureCaptureOwnedyyyyXEn_AA9SingleEltVntF'
//
// CHECK-LABEL: sil private [ossa] @$s16moveonly_closure40testConsumingNoEscapeClosureCaptureOwnedyyyyXEn_AA9SingleEltVntFyyXEfU_ : $@convention(thin) (@guaranteed SingleElt) -> () {
// CHECK: bb0([[ARG:%.*]] :
// CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
// CHECK: [[CHECK:%.*]] = mark_must_check [no_consume_or_assign] [[ARG_COPY]]
// CHECK: } // end sil function '$s16moveonly_closure40testConsumingNoEscapeClosureCaptureOwnedyyyyXEn_AA9SingleEltVntFyyXEfU_'
func testConsumingNoEscapeClosureCaptureOwned(_ f: consuming () -> (),
_ x: __owned SingleElt) {
// expected-error @-1 {{'x' consumed and used at the same time}}
f = {
borrowVal(x)
consumeVal(x)
consumeVal(x)
borrowConsumeVal(x, x) // expected-note {{consuming and non-consuming uses here}}
}
f()
}

// CHECK-LABEL: sil hidden [ossa] @$s16moveonly_closure38testConsumingEscapeClosureCaptureOwnedyyyycn_AA9SingleEltVntF : $@convention(thin) (@owned @callee_guaranteed () -> (), @owned SingleElt) -> () {
// CHECK: bb0([[ARG:%.*]] : @_eagerMove @owned $@callee_guaranteed () -> (),
Expand Down