|
1 | 1 | // RUN: %target-swift-emit-silgen -parse-stdlib -enable-sil-ownership -Xllvm -sil-print-debuginfo -verify -primary-file %s %S/Inputs/errors_other.swift | %FileCheck %s
|
2 | 2 |
|
3 |
| -// TODO: Turn back on ownership verification. I turned off the verification on |
4 |
| -// this file since it shows an ownership error that does not affect |
5 |
| -// codegen. Specifically when we destroy the temporary array we use for the |
6 |
| -// variadic tuple, we try to borrow the temporary array when we pass it to the |
7 |
| -// destroy function. This makes the ownership verifier think that the owned |
8 |
| -// value we are trying to destroy is not cleaned up. But once ownership is |
9 |
| -// stripped out, the destroy array function still does what it needs to do. The |
10 |
| -// actual fix for this would require a bunch of surgery in SILGenApply around |
11 |
| -// how function types are computed and preserving non-canonical function types |
12 |
| -// through SILGenApply. This is something that can be done after +0 is turned |
13 |
| -// on. |
14 |
| - |
15 | 3 | import Swift
|
16 | 4 |
|
17 | 5 | class Cat {}
|
@@ -176,6 +164,83 @@ func all_together_now(_ flag: Bool) -> Cat {
|
176 | 164 | }
|
177 | 165 | }
|
178 | 166 |
|
| 167 | +// Make sure that if we catch an error in a throwing function we borrow the |
| 168 | +// error and only consume the error in the rethrow block. |
| 169 | +// |
| 170 | +// CHECK-LABEL: sil hidden @$s6errors20all_together_now_twoyAA3CatCSgSbKF : $@convention(thin) (Bool) -> (@owned Optional<Cat>, @error Error) { |
| 171 | +// CHECK: bb0( |
| 172 | +// CHECK-NOT: bb1 |
| 173 | +// CHECK: try_apply {{.*}}, normal [[NORMAL_BB:bb[0-9]+]], error [[ERROR_BB:bb[0-9]+]] |
| 174 | +// |
| 175 | +// CHECK: [[ERROR_BB]]([[ERROR:%.*]] : @owned $Error): |
| 176 | +// CHECK: [[BORROWED_ERROR:%.*]] = begin_borrow [[ERROR]] |
| 177 | +// CHECK: [[COPIED_ERROR:%.*]] = copy_value [[BORROWED_ERROR]] |
| 178 | +// CHECK: store [[COPIED_ERROR]] to [init] [[CAST_INPUT_MEM:%.*]] : $*Error |
| 179 | +// CHECK: checked_cast_addr_br copy_on_success Error in [[CAST_INPUT_MEM]] : $*Error to HomeworkError in [[CAST_OUTPUT_MEM:%.*]] : $*HomeworkError, [[CAST_YES_BB:bb[0-9]+]], [[CAST_NO_BB:bb[0-9]+]], |
| 180 | +// |
| 181 | +// CHECK: [[CAST_YES_BB]]: |
| 182 | +// CHECK: [[SUBERROR:%.*]] = load [take] [[CAST_OUTPUT_MEM]] |
| 183 | +// CHECK: switch_enum [[SUBERROR]] : $HomeworkError, case #HomeworkError.TooHard!enumelt: {{bb[0-9]+}}, default [[SWITCH_MATCH_FAIL_BB:bb[0-9]+]], |
| 184 | +// |
| 185 | +// CHECK: [[SWITCH_MATCH_FAIL_BB]]([[SUBERROR:%.*]] : @owned $HomeworkError): |
| 186 | +// CHECK: destroy_value [[SUBERROR]] |
| 187 | +// CHECK: end_borrow [[BORROWED_ERROR]] |
| 188 | +// CHECK: br [[RETHROW_BB:bb[0-9]+]]([[ERROR]] : $Error) |
| 189 | +// |
| 190 | +// CHECK: [[CAST_NO_BB]]: |
| 191 | +// CHECK: end_borrow [[BORROWED_ERROR]] |
| 192 | +// CHECK: br [[RETHROW_BB]]([[ERROR]] : $Error) |
| 193 | +// |
| 194 | +// CHECK: [[RETHROW_BB]]([[ERROR_FOR_RETHROW:%.*]] : @owned $Error): |
| 195 | +// CHECK: throw [[ERROR_FOR_RETHROW]] |
| 196 | +// CHECK: } // end sil function '$s6errors20all_together_now_twoyAA3CatCSgSbKF' |
| 197 | +func all_together_now_two(_ flag: Bool) throws -> Cat? { |
| 198 | + do { |
| 199 | + return try dont_return(Cat()) |
| 200 | + } catch HomeworkError.TooHard { |
| 201 | + return nil |
| 202 | + } |
| 203 | +} |
| 204 | + |
| 205 | +// Same as the previous test, but with multiple cases instead of just one. |
| 206 | +// |
| 207 | +// CHECK-LABEL: sil hidden @$s6errors22all_together_now_threeyAA3CatCSgSbKF : $@convention(thin) (Bool) -> (@owned Optional<Cat>, @error Error) { |
| 208 | +// CHECK: bb0( |
| 209 | +// CHECK-NOT: bb1 |
| 210 | +// CHECK: try_apply {{.*}}, normal [[NORMAL_BB:bb[0-9]+]], error [[ERROR_BB:bb[0-9]+]] |
| 211 | +// |
| 212 | +// CHECK: [[ERROR_BB]]([[ERROR:%.*]] : @owned $Error): |
| 213 | +// CHECK: [[BORROWED_ERROR:%.*]] = begin_borrow [[ERROR]] |
| 214 | +// CHECK: [[COPIED_ERROR:%.*]] = copy_value [[BORROWED_ERROR]] |
| 215 | +// CHECK: store [[COPIED_ERROR]] to [init] [[CAST_INPUT_MEM:%.*]] : $*Error |
| 216 | +// CHECK: checked_cast_addr_br copy_on_success Error in [[CAST_INPUT_MEM]] : $*Error to HomeworkError in [[CAST_OUTPUT_MEM:%.*]] : $*HomeworkError, [[CAST_YES_BB:bb[0-9]+]], [[CAST_NO_BB:bb[0-9]+]], |
| 217 | +// |
| 218 | +// CHECK: [[CAST_YES_BB]]: |
| 219 | +// CHECK: [[SUBERROR:%.*]] = load [take] [[CAST_OUTPUT_MEM]] |
| 220 | +// CHECK: switch_enum [[SUBERROR]] : $HomeworkError, case #HomeworkError.TooHard!enumelt: {{bb[0-9]+}}, case #HomeworkError.TooMuch!enumelt: {{bb[0-9]+}}, default [[SWITCH_MATCH_FAIL_BB:bb[0-9]+]], |
| 221 | +// |
| 222 | +// CHECK: [[SWITCH_MATCH_FAIL_BB]]([[SUBERROR:%.*]] : @owned $HomeworkError): |
| 223 | +// CHECK: destroy_value [[SUBERROR]] |
| 224 | +// CHECK: end_borrow [[BORROWED_ERROR]] |
| 225 | +// CHECK: br [[RETHROW_BB:bb[0-9]+]]([[ERROR]] : $Error) |
| 226 | +// |
| 227 | +// CHECK: [[CAST_NO_BB]]: |
| 228 | +// CHECK: end_borrow [[BORROWED_ERROR]] |
| 229 | +// CHECK: br [[RETHROW_BB]]([[ERROR]] : $Error) |
| 230 | +// |
| 231 | +// CHECK: [[RETHROW_BB]]([[ERROR_FOR_RETHROW:%.*]] : @owned $Error): |
| 232 | +// CHECK: throw [[ERROR_FOR_RETHROW]] |
| 233 | +// CHECK: } // end sil function '$s6errors22all_together_now_threeyAA3CatCSgSbKF' |
| 234 | +func all_together_now_three(_ flag: Bool) throws -> Cat? { |
| 235 | + do { |
| 236 | + return try dont_return(Cat()) |
| 237 | + } catch HomeworkError.TooHard { |
| 238 | + return nil |
| 239 | + } catch HomeworkError.TooMuch { |
| 240 | + return nil |
| 241 | + } |
| 242 | +} |
| 243 | + |
179 | 244 | // Catch in non-throwing context.
|
180 | 245 | // CHECK-LABEL: sil hidden @$s6errors11catch_a_catAA3CatCyF : $@convention(thin) () -> @owned Cat
|
181 | 246 | // CHECK-NEXT: bb0:
|
|
0 commit comments