Skip to content

Commit d28a8ae

Browse files
committed
Exclusivity: Disable verifier assert on noescape closure block args.
This is a small hole in the exclusivity model that verification is now catching in 4.2. On 4.2, disable the verification just in this narrow, unsupported case. This silences a harmless assert and reverts to the 4.2 behavior in this unusual corner case. The exclusivity enforcement hole will be fully fixed on master. Fixed <rdar://problem/42242406> [SR-8266]: Compiler crash when checking exclusivity of inout alias.
1 parent 00639e3 commit d28a8ae

File tree

2 files changed

+96
-0
lines changed

2 files changed

+96
-0
lines changed

lib/SILOptimizer/Mandatory/DiagnoseStaticExclusivity.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -896,6 +896,14 @@ static void checkNoEscapePartialApply(PartialApplyInst *PAI) {
896896
continue;
897897
}
898898
}
899+
auto *termInst = dyn_cast<TermInst>(user);
900+
if (termInst && termInst->isBranch()) {
901+
// FIXME: Passing noescape closures through block arguments is currently a
902+
// hole in the exclusivity model. This is only permitted on the 4.2
903+
// branch. The implementation on master should follow block arguments both
904+
// here and in checkForViolationAtApply.
905+
continue;
906+
}
899907
llvm::dbgs() << "Unexpected partial_apply use: " << *user;
900908
llvm_unreachable("A partial_apply with @inout_aliasable may only be "
901909
"used as a @noescape function type argument.");
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
// RUN: %target-sil-opt -enable-sil-verify-all %s -enforce-exclusivity=unchecked -diagnose-static-exclusivity -verify -enable-sil-ownership | %FileCheck %s
2+
//
3+
// These tests are extensions of those in
4+
// exclusivity_static_diagnostics.sil. Once those tests are rewritten
5+
// with full ownership annotations, the files can be merged.
6+
7+
sil_stage raw
8+
9+
import Builtin
10+
import Swift
11+
12+
// -----------------------------------------------------------------------------
13+
// <rdar://problem/42242406> [SR-8266]: Compiler crash when checking
14+
// exclusivity of inout alias closureWithNoCapture,
15+
// closureWithConflict, partialApplyPhiThunk, and testPartialApplyPhi.
16+
//
17+
// Test that 'checkNoEscapePartialApply' does not assert on a noescape
18+
// closure passed through a block argument.
19+
20+
sil hidden @closureWithNoCapture : $@convention(thin) (Int32) -> () {
21+
bb0(%0 : @trivial $Int32):
22+
%2 = tuple ()
23+
return %2 : $()
24+
}
25+
26+
sil hidden @closureWithConflict : $@convention(thin) (Int32, @inout_aliasable Int32) -> () {
27+
bb0(%0 : @trivial $Int32, %1 : @trivial $*Int32):
28+
// FIXME: a conflict should be reported here.
29+
%2 = begin_access [modify] [unknown] %1 : $*Int32
30+
end_access %2 : $*Int32
31+
%v = tuple ()
32+
return %v : $()
33+
}
34+
35+
sil shared [transparent] [serializable] [reabstraction_thunk] @partialApplyPhiThunk : $@convention(thin) (@in_guaranteed Int32, @guaranteed @noescape @callee_guaranteed (Int32) -> (@error Error)) -> (@error Error) {
36+
bb0(%0 : @trivial $*Int32, %1 : @trivial $@noescape @callee_guaranteed (Int32) -> (@error Error)):
37+
%val = load [trivial] %0 : $*Int32
38+
try_apply %1(%val) : $@noescape @callee_guaranteed (Int32) -> (@error Error), normal bb1, error bb2
39+
40+
bb1(%v : @trivial $()):
41+
return %v : $()
42+
43+
bb2(%5 : @owned $Error):
44+
throw %5 : $Error
45+
}
46+
47+
sil @takeGenericNoEscapeFunction : $@convention(method) <τ_0_0> (@inout τ_0_0, @noescape @callee_guaranteed (@in_guaranteed τ_0_0) -> (@error Error)) -> (@error Error)
48+
49+
// CHECK-LABEL: sil @testPartialApplyPhi
50+
sil @testPartialApplyPhi : $@convention(thin) (Int, @inout Int32) -> (@error Error) {
51+
bb0(%0 : @trivial $Int, %1 : @trivial $*Int32):
52+
cond_br undef, bb1, bb2
53+
54+
bb1:
55+
%f1 = function_ref @closureWithNoCapture : $@convention(thin) (Int32) -> ()
56+
%pa1 = partial_apply [callee_guaranteed] %f1() : $@convention(thin) (Int32) -> ()
57+
br bb3(%pa1 : $@callee_guaranteed (Int32) -> ())
58+
59+
bb2:
60+
%f2 = function_ref @closureWithConflict : $@convention(thin) (Int32, @inout_aliasable Int32) -> ()
61+
%pa2 = partial_apply [callee_guaranteed] %f2(%1) : $@convention(thin) (Int32, @inout_aliasable Int32) -> ()
62+
br bb3(%pa2 : $@callee_guaranteed (Int32) -> ())
63+
64+
bb3(%pa3 : @owned $@callee_guaranteed (Int32) -> ()):
65+
%cvt3 = convert_function %pa3 : $@callee_guaranteed (Int32) -> () to $@callee_guaranteed (Int32) -> (@error Error)
66+
%esc3 = convert_escape_to_noescape [not_guaranteed] %cvt3 : $@callee_guaranteed (Int32) -> (@error Error) to $@noescape @callee_guaranteed (Int32) -> (@error Error)
67+
68+
%f3 = function_ref @partialApplyPhiThunk : $@convention(thin) (@in_guaranteed Int32, @guaranteed @noescape @callee_guaranteed (Int32) -> (@error Error)) -> (@error Error)
69+
%pa4 = partial_apply [callee_guaranteed] %f3(%esc3) : $@convention(thin) (@in_guaranteed Int32, @guaranteed @noescape @callee_guaranteed (Int32) -> (@error Error)) -> (@error Error)
70+
%esc4 = convert_escape_to_noescape [not_guaranteed] %pa4 : $@callee_guaranteed (@in_guaranteed Int32) -> (@error Error) to $@noescape @callee_guaranteed (@in_guaranteed Int32) -> (@error Error)
71+
72+
// In the original test case, the closures are destroyed before their use. Is that ok?
73+
destroy_value %pa4 : $@callee_guaranteed (@in_guaranteed Int32) -> (@error Error)
74+
destroy_value %cvt3 : $@callee_guaranteed (Int32) -> (@error Error)
75+
76+
// FIXME: a conflict should be reported here.
77+
%access = begin_access [modify] [static] %1 : $*Int32
78+
%f4 = function_ref @takeGenericNoEscapeFunction : $@convention(method) <τ_0_0> (@inout τ_0_0, @noescape @callee_guaranteed (@in_guaranteed τ_0_0) -> (@error Error)) -> (@error Error)
79+
try_apply %f4<Int32>(%access, %esc4) : $@convention(method) <τ_0_0> (@inout τ_0_0, @noescape @callee_guaranteed (@in_guaranteed τ_0_0) -> (@error Error)) -> (@error Error), normal bb4, error bb5
80+
81+
bb4(%v : @trivial $()):
82+
end_access %access : $*Int32
83+
return %v : $()
84+
85+
bb5(%e : @owned $Error):
86+
end_access %access : $*Int32
87+
throw %e : $Error
88+
}

0 commit comments

Comments
 (0)