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 @@ -576,24 +576,30 @@ static bool isSupportedClosure(const SILInstruction *Closure) {
576
576
return false ;
577
577
578
578
if (auto *PAI = dyn_cast<PartialApplyInst>(Closure)) {
579
- // Bail if any of the arguments are passed by address and
580
- // are not @inout.
581
- // This is a temporary limitation.
579
+ // Check whether each argument is supported.
582
580
auto ClosureCallee = FRI->getReferencedFunction ();
583
581
auto ClosureCalleeConv = ClosureCallee->getConventions ();
584
582
unsigned ClosureArgIdxBase =
585
583
ClosureCalleeConv.getNumSILArguments () - PAI->getNumArguments ();
586
584
for (auto pair : llvm::enumerate (PAI->getArguments ())) {
587
585
auto Arg = pair.value ();
588
586
auto ClosureArgIdx = pair.index () + ClosureArgIdxBase;
587
+ auto ArgConvention =
588
+ ClosureCalleeConv.getSILArgumentConvention (ClosureArgIdx);
589
+
589
590
SILType ArgTy = Arg->getType ();
591
+ // Specializing (currently) always produces a retain in the caller.
592
+ // That's not allowed for values of move-only type.
593
+ if (ArgTy.isMoveOnly ()) {
594
+ return false ;
595
+ }
596
+
597
+ // Only @inout/@inout_aliasable addresses are (currently) supported.
590
598
// If our argument is an object, continue...
591
599
if (ArgTy.isObject ()) {
592
600
++ClosureArgIdx;
593
601
continue ;
594
602
}
595
- auto ArgConvention =
596
- ClosureCalleeConv.getSILArgumentConvention (ClosureArgIdx);
597
603
if (ArgConvention != SILArgumentConvention::Indirect_Inout &&
598
604
ArgConvention != SILArgumentConvention::Indirect_InoutAliasable)
599
605
return false ;
Original file line number Diff line number Diff line change @@ -938,3 +938,35 @@ bb0(%0 : $Int):
938
938
%empty = tuple ()
939
939
return %empty : $()
940
940
}
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