File tree 3 files changed +73
-2
lines changed
lib/SILOptimizer/SILCombiner 3 files changed +73
-2
lines changed Original file line number Diff line number Diff line change @@ -91,8 +91,16 @@ SILCombiner::visitAllocExistentialBoxInst(AllocExistentialBoxInst *AEBI) {
91
91
if (SingleStore && SingleRelease) {
92
92
assert (SingleProjection && " store without a projection" );
93
93
// Release the value that was stored into the existential box. The box
94
- // is going away so we need to release the stored value now.
95
- Builder.setInsertionPoint (SingleStore);
94
+ // is going away so we need to release the stored value.
95
+ // NOTE: It's important that the release is inserted at the single
96
+ // release of the box and not at the store, because a balancing retain could
97
+ // be _after_ the store, e.g:
98
+ // %box = alloc_existential_box
99
+ // %addr = project_existential_box %box
100
+ // store %value to %addr
101
+ // retain_value %value // must insert the release after this retain
102
+ // strong_release %box
103
+ Builder.setInsertionPoint (SingleRelease);
96
104
Builder.createReleaseValue (AEBI->getLoc (), SingleStore->getSrc (),
97
105
SingleRelease->getAtomicity ());
98
106
Original file line number Diff line number Diff line change @@ -2806,6 +2806,32 @@ bb3(%19 : $Double): // Preds: bb1 bb2
2806
2806
return %19 : $Double // id: %20
2807
2807
}
2808
2808
2809
+ enum ErrorEnum: Error {
2810
+ case errorCase(label: [Error])
2811
+ case other
2812
+ }
2813
+
2814
+ // CHECK-LABEL: sil @insert_compensating_release_at_release_of_box
2815
+ // CHECK: [[L:%[0-9]+]] = load
2816
+ // CHECK-NEXT: [[T:%[0-9]+]] = tuple
2817
+ // CHECK-NEXT: retain_value [[L]]
2818
+ // CHECK-NEXT: release_value [[T]]
2819
+ // CHECK-NEXT: tuple
2820
+ // CHECK-NEXT: return
2821
+ sil @insert_compensating_release_at_release_of_box : $@convention(method) (@in_guaranteed Array<Error>) -> () {
2822
+ bb0(%0 : $*Array<Error>):
2823
+ %20 = load %0 : $*Array<Error>
2824
+ %22 = tuple $(label: Array<Error>) (%20)
2825
+ %23 = enum $ErrorEnum, #ErrorEnum.errorCase!enumelt.1, %22 : $(label: Array<Error>)
2826
+ %36 = alloc_existential_box $Error, $ErrorEnum
2827
+ %37 = project_existential_box $ErrorEnum in %36 : $Error
2828
+ store %23 to %37 : $*ErrorEnum
2829
+ retain_value %20 : $Array<Error>
2830
+ strong_release %36 : $Error
2831
+ %52 = tuple ()
2832
+ return %52 : $()
2833
+ }
2834
+
2809
2835
sil [reabstraction_thunk] @_TTRXFo_oSS_dSb_XFo_iSS_iSb_ : $@convention(thin) (@in String, @owned @callee_owned (@owned String) -> Bool) -> @out Bool
2810
2836
sil [reabstraction_thunk] @_TTRXFo_iSS_iSb_XFo_oSS_dSb_ : $@convention(thin) (@owned String, @owned @callee_owned (@in String) -> @out Bool) -> Bool
2811
2837
Original file line number Diff line number Diff line change
1
+ // RUN: %empty-directory(%t)
2
+ // RUN: %target-build-swift -O -module-name=a %s -o %t/a.out
3
+ // RUN: %target-run %t/a.out | %FileCheck %s
4
+
5
+ // REQUIRES: executable_test
6
+
7
+ // This is an end-to-end test for rdar://problem/50759056.
8
+
9
+ enum ErrorEnum : Error {
10
+ case errorCase( [ Error ] )
11
+ case other
12
+ }
13
+
14
+ final class Myclass {
15
+ var e = [ Error] ( )
16
+ var b = true
17
+
18
+ @inline ( never)
19
+ func foo( ) {
20
+ e. append ( ErrorEnum . other)
21
+ if b {
22
+ bar ( ErrorEnum . errorCase ( e) )
23
+ }
24
+ }
25
+
26
+ @inline ( never)
27
+ func bar( _: Error ? ) {
28
+ b = false
29
+ foo ( )
30
+ }
31
+ }
32
+
33
+ let c = Myclass ( )
34
+ c. foo ( )
35
+
36
+ // CHECK: [a.ErrorEnum.other, a.ErrorEnum.other]
37
+ print ( c. e)
You can’t perform that action at this time.
0 commit comments