authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-02-09 20:41:26-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-02-09 20:41:26-05:00
log34eb9f18acc2370973adcc7be0d010d62300e9a9
tree9701cfe85107331cc84b9ef6ee77c832afbfe013
parentca8580ece1ab07215b72394cc4ab3030bf9df139
signature Commit is signed but in an unrecognized format.

fix not updating debug info type of optional error sets

There's an unfortunate footgun in the current design of error sets. The debug info type for every error set is the same as the debug info type of the global error set, which is essentially an enum forward declaration. The problem is that when we "replace" the forward declaration with the final value, once we know all the possible errors, we have to update the pointers of every error set. So the footgun is that if you ever copy the debug info type of the global error set, you have to add the address of the pointer to a list of pointers that need to be updated once we "replace" the forward declaration. I activated the footgun when I introduced the optimization that `?anyerror` types are the same size as `anyerror` types (using 0 as the null value), because I introduced a pointer copy of the global error set debug info type, but forgot to add it to the list. I'm sure that there is a better way to code this, which does not have the footgun, but this commit contains only a fix, not a reworking of the logic. closes #1937

2 files changed, 8 insertions(+), 0 deletions(-)

src/analyze.cpp+3
...@@ -594,6 +594,9 @@ ZigType *get_optional_type(CodeGen *g, ZigType *child_type) {...@@ -594,6 +594,9 @@ ZigType *get_optional_type(CodeGen *g, ZigType *child_type) {
594 // function types are technically pointers594 // function types are technically pointers
595 entry->type_ref = child_type->type_ref;595 entry->type_ref = child_type->type_ref;
596 entry->di_type = child_type->di_type;596 entry->di_type = child_type->di_type;
597 if (entry->di_type == g->builtin_types.entry_global_error_set->di_type) {
598 g->error_di_types.append(&entry->di_type);
599 }
597 } else {600 } else {
598 assert(child_type->di_type);601 assert(child_type->di_type);
599 // create a struct with a boolean whether this is the null value602 // create a struct with a boolean whether this is the null value
test/stage1/behavior/error.zig+5
...@@ -330,3 +330,8 @@ test "optional error set is the same size as error set" {...@@ -330,3 +330,8 @@ test "optional error set is the same size as error set" {
330 expect(S.returnsOptErrSet() == null);330 expect(S.returnsOptErrSet() == null);
331 comptime expect(S.returnsOptErrSet() == null);331 comptime expect(S.returnsOptErrSet() == null);
332}332}
333
334test "debug info for optional error set" {
335 const SomeError = error{Hello};
336 var a_local_variable: ?SomeError = null;
337}