| 1 | const std = @import("std"); |
| 2 | const Context = @import("tests.zig").ErrorTracesContext; |
| 3 | |
| 4 | pub fn addCases(cases: *Context, params: *const Context.CaseParameters, target: *const std.Target) void { |
| 5 | cases.addCase(.{ |
| 6 | .params = params, |
| 7 | .target = target, |
| 8 | .name = "return", |
| 9 | .source = |
| 10 | \\pub fn main() !void { |
| 11 | \\ return error.TheSkyIsFalling; |
| 12 | \\} |
| 13 | , |
| 14 | .expect_error = "TheSkyIsFalling", |
| 15 | .expect_trace = |
| 16 | \\source.zig:2:5: [address] in main |
| 17 | \\ return error.TheSkyIsFalling; |
| 18 | \\ ^ |
| 19 | , |
| 20 | }); |
| 21 | |
| 22 | cases.addCase(.{ |
| 23 | .params = params, |
| 24 | .target = target, |
| 25 | .name = "try return", |
| 26 | .source = |
| 27 | \\fn foo() !void { |
| 28 | \\ return error.TheSkyIsFalling; |
| 29 | \\} |
| 30 | \\ |
| 31 | \\pub fn main() !void { |
| 32 | \\ try foo(); |
| 33 | \\} |
| 34 | , |
| 35 | .expect_error = "TheSkyIsFalling", |
| 36 | .expect_trace = |
| 37 | \\source.zig:2:5: [address] in foo |
| 38 | \\ return error.TheSkyIsFalling; |
| 39 | \\ ^ |
| 40 | \\source.zig:6:5: [address] in main |
| 41 | \\ try foo(); |
| 42 | \\ ^ |
| 43 | , |
| 44 | .disable_trace_optimized = &.{ |
| 45 | .{ .x86_64, .windows }, |
| 46 | .{ .x86, .windows }, |
| 47 | .{ .x86_64, .macos }, |
| 48 | .{ .aarch64, .macos }, |
| 49 | }, |
| 50 | }); |
| 51 | cases.addCase(.{ |
| 52 | .params = params, |
| 53 | .target = target, |
| 54 | .name = "non-error return pops error trace", |
| 55 | .source = |
| 56 | \\fn bar() !void { |
| 57 | \\ return error.UhOh; |
| 58 | \\} |
| 59 | \\ |
| 60 | \\fn foo() !void { |
| 61 | \\ bar() catch { |
| 62 | \\ return; // non-error result: success |
| 63 | \\ }; |
| 64 | \\} |
| 65 | \\ |
| 66 | \\pub fn main() !void { |
| 67 | \\ try foo(); |
| 68 | \\ return error.UnrelatedError; |
| 69 | \\} |
| 70 | , |
| 71 | .expect_error = "UnrelatedError", |
| 72 | .expect_trace = |
| 73 | \\source.zig:13:5: [address] in main |
| 74 | \\ return error.UnrelatedError; |
| 75 | \\ ^ |
| 76 | , |
| 77 | }); |
| 78 | |
| 79 | cases.addCase(.{ |
| 80 | .params = params, |
| 81 | .target = target, |
| 82 | .name = "continue in while loop", |
| 83 | .source = |
| 84 | \\fn foo() !void { |
| 85 | \\ return error.UhOh; |
| 86 | \\} |
| 87 | \\ |
| 88 | \\pub fn main() !void { |
| 89 | \\ var i: usize = 0; |
| 90 | \\ while (i < 3) : (i += 1) { |
| 91 | \\ foo() catch continue; |
| 92 | \\ } |
| 93 | \\ return error.UnrelatedError; |
| 94 | \\} |
| 95 | , |
| 96 | .expect_error = "UnrelatedError", |
| 97 | .expect_trace = |
| 98 | \\source.zig:10:5: [address] in main |
| 99 | \\ return error.UnrelatedError; |
| 100 | \\ ^ |
| 101 | , |
| 102 | }); |
| 103 | |
| 104 | cases.addCase(.{ |
| 105 | .params = params, |
| 106 | .target = target, |
| 107 | .name = "for loop pops error return trace", |
| 108 | .source = |
| 109 | \\fn foo() !void { return error.FooError; } |
| 110 | \\ |
| 111 | \\pub fn main() !void { |
| 112 | \\ for (0..2) |_| { |
| 113 | \\ const f = foo(); |
| 114 | \\ f catch {}; |
| 115 | \\ } else { |
| 116 | \\ const f = foo(); |
| 117 | \\ f catch {}; |
| 118 | \\ } |
| 119 | \\ return error.Stop; |
| 120 | \\} |
| 121 | , |
| 122 | .expect_error = "Stop", |
| 123 | .expect_trace = |
| 124 | \\source.zig:11:5: [address] in main |
| 125 | \\ return error.Stop; |
| 126 | \\ ^ |
| 127 | , |
| 128 | .disable_trace_optimized = &.{ |
| 129 | .{ .x86_64, .windows }, |
| 130 | .{ .x86, .windows }, |
| 131 | .{ .x86_64, .macos }, |
| 132 | .{ .aarch64, .macos }, |
| 133 | }, |
| 134 | }); |
| 135 | |
| 136 | cases.addCase(.{ |
| 137 | .params = params, |
| 138 | .target = target, |
| 139 | .name = "implicit continue in for loop pops stale error return trace", |
| 140 | .source = |
| 141 | \\fn foo() !void { return error.FooError; } |
| 142 | \\ |
| 143 | \\pub fn main() !void { |
| 144 | \\ for (0..2) |i| { |
| 145 | \\ const f = foo(); |
| 146 | \\ f catch {}; |
| 147 | \\ |
| 148 | \\ if (i == 1) return error.Stop; |
| 149 | \\ } |
| 150 | \\} |
| 151 | , |
| 152 | .expect_error = "Stop", |
| 153 | .expect_trace = |
| 154 | \\source.zig:1:18: [address] in foo |
| 155 | \\fn foo() !void { return error.FooError; } |
| 156 | \\ ^ |
| 157 | \\source.zig:8:21: [address] in main |
| 158 | \\ if (i == 1) return error.Stop; |
| 159 | \\ ^ |
| 160 | , |
| 161 | .disable_trace_optimized = &.{ |
| 162 | .{ .x86_64, .windows }, |
| 163 | .{ .x86, .windows }, |
| 164 | .{ .x86_64, .macos }, |
| 165 | .{ .aarch64, .macos }, |
| 166 | }, |
| 167 | }); |
| 168 | |
| 169 | cases.addCase(.{ |
| 170 | .params = params, |
| 171 | .target = target, |
| 172 | .name = "while loop pops error return trace", |
| 173 | .source = |
| 174 | \\fn foo() !void { return error.FooError; } |
| 175 | \\ |
| 176 | \\pub fn main() !void { |
| 177 | \\ var i: usize = 0; |
| 178 | \\ while (i < 2) { |
| 179 | \\ const f = foo(); |
| 180 | \\ f catch {}; |
| 181 | \\ i += 1; |
| 182 | \\ } else { |
| 183 | \\ const f = foo(); |
| 184 | \\ f catch {}; |
| 185 | \\ } |
| 186 | \\ return error.Stop; |
| 187 | \\} |
| 188 | , |
| 189 | .expect_error = "Stop", |
| 190 | .expect_trace = |
| 191 | \\source.zig:13:5: [address] in main |
| 192 | \\ return error.Stop; |
| 193 | \\ ^ |
| 194 | , |
| 195 | .disable_trace_optimized = &.{ |
| 196 | .{ .x86_64, .windows }, |
| 197 | .{ .x86, .windows }, |
| 198 | .{ .x86_64, .macos }, |
| 199 | .{ .aarch64, .macos }, |
| 200 | }, |
| 201 | }); |
| 202 | |
| 203 | cases.addCase(.{ |
| 204 | .params = params, |
| 205 | .target = target, |
| 206 | .name = "implicit continue in while loop pops stale error return trace", |
| 207 | .source = |
| 208 | \\fn foo() !void { return error.FooError; } |
| 209 | \\ |
| 210 | \\pub fn main() !void { |
| 211 | \\ var i: usize = 0; |
| 212 | \\ while (i < 2) { |
| 213 | \\ const f = foo(); |
| 214 | \\ f catch {}; |
| 215 | \\ |
| 216 | \\ if (i == 1) return error.Stop; |
| 217 | \\ i += 1; |
| 218 | \\ } |
| 219 | \\} |
| 220 | , |
| 221 | .expect_error = "Stop", |
| 222 | .expect_trace = |
| 223 | \\source.zig:1:18: [address] in foo |
| 224 | \\fn foo() !void { return error.FooError; } |
| 225 | \\ ^ |
| 226 | \\source.zig:9:21: [address] in main |
| 227 | \\ if (i == 1) return error.Stop; |
| 228 | \\ ^ |
| 229 | , |
| 230 | .disable_trace_optimized = &.{ |
| 231 | .{ .x86_64, .windows }, |
| 232 | .{ .x86, .windows }, |
| 233 | .{ .x86_64, .macos }, |
| 234 | .{ .aarch64, .macos }, |
| 235 | }, |
| 236 | }); |
| 237 | |
| 238 | cases.addCase(.{ |
| 239 | .params = params, |
| 240 | .target = target, |
| 241 | .name = "try return + handled catch/if-else", |
| 242 | .source = |
| 243 | \\fn foo() !void { |
| 244 | \\ return error.TheSkyIsFalling; |
| 245 | \\} |
| 246 | \\ |
| 247 | \\pub fn main() !void { |
| 248 | \\ foo() catch {}; // should not affect error trace |
| 249 | \\ if (foo()) |_| {} else |_| { |
| 250 | \\ // should also not affect error trace |
| 251 | \\ } |
| 252 | \\ try foo(); |
| 253 | \\} |
| 254 | , |
| 255 | .expect_error = "TheSkyIsFalling", |
| 256 | .expect_trace = |
| 257 | \\source.zig:2:5: [address] in foo |
| 258 | \\ return error.TheSkyIsFalling; |
| 259 | \\ ^ |
| 260 | \\source.zig:10:5: [address] in main |
| 261 | \\ try foo(); |
| 262 | \\ ^ |
| 263 | , |
| 264 | .disable_trace_optimized = &.{ |
| 265 | .{ .x86_64, .windows }, |
| 266 | .{ .x86, .windows }, |
| 267 | .{ .x86_64, .macos }, |
| 268 | .{ .aarch64, .macos }, |
| 269 | }, |
| 270 | }); |
| 271 | |
| 272 | cases.addCase(.{ |
| 273 | .params = params, |
| 274 | .target = target, |
| 275 | .name = "break from inline loop pops error return trace", |
| 276 | .source = |
| 277 | \\fn foo() !void { return error.FooBar; } |
| 278 | \\ |
| 279 | \\pub fn main() !void { |
| 280 | \\ comptime var i: usize = 0; |
| 281 | \\ b: inline while (i < 5) : (i += 1) { |
| 282 | \\ foo() catch { |
| 283 | \\ break :b; // non-error break, success |
| 284 | \\ }; |
| 285 | \\ } |
| 286 | \\ // foo() was successfully handled, should not appear in trace |
| 287 | \\ |
| 288 | \\ return error.BadTime; |
| 289 | \\} |
| 290 | , |
| 291 | .expect_error = "BadTime", |
| 292 | .expect_trace = |
| 293 | \\source.zig:12:5: [address] in main |
| 294 | \\ return error.BadTime; |
| 295 | \\ ^ |
| 296 | , |
| 297 | }); |
| 298 | |
| 299 | cases.addCase(.{ |
| 300 | .params = params, |
| 301 | .target = target, |
| 302 | .name = "catch and re-throw error", |
| 303 | .source = |
| 304 | \\fn foo() !void { |
| 305 | \\ return error.TheSkyIsFalling; |
| 306 | \\} |
| 307 | \\ |
| 308 | \\pub fn main() !void { |
| 309 | \\ return foo() catch error.AndMyCarIsOutOfGas; |
| 310 | \\} |
| 311 | , |
| 312 | .expect_error = "AndMyCarIsOutOfGas", |
| 313 | .expect_trace = |
| 314 | \\source.zig:2:5: [address] in foo |
| 315 | \\ return error.TheSkyIsFalling; |
| 316 | \\ ^ |
| 317 | \\source.zig:6:5: [address] in main |
| 318 | \\ return foo() catch error.AndMyCarIsOutOfGas; |
| 319 | \\ ^ |
| 320 | , |
| 321 | .disable_trace_optimized = &.{ |
| 322 | .{ .x86_64, .windows }, |
| 323 | .{ .x86, .windows }, |
| 324 | .{ .x86_64, .macos }, |
| 325 | .{ .aarch64, .macos }, |
| 326 | }, |
| 327 | }); |
| 328 | |
| 329 | cases.addCase(.{ |
| 330 | .params = params, |
| 331 | .target = target, |
| 332 | .name = "errors stored in var do not contribute to error trace", |
| 333 | .source = |
| 334 | \\fn foo() !void { |
| 335 | \\ return error.TheSkyIsFalling; |
| 336 | \\} |
| 337 | \\ |
| 338 | \\pub fn main() !void { |
| 339 | \\ // Once an error is stored in a variable, it is popped from the trace |
| 340 | \\ var x = foo(); |
| 341 | \\ x = {}; |
| 342 | \\ |
| 343 | \\ // As a result, this error trace will still be clean |
| 344 | \\ return error.SomethingUnrelatedWentWrong; |
| 345 | \\} |
| 346 | , |
| 347 | .expect_error = "SomethingUnrelatedWentWrong", |
| 348 | .expect_trace = |
| 349 | \\source.zig:11:5: [address] in main |
| 350 | \\ return error.SomethingUnrelatedWentWrong; |
| 351 | \\ ^ |
| 352 | , |
| 353 | }); |
| 354 | |
| 355 | cases.addCase(.{ |
| 356 | .params = params, |
| 357 | .target = target, |
| 358 | .name = "error stored in const has trace preserved for duration of block", |
| 359 | .source = |
| 360 | \\fn foo() !void { return error.TheSkyIsFalling; } |
| 361 | \\fn bar() !void { return error.InternalError; } |
| 362 | \\fn baz() !void { return error.UnexpectedReality; } |
| 363 | \\ |
| 364 | \\pub fn main() !void { |
| 365 | \\ const x = foo(); |
| 366 | \\ const y = b: { |
| 367 | \\ if (true) |
| 368 | \\ break :b bar(); |
| 369 | \\ |
| 370 | \\ break :b {}; |
| 371 | \\ }; |
| 372 | \\ x catch {}; |
| 373 | \\ y catch {}; |
| 374 | \\ // foo()/bar() error traces not popped until end of block |
| 375 | \\ |
| 376 | \\ { |
| 377 | \\ const z = baz(); |
| 378 | \\ z catch {}; |
| 379 | \\ // baz() error trace still alive here |
| 380 | \\ } |
| 381 | \\ // baz() error trace popped, foo(), bar() still alive |
| 382 | \\ return error.StillUnresolved; |
| 383 | \\} |
| 384 | , |
| 385 | .expect_error = "StillUnresolved", |
| 386 | .expect_trace = |
| 387 | \\source.zig:1:18: [address] in foo |
| 388 | \\fn foo() !void { return error.TheSkyIsFalling; } |
| 389 | \\ ^ |
| 390 | \\source.zig:2:18: [address] in bar |
| 391 | \\fn bar() !void { return error.InternalError; } |
| 392 | \\ ^ |
| 393 | \\source.zig:23:5: [address] in main |
| 394 | \\ return error.StillUnresolved; |
| 395 | \\ ^ |
| 396 | , |
| 397 | .disable_trace_optimized = &.{ |
| 398 | .{ .x86_64, .windows }, |
| 399 | .{ .x86, .windows }, |
| 400 | .{ .x86_64, .macos }, |
| 401 | .{ .aarch64, .macos }, |
| 402 | }, |
| 403 | }); |
| 404 | |
| 405 | cases.addCase(.{ |
| 406 | .params = params, |
| 407 | .target = target, |
| 408 | .name = "error passed to function has its trace preserved for duration of the call", |
| 409 | .source = |
| 410 | \\pub fn expectError(expected_error: anyerror, actual_error: anyerror!void) !void { |
| 411 | \\ actual_error catch |err| { |
| 412 | \\ if (err == expected_error) return {}; |
| 413 | \\ }; |
| 414 | \\ return error.TestExpectedError; |
| 415 | \\} |
| 416 | \\ |
| 417 | \\fn alwaysErrors() !void { return error.ThisErrorShouldNotAppearInAnyTrace; } |
| 418 | \\fn foo() !void { return error.Foo; } |
| 419 | \\ |
| 420 | \\pub fn main() !void { |
| 421 | \\ try expectError(error.ThisErrorShouldNotAppearInAnyTrace, alwaysErrors()); |
| 422 | \\ try expectError(error.ThisErrorShouldNotAppearInAnyTrace, alwaysErrors()); |
| 423 | \\ try expectError(error.Foo, foo()); |
| 424 | \\ |
| 425 | \\ // Only the error trace for this failing check should appear: |
| 426 | \\ try expectError(error.Bar, foo()); |
| 427 | \\} |
| 428 | , |
| 429 | .expect_error = "TestExpectedError", |
| 430 | .expect_trace = |
| 431 | \\source.zig:9:18: [address] in foo |
| 432 | \\fn foo() !void { return error.Foo; } |
| 433 | \\ ^ |
| 434 | \\source.zig:5:5: [address] in expectError |
| 435 | \\ return error.TestExpectedError; |
| 436 | \\ ^ |
| 437 | \\source.zig:17:5: [address] in main |
| 438 | \\ try expectError(error.Bar, foo()); |
| 439 | \\ ^ |
| 440 | , |
| 441 | .disable_trace_optimized = &.{ |
| 442 | .{ .x86_64, .windows }, |
| 443 | .{ .x86, .windows }, |
| 444 | .{ .x86_64, .macos }, |
| 445 | .{ .aarch64, .macos }, |
| 446 | }, |
| 447 | }); |
| 448 | |
| 449 | cases.addCase(.{ |
| 450 | .params = params, |
| 451 | .target = target, |
| 452 | .name = "try return from within catch", |
| 453 | .source = |
| 454 | \\fn foo() !void { |
| 455 | \\ return error.TheSkyIsFalling; |
| 456 | \\} |
| 457 | \\ |
| 458 | \\fn bar() !void { |
| 459 | \\ return error.AndMyCarIsOutOfGas; |
| 460 | \\} |
| 461 | \\ |
| 462 | \\pub fn main() !void { |
| 463 | \\ foo() catch { // error trace should include foo() |
| 464 | \\ try bar(); |
| 465 | \\ }; |
| 466 | \\} |
| 467 | , |
| 468 | .expect_error = "AndMyCarIsOutOfGas", |
| 469 | .expect_trace = |
| 470 | \\source.zig:2:5: [address] in foo |
| 471 | \\ return error.TheSkyIsFalling; |
| 472 | \\ ^ |
| 473 | \\source.zig:6:5: [address] in bar |
| 474 | \\ return error.AndMyCarIsOutOfGas; |
| 475 | \\ ^ |
| 476 | \\source.zig:11:9: [address] in main |
| 477 | \\ try bar(); |
| 478 | \\ ^ |
| 479 | , |
| 480 | .disable_trace_optimized = &.{ |
| 481 | .{ .x86_64, .windows }, |
| 482 | .{ .x86, .windows }, |
| 483 | .{ .x86_64, .macos }, |
| 484 | .{ .aarch64, .macos }, |
| 485 | }, |
| 486 | }); |
| 487 | |
| 488 | cases.addCase(.{ |
| 489 | .params = params, |
| 490 | .target = target, |
| 491 | .name = "try return from within if-else", |
| 492 | .source = |
| 493 | \\fn foo() !void { |
| 494 | \\ return error.TheSkyIsFalling; |
| 495 | \\} |
| 496 | \\ |
| 497 | \\fn bar() !void { |
| 498 | \\ return error.AndMyCarIsOutOfGas; |
| 499 | \\} |
| 500 | \\ |
| 501 | \\pub fn main() !void { |
| 502 | \\ if (foo()) |_| {} else |_| { // error trace should include foo() |
| 503 | \\ try bar(); |
| 504 | \\ } |
| 505 | \\} |
| 506 | , |
| 507 | .expect_error = "AndMyCarIsOutOfGas", |
| 508 | .expect_trace = |
| 509 | \\source.zig:2:5: [address] in foo |
| 510 | \\ return error.TheSkyIsFalling; |
| 511 | \\ ^ |
| 512 | \\source.zig:6:5: [address] in bar |
| 513 | \\ return error.AndMyCarIsOutOfGas; |
| 514 | \\ ^ |
| 515 | \\source.zig:11:9: [address] in main |
| 516 | \\ try bar(); |
| 517 | \\ ^ |
| 518 | , |
| 519 | .disable_trace_optimized = &.{ |
| 520 | .{ .x86_64, .windows }, |
| 521 | .{ .x86, .windows }, |
| 522 | .{ .x86_64, .macos }, |
| 523 | .{ .aarch64, .macos }, |
| 524 | }, |
| 525 | }); |
| 526 | |
| 527 | cases.addCase(.{ |
| 528 | .params = params, |
| 529 | .target = target, |
| 530 | .name = "try try return return", |
| 531 | .source = |
| 532 | \\fn foo() !void { |
| 533 | \\ try bar(); |
| 534 | \\} |
| 535 | \\ |
| 536 | \\fn bar() !void { |
| 537 | \\ return make_error(); |
| 538 | \\} |
| 539 | \\ |
| 540 | \\fn make_error() !void { |
| 541 | \\ return error.TheSkyIsFalling; |
| 542 | \\} |
| 543 | \\ |
| 544 | \\pub fn main() !void { |
| 545 | \\ try foo(); |
| 546 | \\} |
| 547 | , |
| 548 | .expect_error = "TheSkyIsFalling", |
| 549 | .expect_trace = |
| 550 | \\source.zig:10:5: [address] in make_error |
| 551 | \\ return error.TheSkyIsFalling; |
| 552 | \\ ^ |
| 553 | \\source.zig:6:5: [address] in bar |
| 554 | \\ return make_error(); |
| 555 | \\ ^ |
| 556 | \\source.zig:2:5: [address] in foo |
| 557 | \\ try bar(); |
| 558 | \\ ^ |
| 559 | \\source.zig:14:5: [address] in main |
| 560 | \\ try foo(); |
| 561 | \\ ^ |
| 562 | , |
| 563 | .disable_trace_optimized = &.{ |
| 564 | .{ .x86_64, .windows }, |
| 565 | .{ .x86, .windows }, |
| 566 | .{ .x86_64, .macos }, |
| 567 | .{ .aarch64, .macos }, |
| 568 | }, |
| 569 | }); |
| 570 | |
| 571 | cases.addCase(.{ |
| 572 | .params = params, |
| 573 | .target = target, |
| 574 | .name = "error union switch with call operand", |
| 575 | .source = |
| 576 | \\pub fn main() !void { |
| 577 | \\ try foo(); |
| 578 | \\ return error.TheSkyIsFalling; |
| 579 | \\} |
| 580 | \\ |
| 581 | \\noinline fn failure() error{ Fatal, NonFatal }!void { |
| 582 | \\ return error.NonFatal; |
| 583 | \\} |
| 584 | \\ |
| 585 | \\fn foo() error{Fatal}!void { |
| 586 | \\ return failure() catch |err| switch (err) { |
| 587 | \\ error.Fatal => return error.Fatal, |
| 588 | \\ error.NonFatal => return, |
| 589 | \\ }; |
| 590 | \\} |
| 591 | , |
| 592 | .expect_error = "TheSkyIsFalling", |
| 593 | .expect_trace = |
| 594 | \\source.zig:3:5: [address] in main |
| 595 | \\ return error.TheSkyIsFalling; |
| 596 | \\ ^ |
| 597 | , |
| 598 | .disable_trace_optimized = &.{ |
| 599 | .{ .x86_64, .freebsd }, |
| 600 | .{ .x86_64, .netbsd }, |
| 601 | .{ .x86_64, .linux }, |
| 602 | .{ .x86, .linux }, |
| 603 | .{ .aarch64, .freebsd }, |
| 604 | .{ .aarch64, .netbsd }, |
| 605 | .{ .aarch64, .linux }, |
| 606 | .{ .loongarch64, .linux }, |
| 607 | .{ .powerpc64le, .linux }, |
| 608 | .{ .riscv64, .linux }, |
| 609 | .{ .s390x, .linux }, |
| 610 | .{ .x86_64, .openbsd }, |
| 611 | .{ .x86_64, .windows }, |
| 612 | .{ .x86, .windows }, |
| 613 | .{ .x86_64, .macos }, |
| 614 | .{ .aarch64, .macos }, |
| 615 | }, |
| 616 | }); |
| 617 | |
| 618 | cases.addCase(.{ |
| 619 | .params = params, |
| 620 | .target = target, |
| 621 | .name = "trace through inline call", |
| 622 | // The main function has two inline calls to ensure |
| 623 | // that inlinees in PDBs are properly deduplicated. |
| 624 | .source = |
| 625 | \\pub fn main() !void { |
| 626 | \\ try foo(false); |
| 627 | \\ try foo(true); |
| 628 | \\} |
| 629 | \\inline fn foo(b: bool) !void { |
| 630 | \\ if (b) try bar(); |
| 631 | \\} |
| 632 | \\fn bar() !void { |
| 633 | \\ return error.ThisIsSoSad; |
| 634 | \\} |
| 635 | , |
| 636 | .expect_error = "ThisIsSoSad", |
| 637 | .expect_trace = switch (target.os.tag) { |
| 638 | // LLVM doesn't emit column info in the binary annotations for inlinee callees in PDBs, |
| 639 | // so our expected result is slightly different for Windows than on other operating |
| 640 | // systems. |
| 641 | .windows => |
| 642 | \\source.zig:9:5: [address] in bar |
| 643 | \\ return error.ThisIsSoSad; |
| 644 | \\ ^ |
| 645 | \\source.zig:6: [address] in foo |
| 646 | \\ if (b) try bar(); |
| 647 | \\ |
| 648 | \\source.zig:3:5: [address] in main |
| 649 | \\ try foo(true); |
| 650 | \\ ^ |
| 651 | , |
| 652 | else => |
| 653 | \\source.zig:9:5: [address] in bar |
| 654 | \\ return error.ThisIsSoSad; |
| 655 | \\ ^ |
| 656 | \\source.zig:6:12: [address] in foo |
| 657 | \\ if (b) try bar(); |
| 658 | \\ ^ |
| 659 | \\source.zig:3:5: [address] in main |
| 660 | \\ try foo(true); |
| 661 | \\ ^ |
| 662 | , |
| 663 | }, |
| 664 | .disable_trace_optimized = &.{ |
| 665 | .{ .x86_64, .freebsd }, |
| 666 | .{ .x86_64, .netbsd }, |
| 667 | .{ .x86_64, .linux }, |
| 668 | .{ .x86, .linux }, |
| 669 | .{ .aarch64, .freebsd }, |
| 670 | .{ .aarch64, .netbsd }, |
| 671 | .{ .aarch64, .openbsd }, |
| 672 | .{ .aarch64, .linux }, |
| 673 | .{ .loongarch64, .linux }, |
| 674 | .{ .powerpc64le, .linux }, |
| 675 | .{ .riscv64, .linux }, |
| 676 | .{ .s390x, .linux }, |
| 677 | .{ .x86_64, .openbsd }, |
| 678 | .{ .x86_64, .windows }, |
| 679 | .{ .x86, .windows }, |
| 680 | .{ .x86_64, .macos }, |
| 681 | .{ .aarch64, .macos }, |
| 682 | }, |
| 683 | }); |
| 684 | } |