| ... | ... | @@ -11481,6 +11481,19 @@ fn zirUnionInit(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 11481 | 11481 | const union_ty = try sema.resolveType(block, ty_src, extra.union_type); |
| 11482 | 11482 | const field_name = try sema.resolveConstString(block, field_src, extra.field_name); |
| 11483 | 11483 | const init = sema.resolveInst(extra.init); |
| 11484 | return sema.unionInit(block, init, init_src, union_ty, ty_src, field_name, field_src); |
| 11485 | } |
| 11486 | |
| 11487 | fn unionInit( |
| 11488 | sema: *Sema, |
| 11489 | block: *Block, |
| 11490 | init: Air.Inst.Ref, |
| 11491 | init_src: LazySrcLoc, |
| 11492 | union_ty: Type, |
| 11493 | union_ty_src: LazySrcLoc, |
| 11494 | field_name: []const u8, |
| 11495 | field_src: LazySrcLoc, |
| 11496 | ) CompileError!Air.Inst.Ref { |
| 11484 | 11497 | const union_obj = union_ty.cast(Type.Payload.Union).?.data; |
| 11485 | 11498 | const field_index_usize = union_obj.fields.getIndex(field_name) orelse |
| 11486 | 11499 | return sema.failWithBadUnionFieldAccess(block, union_obj, field_src, field_name); |
| ... | ... | @@ -11488,14 +11501,14 @@ fn zirUnionInit(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 11488 | 11501 | |
| 11489 | 11502 | if (try sema.resolveMaybeUndefVal(block, init_src, init)) |init_val| { |
| 11490 | 11503 | const tag_val = try Value.Tag.enum_field_index.create(sema.arena, field_index); |
| 11491 | | return sema.addConstant( |
| 11492 | | union_ty, |
| 11493 | | try Value.Tag.@"union".create(sema.arena, .{ .tag = tag_val, .val = init_val }), |
| 11494 | | ); |
| 11504 | return sema.addConstant(union_ty, try Value.Tag.@"union".create(sema.arena, .{ |
| 11505 | .tag = tag_val, |
| 11506 | .val = init_val, |
| 11507 | })); |
| 11495 | 11508 | } |
| 11496 | 11509 | |
| 11497 | 11510 | try sema.requireRuntimeBlock(block, init_src); |
| 11498 | | try sema.resolveTypeLayout(block, ty_src, union_ty); |
| 11511 | try sema.resolveTypeLayout(block, union_ty_src, union_ty); |
| 11499 | 11512 | return block.addUnionInit(union_ty, field_index, init); |
| 11500 | 11513 | } |
| 11501 | 11514 | |
| ... | ... | @@ -15903,6 +15916,11 @@ fn coerce( |
| 15903 | 15916 | }, |
| 15904 | 15917 | .Union => switch (inst_ty.zigTypeTag()) { |
| 15905 | 15918 | .Enum, .EnumLiteral => return sema.coerceEnumToUnion(block, dest_ty, dest_ty_src, inst, inst_src), |
| 15919 | .Struct => { |
| 15920 | if (inst_ty.castTag(.anon_struct)) |anon_struct| { |
| 15921 | return sema.coerceAnonStructToUnion(block, dest_ty, dest_ty_src, inst, inst_src, anon_struct.data); |
| 15922 | } |
| 15923 | }, |
| 15906 | 15924 | else => {}, |
| 15907 | 15925 | }, |
| 15908 | 15926 | .Array => switch (inst_ty.zigTypeTag()) { |
| ... | ... | @@ -16983,6 +17001,40 @@ fn coerceEnumToUnion( |
| 16983 | 17001 | return sema.failWithOwnedErrorMsg(msg); |
| 16984 | 17002 | } |
| 16985 | 17003 | |
| 17004 | fn coerceAnonStructToUnion( |
| 17005 | sema: *Sema, |
| 17006 | block: *Block, |
| 17007 | union_ty: Type, |
| 17008 | union_ty_src: LazySrcLoc, |
| 17009 | inst: Air.Inst.Ref, |
| 17010 | inst_src: LazySrcLoc, |
| 17011 | anon_struct: Type.Payload.AnonStruct.Data, |
| 17012 | ) !Air.Inst.Ref { |
| 17013 | if (anon_struct.types.len != 1) { |
| 17014 | const msg = msg: { |
| 17015 | const msg = try sema.errMsg( |
| 17016 | block, |
| 17017 | inst_src, |
| 17018 | "cannot initialize multiple union fields at once, unions can only have one active field", |
| 17019 | .{}, |
| 17020 | ); |
| 17021 | errdefer msg.destroy(sema.gpa); |
| 17022 | |
| 17023 | // TODO add notes for where the anon struct was created to point out |
| 17024 | // the extra fields. |
| 17025 | |
| 17026 | try sema.addDeclaredHereNote(msg, union_ty); |
| 17027 | break :msg msg; |
| 17028 | }; |
| 17029 | return sema.failWithOwnedErrorMsg(msg); |
| 17030 | } |
| 17031 | |
| 17032 | const field_name = anon_struct.names[0]; |
| 17033 | const inst_ty = sema.typeOf(inst); |
| 17034 | const init = try sema.structFieldVal(block, inst_src, inst, field_name, inst_src, inst_ty); |
| 17035 | return sema.unionInit(block, init, inst_src, union_ty, union_ty_src, field_name, inst_src); |
| 17036 | } |
| 17037 | |
| 16986 | 17038 | /// If the lengths match, coerces element-wise. |
| 16987 | 17039 | fn coerceArrayLike( |
| 16988 | 17040 | sema: *Sema, |