| ... | @@ -21892,17 +21892,18 @@ fn unionFieldPtr( | ... | @@ -21892,17 +21892,18 @@ fn unionFieldPtr( |
| 21892 | if (union_val.isUndef()) { | 21892 | if (union_val.isUndef()) { |
| 21893 | return sema.failWithUseOfUndef(block, src); | 21893 | return sema.failWithUseOfUndef(block, src); |
| 21894 | } | 21894 | } |
| | 21895 | const enum_field_index = union_obj.tag_ty.enumFieldIndex(field_name).?; |
| 21895 | const tag_and_val = union_val.castTag(.@"union").?.data; | 21896 | const tag_and_val = union_val.castTag(.@"union").?.data; |
| 21896 | var field_tag_buf: Value.Payload.U32 = .{ | 21897 | var field_tag_buf: Value.Payload.U32 = .{ |
| 21897 | .base = .{ .tag = .enum_field_index }, | 21898 | .base = .{ .tag = .enum_field_index }, |
| 21898 | .data = field_index, | 21899 | .data = @intCast(u32, enum_field_index), |
| 21899 | }; | 21900 | }; |
| 21900 | const field_tag = Value.initPayload(&field_tag_buf.base); | 21901 | const field_tag = Value.initPayload(&field_tag_buf.base); |
| 21901 | const tag_matches = tag_and_val.tag.eql(field_tag, union_obj.tag_ty, sema.mod); | 21902 | const tag_matches = tag_and_val.tag.eql(field_tag, union_obj.tag_ty, sema.mod); |
| 21902 | if (!tag_matches) { | 21903 | if (!tag_matches) { |
| 21903 | const msg = msg: { | 21904 | const msg = msg: { |
| 21904 | const active_index = tag_and_val.tag.castTag(.enum_field_index).?.data; | 21905 | const active_index = tag_and_val.tag.castTag(.enum_field_index).?.data; |
| 21905 | const active_field_name = union_obj.fields.keys()[active_index]; | 21906 | const active_field_name = union_obj.tag_ty.enumFieldName(active_index); |
| 21906 | const msg = try sema.errMsg(block, src, "access of union field '{s}' while field '{s}' is active", .{ field_name, active_field_name }); | 21907 | const msg = try sema.errMsg(block, src, "access of union field '{s}' while field '{s}' is active", .{ field_name, active_field_name }); |
| 21907 | errdefer msg.destroy(sema.gpa); | 21908 | errdefer msg.destroy(sema.gpa); |
| 21908 | try sema.addDeclaredHereNote(msg, union_ty); | 21909 | try sema.addDeclaredHereNote(msg, union_ty); |
| ... | @@ -21927,12 +21928,11 @@ fn unionFieldPtr( | ... | @@ -21927,12 +21928,11 @@ fn unionFieldPtr( |
| 21927 | if (!initializing and union_obj.layout == .Auto and block.wantSafety() and | 21928 | if (!initializing and union_obj.layout == .Auto and block.wantSafety() and |
| 21928 | union_ty.unionTagTypeSafety() != null and union_obj.fields.count() > 1) | 21929 | union_ty.unionTagTypeSafety() != null and union_obj.fields.count() > 1) |
| 21929 | { | 21930 | { |
| 21930 | const enum_ty = union_ty.unionTagTypeHypothetical(); | | |
| 21931 | const wanted_tag_val = try Value.Tag.enum_field_index.create(sema.arena, field_index); | 21931 | const wanted_tag_val = try Value.Tag.enum_field_index.create(sema.arena, field_index); |
| 21932 | const wanted_tag = try sema.addConstant(enum_ty, wanted_tag_val); | 21932 | const wanted_tag = try sema.addConstant(union_obj.tag_ty, wanted_tag_val); |
| 21933 | // TODO would it be better if get_union_tag supported pointers to unions? | 21933 | // TODO would it be better if get_union_tag supported pointers to unions? |
| 21934 | const union_val = try block.addTyOp(.load, union_ty, union_ptr); | 21934 | const union_val = try block.addTyOp(.load, union_ty, union_ptr); |
| 21935 | const active_tag = try block.addTyOp(.get_union_tag, enum_ty, union_val); | 21935 | const active_tag = try block.addTyOp(.get_union_tag, union_obj.tag_ty, union_val); |
| 21936 | const ok = try block.addBinOp(.cmp_eq, active_tag, wanted_tag); | 21936 | const ok = try block.addBinOp(.cmp_eq, active_tag, wanted_tag); |
| 21937 | try sema.addSafetyCheck(block, ok, .inactive_union_field); | 21937 | try sema.addSafetyCheck(block, ok, .inactive_union_field); |
| 21938 | } | 21938 | } |
| ... | @@ -21963,9 +21963,10 @@ fn unionFieldVal( | ... | @@ -21963,9 +21963,10 @@ fn unionFieldVal( |
| 21963 | if (union_val.isUndef()) return sema.addConstUndef(field.ty); | 21963 | if (union_val.isUndef()) return sema.addConstUndef(field.ty); |
| 21964 | | 21964 | |
| 21965 | const tag_and_val = union_val.castTag(.@"union").?.data; | 21965 | const tag_and_val = union_val.castTag(.@"union").?.data; |
| | 21966 | const enum_field_index = union_obj.tag_ty.enumFieldIndex(field_name).?; |
| 21966 | var field_tag_buf: Value.Payload.U32 = .{ | 21967 | var field_tag_buf: Value.Payload.U32 = .{ |
| 21967 | .base = .{ .tag = .enum_field_index }, | 21968 | .base = .{ .tag = .enum_field_index }, |
| 21968 | .data = field_index, | 21969 | .data = @intCast(u32, enum_field_index), |
| 21969 | }; | 21970 | }; |
| 21970 | const field_tag = Value.initPayload(&field_tag_buf.base); | 21971 | const field_tag = Value.initPayload(&field_tag_buf.base); |
| 21971 | const tag_matches = tag_and_val.tag.eql(field_tag, union_obj.tag_ty, sema.mod); | 21972 | const tag_matches = tag_and_val.tag.eql(field_tag, union_obj.tag_ty, sema.mod); |
| ... | @@ -21976,7 +21977,7 @@ fn unionFieldVal( | ... | @@ -21976,7 +21977,7 @@ fn unionFieldVal( |
| 21976 | } else { | 21977 | } else { |
| 21977 | const msg = msg: { | 21978 | const msg = msg: { |
| 21978 | const active_index = tag_and_val.tag.castTag(.enum_field_index).?.data; | 21979 | const active_index = tag_and_val.tag.castTag(.enum_field_index).?.data; |
| 21979 | const active_field_name = union_obj.fields.keys()[active_index]; | 21980 | const active_field_name = union_obj.tag_ty.enumFieldName(active_index); |
| 21980 | const msg = try sema.errMsg(block, src, "access of union field '{s}' while field '{s}' is active", .{ field_name, active_field_name }); | 21981 | const msg = try sema.errMsg(block, src, "access of union field '{s}' while field '{s}' is active", .{ field_name, active_field_name }); |
| 21981 | errdefer msg.destroy(sema.gpa); | 21982 | errdefer msg.destroy(sema.gpa); |
| 21982 | try sema.addDeclaredHereNote(msg, union_ty); | 21983 | try sema.addDeclaredHereNote(msg, union_ty); |
| ... | @@ -22001,10 +22002,9 @@ fn unionFieldVal( | ... | @@ -22001,10 +22002,9 @@ fn unionFieldVal( |
| 22001 | if (union_obj.layout == .Auto and block.wantSafety() and | 22002 | if (union_obj.layout == .Auto and block.wantSafety() and |
| 22002 | union_ty.unionTagTypeSafety() != null and union_obj.fields.count() > 1) | 22003 | union_ty.unionTagTypeSafety() != null and union_obj.fields.count() > 1) |
| 22003 | { | 22004 | { |
| 22004 | const enum_ty = union_ty.unionTagTypeHypothetical(); | | |
| 22005 | const wanted_tag_val = try Value.Tag.enum_field_index.create(sema.arena, field_index); | 22005 | const wanted_tag_val = try Value.Tag.enum_field_index.create(sema.arena, field_index); |
| 22006 | const wanted_tag = try sema.addConstant(enum_ty, wanted_tag_val); | 22006 | const wanted_tag = try sema.addConstant(union_obj.tag_ty, wanted_tag_val); |
| 22007 | const active_tag = try block.addTyOp(.get_union_tag, enum_ty, union_byval); | 22007 | const active_tag = try block.addTyOp(.get_union_tag, union_obj.tag_ty, union_byval); |
| 22008 | const ok = try block.addBinOp(.cmp_eq, active_tag, wanted_tag); | 22008 | const ok = try block.addBinOp(.cmp_eq, active_tag, wanted_tag); |
| 22009 | try sema.addSafetyCheck(block, ok, .inactive_union_field); | 22009 | try sema.addSafetyCheck(block, ok, .inactive_union_field); |
| 22010 | } | 22010 | } |