Special-case switching on error union capture#18173
Special-case switching on error union capture#18173andrewrk merged 16 commits intoziglang:masterfrom
Conversation
0f08626 to
0436b3b
Compare
|
Not sure what the errors in the CI are - I can reproduce the segfault in bootstrap locally, but don't know what would be causing it. Perhaps there is some incompatibility with the x86_64 backend. Edit: The segfault referenced above has been fixed, but there is a new/different segfault happening in the CI that I cannot reproduce. |
ad85f90 to
815b4d4
Compare
815b4d4 to
905abb9
Compare
905abb9 to
599ca96
Compare
|
Looks like stage2 is broken, probably due to the C backend emitting broken code in readFromPackedMemory and utf8ToUtf16Le. Since this is Linux Release, I'd guess that readFromPackedMemory is broken. I do see 3 ways forward, since I suspect you checked that the miscompilation is not detectable within standard debugging tools (valgrind, memsanitizer etc):
Please let me know what you think. |
|
Aren't the quoted warnings from The failure in this case seems to be after those: |
Buffer overreads or overwrites are undefined behavior and, if conforming to the c standard, compilers are free to optimize based on the absence of such things and miscompile your programs. |
599ca96 to
3d26d8c
Compare
This change only emits the unwrap_errunion_err instruction if the error capture is actually used in a branch.
3d26d8c to
67d7d7b
Compare
I think you were probably right - I started investigating and it looked like a bug when Now that I've rebased to include those changes, hopefully the CI will pass on all the x86_64-linux targets. |
| // The non-error and error cases are only peers if the error case is just a switch expression; | ||
| // the pattern `if (x) {...} else |err| blk: { switch (err) {...} }` does not consider the | ||
| // non-error and error case to be peers. |
There was a problem hiding this comment.
I don't like how this turns a limitation of the compiler into a feature of the language.
There was a problem hiding this comment.
I was just trying to be clear about what the behaviour is so as to not cause confusion, but I can see that this may the source of future problems if peer type resolution changes for these cases. Should I remove the sentence, or add a note saying something along the lines of 'this is the current behaviour and may change'?
There was a problem hiding this comment.
I think it's good enough for now. I need to go over the langref anyway; it's collected quite a few different contributors' conflicting ideas about what a langref should be and it needs to be reworked by one person with a vision.
andrewrk
left a comment
There was a problem hiding this comment.
Thank you @dweiller - nice work. The amount of additions and copy-pasted code makes me a bit uneasy, but you made up for it with robust test coverage.
I have a couple review comments but they are insignificant and so I will proceed with the merge regardless. Feel free to ignore them, they can be cleaned up later along with a future enhancement or bug fix.
| pub const Bits = packed struct(u32) { | ||
| /// If true, one or more prongs have multiple items. | ||
| has_multi_cases: bool, | ||
| /// If true, there is an else prong. This is mutually exclusive with `has_under`. |
There was a problem hiding this comment.
this comment looks like it was copy pasted and no longer applies since there is no has_under field.
| sema.inst_map.putAssumeCapacity(err_capture_inst, spa.operand); | ||
| } | ||
| defer if (extra.data.bits.any_uses_err_capture) assert(sema.inst_map.remove(err_capture_inst)); | ||
| _ = try sema.analyzeSwitchRuntimeBlock( |
There was a problem hiding this comment.
it looks like this return value is never used by any caller.
| // The non-error and error cases are only peers if the error case is just a switch expression; | ||
| // the pattern `if (x) {...} else |err| blk: { switch (err) {...} }` does not consider the | ||
| // non-error and error case to be peers. |
There was a problem hiding this comment.
I think it's good enough for now. I need to go over the langref anyway; it's collected quite a few different contributors' conflicting ideas about what a langref should be and it needs to be reworked by one person with a vision.
I wouldn't be surprise if there is a way to unify the new logic more with the regular switch logic to reduce the amount of duplication. However, there are a number of subtle differences that made it tricky to do without requiring interleaving a bunch of |
Closes #11957 and as well as the related issues #16770 and #11812.
There are a few things left to do before merging:
if (x) { ... } else |err| switch (err) { ... }pattern-Donly-ast-checkbuild flag?)AstGen.zigandSema.zig)ifandcatchpatterns in langref (contrast with using a block around theswitch)