| ... | @@ -11481,6 +11481,19 @@ fn zirUnionInit(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A | ... | @@ -11481,6 +11481,19 @@ fn zirUnionInit(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 11481 | const union_ty = try sema.resolveType(block, ty_src, extra.union_type); | 11481 | const union_ty = try sema.resolveType(block, ty_src, extra.union_type); |
| 11482 | const field_name = try sema.resolveConstString(block, field_src, extra.field_name); | 11482 | const field_name = try sema.resolveConstString(block, field_src, extra.field_name); |
| 11483 | const init = sema.resolveInst(extra.init); | 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 | const union_obj = union_ty.cast(Type.Payload.Union).?.data; | 11497 | const union_obj = union_ty.cast(Type.Payload.Union).?.data; |
| 11485 | const field_index_usize = union_obj.fields.getIndex(field_name) orelse | 11498 | const field_index_usize = union_obj.fields.getIndex(field_name) orelse |
| 11486 | return sema.failWithBadUnionFieldAccess(block, union_obj, field_src, field_name); | 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,14 +11501,14 @@ fn zirUnionInit(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 11488 | | 11501 | |
| 11489 | if (try sema.resolveMaybeUndefVal(block, init_src, init)) |init_val| { | 11502 | if (try sema.resolveMaybeUndefVal(block, init_src, init)) |init_val| { |
| 11490 | const tag_val = try Value.Tag.enum_field_index.create(sema.arena, field_index); | 11503 | const tag_val = try Value.Tag.enum_field_index.create(sema.arena, field_index); |
| 11491 | return sema.addConstant( | 11504 | return sema.addConstant(union_ty, try Value.Tag.@"union".create(sema.arena, .{ |
| 11492 | union_ty, | 11505 | .tag = tag_val, |
| 11493 | try Value.Tag.@"union".create(sema.arena, .{ .tag = tag_val, .val = init_val }), | 11506 | .val = init_val, |
| 11494 | ); | 11507 | })); |
| 11495 | } | 11508 | } |
| 11496 | | 11509 | |
| 11497 | try sema.requireRuntimeBlock(block, init_src); | 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 | return block.addUnionInit(union_ty, field_index, init); | 11512 | return block.addUnionInit(union_ty, field_index, init); |
| 11500 | } | 11513 | } |
| 11501 | | 11514 | |
| ... | @@ -15903,6 +15916,11 @@ fn coerce( | ... | @@ -15903,6 +15916,11 @@ fn coerce( |
| 15903 | }, | 15916 | }, |
| 15904 | .Union => switch (inst_ty.zigTypeTag()) { | 15917 | .Union => switch (inst_ty.zigTypeTag()) { |
| 15905 | .Enum, .EnumLiteral => return sema.coerceEnumToUnion(block, dest_ty, dest_ty_src, inst, inst_src), | 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 | else => {}, | 15924 | else => {}, |
| 15907 | }, | 15925 | }, |
| 15908 | .Array => switch (inst_ty.zigTypeTag()) { | 15926 | .Array => switch (inst_ty.zigTypeTag()) { |
| ... | @@ -16983,6 +17001,40 @@ fn coerceEnumToUnion( | ... | @@ -16983,6 +17001,40 @@ fn coerceEnumToUnion( |
| 16983 | return sema.failWithOwnedErrorMsg(msg); | 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 | /// If the lengths match, coerces element-wise. | 17038 | /// If the lengths match, coerces element-wise. |
| 16987 | fn coerceArrayLike( | 17039 | fn coerceArrayLike( |
| 16988 | sema: *Sema, | 17040 | sema: *Sema, |