File tree Expand file tree Collapse file tree 2 files changed +43
-5
lines changed Expand file tree Collapse file tree 2 files changed +43
-5
lines changed Original file line number Diff line number Diff line change @@ -675,24 +675,30 @@ static bool isSupportedClosure(const SILInstruction *Closure) {
675675 return false ;
676676
677677 if (auto *PAI = dyn_cast<PartialApplyInst>(Closure)) {
678- // Bail if any of the arguments are passed by address and
679- // are not @inout.
680- // This is a temporary limitation.
678+ // Check whether each argument is supported.
681679 auto ClosureCallee = FRI->getReferencedFunction ();
682680 auto ClosureCalleeConv = ClosureCallee->getConventions ();
683681 unsigned ClosureArgIdxBase =
684682 ClosureCalleeConv.getNumSILArguments () - PAI->getNumArguments ();
685683 for (auto pair : llvm::enumerate (PAI->getArguments ())) {
686684 auto Arg = pair.value ();
687685 auto ClosureArgIdx = pair.index () + ClosureArgIdxBase;
686+ auto ArgConvention =
687+ ClosureCalleeConv.getSILArgumentConvention (ClosureArgIdx);
688+
688689 SILType ArgTy = Arg->getType ();
690+ // Specializing (currently) always produces a retain in the caller.
691+ // That's not allowed for values of move-only type.
692+ if (ArgTy.isMoveOnly ()) {
693+ return false ;
694+ }
695+
696+ // Only @inout/@inout_aliasable addresses are (currently) supported.
689697 // If our argument is an object, continue...
690698 if (ArgTy.isObject ()) {
691699 ++ClosureArgIdx;
692700 continue ;
693701 }
694- auto ArgConvention =
695- ClosureCalleeConv.getSILArgumentConvention (ClosureArgIdx);
696702 if (ArgConvention != SILArgumentConvention::Indirect_Inout &&
697703 ArgConvention != SILArgumentConvention::Indirect_InoutAliasable)
698704 return false ;
Original file line number Diff line number Diff line change @@ -938,3 +938,35 @@ bb0(%0 : $Int):
938938 %empty = tuple ()
939939 return %empty : $()
940940}
941+
942+ struct NC : ~Copyable {
943+ deinit {}
944+ }
945+
946+ sil hidden [noinline] @noncopyable_arg_closure : $@convention(thin) (@guaranteed NC) -> () {
947+ bb0(%0 : $NC):
948+ %retval = tuple ()
949+ return %retval : $()
950+ }
951+
952+ sil hidden [noinline] @use_noncopyable_arg_closure : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> () {
953+ bb0(%0 : $@noescape @callee_guaranteed () -> ()):
954+ %2 = apply %0() : $@noescape @callee_guaranteed () -> ()
955+ %3 = tuple ()
956+ return %3 : $()
957+ }
958+
959+ // Ensure that a retain_value of a noncopyable value isn't created.
960+ // CHECK-LABEL: sil @dont_specialize_noncopyable_arg_closure : {{.*}} {
961+ // CHECK-NOT: retain_value {{%.*}} : $NC
962+ // CHECK-LABEL: } // end sil function 'dont_specialize_noncopyable_arg_closure'
963+ sil @dont_specialize_noncopyable_arg_closure : $@convention(thin) (@guaranteed NC) -> () {
964+ bb0(%nc : $NC):
965+ %closure_fn = function_ref @noncopyable_arg_closure : $@convention(thin) (@guaranteed NC) -> ()
966+ %closure = partial_apply [callee_guaranteed] [on_stack] %closure_fn(%nc) : $@convention(thin) (@guaranteed NC) -> ()
967+ %use = function_ref @use_noncopyable_arg_closure : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
968+ apply %use(%closure) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
969+ dealloc_stack %closure : $@noescape @callee_guaranteed () -> ()
970+ %11 = tuple ()
971+ return %11 : $()
972+ }
You can’t perform that action at this time.
0 commit comments