| ... | ... | @@ -24528,8 +24528,7 @@ fn coerceTupleToStruct( |
| 24528 | 24528 | const struct_ty = try sema.resolveTypeFields(block, dest_ty_src, dest_ty); |
| 24529 | 24529 | |
| 24530 | 24530 | if (struct_ty.isTupleOrAnonStruct()) { |
| 24531 | | // NOTE remember to handle comptime fields |
| 24532 | | return sema.fail(block, dest_ty_src, "TODO: implement coercion from tuples to tuples", .{}); |
| 24531 | return sema.coerceTupleToTuple(block, struct_ty, inst, inst_src); |
| 24533 | 24532 | } |
| 24534 | 24533 | |
| 24535 | 24534 | const fields = struct_ty.structFields(); |
| ... | ... | @@ -24612,6 +24611,110 @@ fn coerceTupleToStruct( |
| 24612 | 24611 | ); |
| 24613 | 24612 | } |
| 24614 | 24613 | |
| 24614 | fn coerceTupleToTuple( |
| 24615 | sema: *Sema, |
| 24616 | block: *Block, |
| 24617 | tuple_ty: Type, |
| 24618 | inst: Air.Inst.Ref, |
| 24619 | inst_src: LazySrcLoc, |
| 24620 | ) !Air.Inst.Ref { |
| 24621 | const field_count = tuple_ty.structFieldCount(); |
| 24622 | const field_vals = try sema.arena.alloc(Value, field_count); |
| 24623 | const field_refs = try sema.arena.alloc(Air.Inst.Ref, field_vals.len); |
| 24624 | mem.set(Air.Inst.Ref, field_refs, .none); |
| 24625 | |
| 24626 | const inst_ty = sema.typeOf(inst); |
| 24627 | const tuple = inst_ty.tupleFields(); |
| 24628 | var runtime_src: ?LazySrcLoc = null; |
| 24629 | for (tuple.types) |_, i_usize| { |
| 24630 | const i = @intCast(u32, i_usize); |
| 24631 | const field_src = inst_src; // TODO better source location |
| 24632 | const field_name = if (inst_ty.castTag(.anon_struct)) |payload| |
| 24633 | payload.data.names[i] |
| 24634 | else |
| 24635 | try std.fmt.allocPrint(sema.arena, "{d}", .{i}); |
| 24636 | |
| 24637 | if (mem.eql(u8, field_name, "len")) { |
| 24638 | return sema.fail(block, field_src, "cannot assign to 'len' field of tuple", .{}); |
| 24639 | } |
| 24640 | |
| 24641 | const field_index = try sema.tupleFieldIndex(block, tuple_ty, field_name, field_src); |
| 24642 | |
| 24643 | const field_ty = tuple_ty.structFieldType(i); |
| 24644 | const default_val = tuple_ty.structFieldDefaultValue(i); |
| 24645 | const elem_ref = try tupleField(sema, block, inst_src, inst, field_src, i); |
| 24646 | const coerced = try sema.coerce(block, field_ty, elem_ref, field_src); |
| 24647 | field_refs[field_index] = coerced; |
| 24648 | if (default_val.tag() != .unreachable_value) { |
| 24649 | const init_val = (try sema.resolveMaybeUndefVal(block, field_src, coerced)) orelse { |
| 24650 | return sema.failWithNeededComptime(block, field_src, "value stored in comptime field must be comptime known"); |
| 24651 | }; |
| 24652 | |
| 24653 | if (!init_val.eql(default_val, field_ty, sema.mod)) { |
| 24654 | return sema.failWithInvalidComptimeFieldStore(block, field_src, inst_ty, i); |
| 24655 | } |
| 24656 | } |
| 24657 | if (runtime_src == null) { |
| 24658 | if (try sema.resolveMaybeUndefVal(block, field_src, coerced)) |field_val| { |
| 24659 | field_vals[field_index] = field_val; |
| 24660 | } else { |
| 24661 | runtime_src = field_src; |
| 24662 | } |
| 24663 | } |
| 24664 | } |
| 24665 | |
| 24666 | // Populate default field values and report errors for missing fields. |
| 24667 | var root_msg: ?*Module.ErrorMsg = null; |
| 24668 | |
| 24669 | for (field_refs) |*field_ref, i| { |
| 24670 | if (field_ref.* != .none) continue; |
| 24671 | |
| 24672 | const default_val = tuple_ty.structFieldDefaultValue(i); |
| 24673 | const field_ty = tuple_ty.structFieldType(i); |
| 24674 | |
| 24675 | const field_src = inst_src; // TODO better source location |
| 24676 | if (default_val.tag() == .unreachable_value) { |
| 24677 | if (tuple_ty.isTuple()) { |
| 24678 | const template = "missing tuple field: {d}"; |
| 24679 | if (root_msg) |msg| { |
| 24680 | try sema.errNote(block, field_src, msg, template, .{i}); |
| 24681 | } else { |
| 24682 | root_msg = try sema.errMsg(block, field_src, template, .{i}); |
| 24683 | } |
| 24684 | continue; |
| 24685 | } |
| 24686 | const template = "missing struct field: {s}"; |
| 24687 | const args = .{tuple_ty.structFieldName(i)}; |
| 24688 | if (root_msg) |msg| { |
| 24689 | try sema.errNote(block, field_src, msg, template, args); |
| 24690 | } else { |
| 24691 | root_msg = try sema.errMsg(block, field_src, template, args); |
| 24692 | } |
| 24693 | continue; |
| 24694 | } |
| 24695 | if (runtime_src == null) { |
| 24696 | field_vals[i] = default_val; |
| 24697 | } else { |
| 24698 | field_ref.* = try sema.addConstant(field_ty, default_val); |
| 24699 | } |
| 24700 | } |
| 24701 | |
| 24702 | if (root_msg) |msg| { |
| 24703 | try sema.addDeclaredHereNote(msg, tuple_ty); |
| 24704 | return sema.failWithOwnedErrorMsg(block, msg); |
| 24705 | } |
| 24706 | |
| 24707 | if (runtime_src) |rs| { |
| 24708 | try sema.requireRuntimeBlock(block, inst_src, rs); |
| 24709 | return block.addAggregateInit(tuple_ty, field_refs); |
| 24710 | } |
| 24711 | |
| 24712 | return sema.addConstant( |
| 24713 | tuple_ty, |
| 24714 | try Value.Tag.aggregate.create(sema.arena, field_vals), |
| 24715 | ); |
| 24716 | } |
| 24717 | |
| 24615 | 24718 | fn analyzeDeclVal( |
| 24616 | 24719 | sema: *Sema, |
| 24617 | 24720 | block: *Block, |