From 3fa5415253695001149ad65ae6f2ca8d0fa63565 Mon Sep 17 00:00:00 2001 From: martinhath Date: Fri, 26 Aug 2022 10:37:17 +0200 Subject: [PATCH] Sema: ensure resolveTypeFields is called for optional and error union types We call `sema.resolveTypeFields` in order to get the fields of structs and unions inserted into their data structures. If it isn't called, it can happen that the fields of a type is queried before those fields are inserted into (for instance) `Module.Union.fields`, which would result in a wrong 'no field named' error. Fixes: #12486 --- src/Sema.zig | 5 ++-- test/behavior.zig | 1 + test/behavior/bugs/12486.zig | 49 ++++++++++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 test/behavior/bugs/12486.zig diff --git a/src/Sema.zig b/src/Sema.zig index fc2a7f872a..2907999c25 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -16190,9 +16190,10 @@ fn fieldType( field_src: LazySrcLoc, ty_src: LazySrcLoc, ) CompileError!Air.Inst.Ref { - const resolved_ty = try sema.resolveTypeFields(block, ty_src, aggregate_ty); - var cur_ty = resolved_ty; + var cur_ty = aggregate_ty; while (true) { + const resolved_ty = try sema.resolveTypeFields(block, ty_src, cur_ty); + cur_ty = resolved_ty; switch (cur_ty.zigTypeTag()) { .Struct => { if (cur_ty.isAnonStruct()) { diff --git a/test/behavior.zig b/test/behavior.zig index 12edd6f9a3..8f581f372e 100644 --- a/test/behavior.zig +++ b/test/behavior.zig @@ -84,6 +84,7 @@ test { _ = @import("behavior/bugs/12003.zig"); _ = @import("behavior/bugs/12033.zig"); _ = @import("behavior/bugs/12430.zig"); + _ = @import("behavior/bugs/12486.zig"); _ = @import("behavior/byteswap.zig"); _ = @import("behavior/byval_arg_var.zig"); _ = @import("behavior/call.zig"); diff --git a/test/behavior/bugs/12486.zig b/test/behavior/bugs/12486.zig new file mode 100644 index 0000000000..f0d357efd1 --- /dev/null +++ b/test/behavior/bugs/12486.zig @@ -0,0 +1,49 @@ +const SomeEnum = union(enum) { + EnumVariant: u8, +}; + +const SomeStruct = struct { + struct_field: u8, +}; + +const OptEnum = struct { + opt_enum: ?SomeEnum, +}; + +const ErrEnum = struct { + err_enum: anyerror!SomeEnum, +}; + +const OptStruct = struct { + opt_struct: ?SomeStruct, +}; + +const ErrStruct = struct { + err_struct: anyerror!SomeStruct, +}; + +test { + _ = OptEnum{ + .opt_enum = .{ + .EnumVariant = 1, + }, + }; + + _ = ErrEnum{ + .err_enum = .{ + .EnumVariant = 1, + }, + }; + + _ = OptStruct{ + .opt_struct = .{ + .struct_field = 1, + }, + }; + + _ = ErrStruct{ + .err_struct = .{ + .struct_field = 1, + }, + }; +}