| author | |
| committer | |
| log | 7b00bef6bf91e69b0bc3a7cec31476573301a3dc |
| tree | e0477b65a71c3068eba481d552f3d11c71fabb80 |
| parent | 0ef2e2520af59a42014399282ddea983fa526449 |
4 files changed, 45 insertions(+), 38 deletions(-)
src/Sema.zig+23-11| ... | @@ -6413,21 +6413,33 @@ fn validateSwitchNoRange( | ... | @@ -6413,21 +6413,33 @@ fn validateSwitchNoRange( |
| 6413 | fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 6413 | fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 6414 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; | 6414 | const inst_data = sema.code.instructions.items(.data)[inst].pl_node; |
| 6415 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; | 6415 | const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; |
| 6416 | const lhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; | 6416 | const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 6417 | const rhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; | 6417 | const name_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; |
| 6418 | const container_type = try sema.resolveType(block, lhs_src, extra.lhs); | 6418 | const unresolved_ty = try sema.resolveType(block, ty_src, extra.lhs); |
| 6419 | const field_name = try sema.resolveConstString(block, rhs_src, extra.rhs); | 6419 | const field_name = try sema.resolveConstString(block, name_src, extra.rhs); |
| 6420 | 6420 | const ty = try sema.resolveTypeFields(block, ty_src, unresolved_ty); | |
| 6421 | const has_field = switch (container_type.zigTypeTag()) { | 6421 | |
| 6422 | .Struct => container_type.structFields().contains(field_name), | 6422 | const has_field = hf: { |
| 6423 | .Union => container_type.unionFields().contains(field_name), | 6423 | if (ty.isSlice()) { |
| 6424 | .Enum => container_type.enumFields().contains(field_name), | 6424 | if (mem.eql(u8, field_name, "ptr")) break :hf true; |
| 6425 | else => return sema.fail(block, lhs_src, "expected struct, enum, or union, found '{}'", .{container_type}), | 6425 | if (mem.eql(u8, field_name, "len")) break :hf true; |
| 6426 | break :hf false; | ||
| 6427 | } | ||
| 6428 | break :hf switch (ty.zigTypeTag()) { | ||
| 6429 | .Struct => ty.structFields().contains(field_name), | ||
| 6430 | .Union => ty.unionFields().contains(field_name), | ||
| 6431 | .Enum => ty.enumFields().contains(field_name), | ||
| 6432 | .Array => mem.eql(u8, field_name, "len"), | ||
| 6433 | else => return sema.fail(block, ty_src, "type '{}' does not support '@hasField'", .{ | ||
| 6434 | ty, | ||
| 6435 | }), | ||
| 6436 | }; | ||
| 6426 | }; | 6437 | }; |
| 6427 | if (has_field) { | 6438 | if (has_field) { |
| 6428 | return Air.Inst.Ref.bool_true; | 6439 | return Air.Inst.Ref.bool_true; |
| 6440 | } else { | ||
| 6441 | return Air.Inst.Ref.bool_false; | ||
| 6429 | } | 6442 | } |
| 6430 | return Air.Inst.Ref.bool_false; | ||
| 6431 | } | 6443 | } |
| 6432 | 6444 | ||
| 6433 | fn zirHasDecl(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 6445 | fn zirHasDecl(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
test/behavior.zig-1| ... | @@ -128,7 +128,6 @@ test { | ... | @@ -128,7 +128,6 @@ test { |
| 128 | _ = @import("behavior/fn_in_struct_in_comptime.zig"); | 128 | _ = @import("behavior/fn_in_struct_in_comptime.zig"); |
| 129 | _ = @import("behavior/for_stage1.zig"); | 129 | _ = @import("behavior/for_stage1.zig"); |
| 130 | _ = @import("behavior/generics_stage1.zig"); | 130 | _ = @import("behavior/generics_stage1.zig"); |
| 131 | _ = @import("behavior/hasfield_stage1.zig"); | ||
| 132 | _ = @import("behavior/if_stage1.zig"); | 131 | _ = @import("behavior/if_stage1.zig"); |
| 133 | _ = @import("behavior/import.zig"); | 132 | _ = @import("behavior/import.zig"); |
| 134 | _ = @import("behavior/incomplete_struct_param_tld.zig"); | 133 | _ = @import("behavior/incomplete_struct_param_tld.zig"); |
test/behavior/hasfield.zig+22| ... | @@ -2,6 +2,28 @@ const expect = @import("std").testing.expect; | ... | @@ -2,6 +2,28 @@ const expect = @import("std").testing.expect; |
| 2 | const builtin = @import("builtin"); | 2 | const builtin = @import("builtin"); |
| 3 | 3 | ||
| 4 | test "@hasField" { | 4 | test "@hasField" { |
| 5 | const struc = struct { | ||
| 6 | a: i32, | ||
| 7 | b: []u8, | ||
| 8 | |||
| 9 | pub const nope = 1; | ||
| 10 | }; | ||
| 11 | try expect(@hasField(struc, "a") == true); | ||
| 12 | try expect(@hasField(struc, "b") == true); | ||
| 13 | try expect(@hasField(struc, "non-existant") == false); | ||
| 14 | try expect(@hasField(struc, "nope") == false); | ||
| 15 | |||
| 16 | const unin = union { | ||
| 17 | a: u64, | ||
| 18 | b: []u16, | ||
| 19 | |||
| 20 | pub const nope = 1; | ||
| 21 | }; | ||
| 22 | try expect(@hasField(unin, "a") == true); | ||
| 23 | try expect(@hasField(unin, "b") == true); | ||
| 24 | try expect(@hasField(unin, "non-existant") == false); | ||
| 25 | try expect(@hasField(unin, "nope") == false); | ||
| 26 | |||
| 5 | const enm = enum { | 27 | const enm = enum { |
| 6 | a, | 28 | a, |
| 7 | b, | 29 | b, |
test/behavior/hasfield_stage1.zig deleted-26| ... | @@ -1,26 +0,0 @@ | ||
| 1 | const expect = @import("std").testing.expect; | ||
| 2 | const builtin = @import("builtin"); | ||
| 3 | |||
| 4 | test "@hasField" { | ||
| 5 | const struc = struct { | ||
| 6 | a: i32, | ||
| 7 | b: []const u8, | ||
| 8 | |||
| 9 | pub const nope = 1; | ||
| 10 | }; | ||
| 11 | try expect(@hasField(struc, "a") == true); | ||
| 12 | try expect(@hasField(struc, "b") == true); | ||
| 13 | try expect(@hasField(struc, "non-existant") == false); | ||
| 14 | try expect(@hasField(struc, "nope") == false); | ||
| 15 | |||
| 16 | const unin = union { | ||
| 17 | a: u64, | ||
| 18 | b: []const u16, | ||
| 19 | |||
| 20 | pub const nope = 1; | ||
| 21 | }; | ||
| 22 | try expect(@hasField(unin, "a") == true); | ||
| 23 | try expect(@hasField(unin, "b") == true); | ||
| 24 | try expect(@hasField(unin, "non-existant") == false); | ||
| 25 | try expect(@hasField(unin, "nope") == false); | ||
| 26 | } | ||