| ... | ... | @@ -2519,6 +2519,7 @@ fn zirStructDecl( |
| 2519 | 2519 | .layout = small.layout, |
| 2520 | 2520 | .status = .none, |
| 2521 | 2521 | .known_non_opv = undefined, |
| 2522 | .is_tuple = small.is_tuple, |
| 2522 | 2523 | .namespace = .{ |
| 2523 | 2524 | .parent = block.namespace, |
| 2524 | 2525 | .ty = struct_ty, |
| ... | ... | @@ -4291,13 +4292,12 @@ fn zirValidateArrayInit( |
| 4291 | 4292 | |
| 4292 | 4293 | if (instrs.len != array_len) switch (array_ty.zigTypeTag()) { |
| 4293 | 4294 | .Struct => { |
| 4294 | | const struct_obj = array_ty.castTag(.tuple).?.data; |
| 4295 | 4295 | var root_msg: ?*Module.ErrorMsg = null; |
| 4296 | 4296 | errdefer if (root_msg) |msg| msg.destroy(sema.gpa); |
| 4297 | 4297 | |
| 4298 | | for (struct_obj.values) |default_val, i| { |
| 4299 | | if (i < instrs.len) continue; |
| 4300 | | |
| 4298 | var i = instrs.len; |
| 4299 | while (i < array_len) : (i += 1) { |
| 4300 | const default_val = array_ty.structFieldDefaultValue(i); |
| 4301 | 4301 | if (default_val.tag() == .unreachable_value) { |
| 4302 | 4302 | const template = "missing tuple field with index {d}"; |
| 4303 | 4303 | if (root_msg) |msg| { |
| ... | ... | @@ -7230,7 +7230,7 @@ fn instantiateGenericCall( |
| 7230 | 7230 | } |
| 7231 | 7231 | |
| 7232 | 7232 | fn resolveTupleLazyValues(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!void { |
| 7233 | | if (!ty.isTuple()) return; |
| 7233 | if (!ty.isSimpleTuple()) return; |
| 7234 | 7234 | const tuple = ty.tupleFields(); |
| 7235 | 7235 | for (tuple.values) |field_val, i| { |
| 7236 | 7236 | try sema.resolveTupleLazyValues(block, src, tuple.types[i]); |
| ... | ... | @@ -7295,7 +7295,7 @@ fn zirElemTypeIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr |
| 7295 | 7295 | const indexable_ty = try sema.resolveType(block, .unneeded, bin.lhs); |
| 7296 | 7296 | assert(indexable_ty.isIndexable()); // validated by a previous instruction |
| 7297 | 7297 | if (indexable_ty.zigTypeTag() == .Struct) { |
| 7298 | | const elem_type = indexable_ty.tupleFields().types[@enumToInt(bin.rhs)]; |
| 7298 | const elem_type = indexable_ty.structFieldType(@enumToInt(bin.rhs)); |
| 7299 | 7299 | return sema.addType(elem_type); |
| 7300 | 7300 | } else { |
| 7301 | 7301 | const elem_type = indexable_ty.elemType2(); |
| ... | ... | @@ -11827,9 +11827,9 @@ fn analyzeTupleCat( |
| 11827 | 11827 | const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = src_node }; |
| 11828 | 11828 | const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = src_node }; |
| 11829 | 11829 | |
| 11830 | | const lhs_tuple = lhs_ty.tupleFields(); |
| 11831 | | const rhs_tuple = rhs_ty.tupleFields(); |
| 11832 | | const dest_fields = lhs_tuple.types.len + rhs_tuple.types.len; |
| 11830 | const lhs_len = lhs_ty.structFieldCount(); |
| 11831 | const rhs_len = rhs_ty.structFieldCount(); |
| 11832 | const dest_fields = lhs_len + rhs_len; |
| 11833 | 11833 | |
| 11834 | 11834 | if (dest_fields == 0) { |
| 11835 | 11835 | return sema.addConstant(Type.initTag(.empty_struct_literal), Value.initTag(.empty_struct_value)); |
| ... | ... | @@ -11841,20 +11841,23 @@ fn analyzeTupleCat( |
| 11841 | 11841 | |
| 11842 | 11842 | const opt_runtime_src = rs: { |
| 11843 | 11843 | var runtime_src: ?LazySrcLoc = null; |
| 11844 | | for (lhs_tuple.types) |ty, i| { |
| 11845 | | types[i] = ty; |
| 11846 | | values[i] = lhs_tuple.values[i]; |
| 11844 | var i: u32 = 0; |
| 11845 | while (i < lhs_len) : (i += 1) { |
| 11846 | types[i] = lhs_ty.structFieldType(i); |
| 11847 | const default_val = lhs_ty.structFieldDefaultValue(i); |
| 11848 | values[i] = default_val; |
| 11847 | 11849 | const operand_src = lhs_src; // TODO better source location |
| 11848 | | if (values[i].tag() == .unreachable_value) { |
| 11850 | if (default_val.tag() == .unreachable_value) { |
| 11849 | 11851 | runtime_src = operand_src; |
| 11850 | 11852 | } |
| 11851 | 11853 | } |
| 11852 | | const offset = lhs_tuple.types.len; |
| 11853 | | for (rhs_tuple.types) |ty, i| { |
| 11854 | | types[i + offset] = ty; |
| 11855 | | values[i + offset] = rhs_tuple.values[i]; |
| 11854 | i = 0; |
| 11855 | while (i < rhs_len) : (i += 1) { |
| 11856 | types[i + lhs_len] = rhs_ty.structFieldType(i); |
| 11857 | const default_val = rhs_ty.structFieldDefaultValue(i); |
| 11858 | values[i + lhs_len] = default_val; |
| 11856 | 11859 | const operand_src = rhs_src; // TODO better source location |
| 11857 | | if (rhs_tuple.values[i].tag() == .unreachable_value) { |
| 11860 | if (default_val.tag() == .unreachable_value) { |
| 11858 | 11861 | runtime_src = operand_src; |
| 11859 | 11862 | } |
| 11860 | 11863 | } |
| ... | ... | @@ -11874,14 +11877,15 @@ fn analyzeTupleCat( |
| 11874 | 11877 | try sema.requireRuntimeBlock(block, src, runtime_src); |
| 11875 | 11878 | |
| 11876 | 11879 | const element_refs = try sema.arena.alloc(Air.Inst.Ref, final_len); |
| 11877 | | for (lhs_tuple.types) |_, i| { |
| 11880 | var i: u32 = 0; |
| 11881 | while (i < lhs_len) : (i += 1) { |
| 11878 | 11882 | const operand_src = lhs_src; // TODO better source location |
| 11879 | 11883 | element_refs[i] = try sema.tupleFieldValByIndex(block, operand_src, lhs, @intCast(u32, i), lhs_ty); |
| 11880 | 11884 | } |
| 11881 | | const offset = lhs_tuple.types.len; |
| 11882 | | for (rhs_tuple.types) |_, i| { |
| 11885 | i = 0; |
| 11886 | while (i < rhs_len) : (i += 1) { |
| 11883 | 11887 | const operand_src = rhs_src; // TODO better source location |
| 11884 | | element_refs[i + offset] = |
| 11888 | element_refs[i + lhs_len] = |
| 11885 | 11889 | try sema.tupleFieldValByIndex(block, operand_src, rhs, @intCast(u32, i), rhs_ty); |
| 11886 | 11890 | } |
| 11887 | 11891 | |
| ... | ... | @@ -12107,12 +12111,11 @@ fn analyzeTupleMul( |
| 12107 | 12111 | factor: u64, |
| 12108 | 12112 | ) CompileError!Air.Inst.Ref { |
| 12109 | 12113 | const operand_ty = sema.typeOf(operand); |
| 12110 | | const operand_tuple = operand_ty.tupleFields(); |
| 12111 | 12114 | const src = LazySrcLoc.nodeOffset(src_node); |
| 12112 | 12115 | const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = src_node }; |
| 12113 | 12116 | const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = src_node }; |
| 12114 | 12117 | |
| 12115 | | const tuple_len = operand_tuple.types.len; |
| 12118 | const tuple_len = operand_ty.structFieldCount(); |
| 12116 | 12119 | const final_len_u64 = std.math.mul(u64, tuple_len, factor) catch |
| 12117 | 12120 | return sema.fail(block, rhs_src, "operation results in overflow", .{}); |
| 12118 | 12121 | |
| ... | ... | @@ -12126,18 +12129,19 @@ fn analyzeTupleMul( |
| 12126 | 12129 | |
| 12127 | 12130 | const opt_runtime_src = rs: { |
| 12128 | 12131 | var runtime_src: ?LazySrcLoc = null; |
| 12129 | | for (operand_tuple.types) |ty, i| { |
| 12130 | | types[i] = ty; |
| 12131 | | values[i] = operand_tuple.values[i]; |
| 12132 | var i: u32 = 0; |
| 12133 | while (i < tuple_len) : (i += 1) { |
| 12134 | types[i] = operand_ty.structFieldType(i); |
| 12135 | values[i] = operand_ty.structFieldDefaultValue(i); |
| 12132 | 12136 | const operand_src = lhs_src; // TODO better source location |
| 12133 | 12137 | if (values[i].tag() == .unreachable_value) { |
| 12134 | 12138 | runtime_src = operand_src; |
| 12135 | 12139 | } |
| 12136 | 12140 | } |
| 12137 | | var i: usize = 1; |
| 12141 | i = 0; |
| 12138 | 12142 | while (i < factor) : (i += 1) { |
| 12139 | | mem.copy(Type, types[tuple_len * i ..], operand_tuple.types); |
| 12140 | | mem.copy(Value, values[tuple_len * i ..], operand_tuple.values); |
| 12143 | mem.copy(Type, types[tuple_len * i ..], types[0..tuple_len]); |
| 12144 | mem.copy(Value, values[tuple_len * i ..], values[0..tuple_len]); |
| 12141 | 12145 | } |
| 12142 | 12146 | break :rs runtime_src; |
| 12143 | 12147 | }; |
| ... | ... | @@ -12155,11 +12159,12 @@ fn analyzeTupleMul( |
| 12155 | 12159 | try sema.requireRuntimeBlock(block, src, runtime_src); |
| 12156 | 12160 | |
| 12157 | 12161 | const element_refs = try sema.arena.alloc(Air.Inst.Ref, final_len); |
| 12158 | | for (operand_tuple.types) |_, i| { |
| 12162 | var i: u32 = 0; |
| 12163 | while (i < tuple_len) : (i += 1) { |
| 12159 | 12164 | const operand_src = lhs_src; // TODO better source location |
| 12160 | 12165 | element_refs[i] = try sema.tupleFieldValByIndex(block, operand_src, operand, @intCast(u32, i), operand_ty); |
| 12161 | 12166 | } |
| 12162 | | var i: usize = 1; |
| 12167 | i = 1; |
| 12163 | 12168 | while (i < factor) : (i += 1) { |
| 12164 | 12169 | mem.copy(Air.Inst.Ref, element_refs[tuple_len * i ..], element_refs[0..tuple_len]); |
| 12165 | 12170 | } |
| ... | ... | @@ -15593,7 +15598,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 15593 | 15598 | const layout = struct_ty.containerLayout(); |
| 15594 | 15599 | |
| 15595 | 15600 | const struct_field_vals = fv: { |
| 15596 | | if (struct_ty.isTupleOrAnonStruct()) { |
| 15601 | if (struct_ty.isSimpleTupleOrAnonStruct()) { |
| 15597 | 15602 | const tuple = struct_ty.tupleFields(); |
| 15598 | 15603 | const field_types = tuple.types; |
| 15599 | 15604 | const struct_field_vals = try fields_anon_decl.arena().alloc(Value, field_types.len); |
| ... | ... | @@ -17063,10 +17068,12 @@ fn finishStructInit( |
| 17063 | 17068 | } |
| 17064 | 17069 | } |
| 17065 | 17070 | } else if (struct_ty.isTuple()) { |
| 17066 | | const struct_obj = struct_ty.castTag(.tuple).?.data; |
| 17067 | | for (struct_obj.values) |default_val, i| { |
| 17071 | var i: u32 = 0; |
| 17072 | const len = struct_ty.structFieldCount(); |
| 17073 | while (i < len) : (i += 1) { |
| 17068 | 17074 | if (field_inits[i] != .none) continue; |
| 17069 | 17075 | |
| 17076 | const default_val = struct_ty.structFieldDefaultValue(i); |
| 17070 | 17077 | if (default_val.tag() == .unreachable_value) { |
| 17071 | 17078 | const template = "missing tuple field with index {d}"; |
| 17072 | 17079 | if (root_msg) |msg| { |
| ... | ... | @@ -17075,7 +17082,7 @@ fn finishStructInit( |
| 17075 | 17082 | root_msg = try sema.errMsg(block, init_src, template, .{i}); |
| 17076 | 17083 | } |
| 17077 | 17084 | } else { |
| 17078 | | field_inits[i] = try sema.addConstant(struct_obj.types[i], default_val); |
| 17085 | field_inits[i] = try sema.addConstant(struct_ty.structFieldType(i), default_val); |
| 17079 | 17086 | } |
| 17080 | 17087 | } |
| 17081 | 17088 | } else { |
| ... | ... | @@ -17297,7 +17304,7 @@ fn zirArrayInit( |
| 17297 | 17304 | const resolved_arg = try sema.resolveInst(arg); |
| 17298 | 17305 | const arg_src = src; // TODO better source location |
| 17299 | 17306 | const elem_ty = if (array_ty.zigTypeTag() == .Struct) |
| 17300 | | array_ty.tupleFields().types[i] |
| 17307 | array_ty.structFieldType(i) |
| 17301 | 17308 | else |
| 17302 | 17309 | array_ty.elemType2(); |
| 17303 | 17310 | resolved_args[i] = try sema.coerce(block, elem_ty, resolved_arg, arg_src); |
| ... | ... | @@ -17337,12 +17344,11 @@ fn zirArrayInit( |
| 17337 | 17344 | const alloc = try block.addTy(.alloc, alloc_ty); |
| 17338 | 17345 | |
| 17339 | 17346 | if (array_ty.isTuple()) { |
| 17340 | | const types = array_ty.tupleFields().types; |
| 17341 | 17347 | for (resolved_args) |arg, i| { |
| 17342 | 17348 | const elem_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{ |
| 17343 | 17349 | .mutable = true, |
| 17344 | 17350 | .@"addrspace" = target_util.defaultAddressSpace(target, .local), |
| 17345 | | .pointee_type = types[i], |
| 17351 | .pointee_type = array_ty.structFieldType(i), |
| 17346 | 17352 | }); |
| 17347 | 17353 | const elem_ptr_ty_ref = try sema.addType(elem_ptr_ty); |
| 17348 | 17354 | |
| ... | ... | @@ -18015,10 +18021,7 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in |
| 18015 | 18021 | return sema.fail(block, src, "non-packed struct does not support backing integer type", .{}); |
| 18016 | 18022 | } |
| 18017 | 18023 | |
| 18018 | | return if (is_tuple_val.toBool()) |
| 18019 | | try sema.reifyTuple(block, src, fields_val) |
| 18020 | | else |
| 18021 | | try sema.reifyStruct(block, inst, src, layout, backing_int_val, fields_val, name_strategy); |
| 18024 | return try sema.reifyStruct(block, inst, src, layout, backing_int_val, fields_val, name_strategy, is_tuple_val.toBool()); |
| 18022 | 18025 | }, |
| 18023 | 18026 | .Enum => { |
| 18024 | 18027 | const struct_val: []const Value = union_val.val.castTag(.aggregate).?.data; |
| ... | ... | @@ -18432,84 +18435,6 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in |
| 18432 | 18435 | } |
| 18433 | 18436 | } |
| 18434 | 18437 | |
| 18435 | | fn reifyTuple( |
| 18436 | | sema: *Sema, |
| 18437 | | block: *Block, |
| 18438 | | src: LazySrcLoc, |
| 18439 | | fields_val: Value, |
| 18440 | | ) CompileError!Air.Inst.Ref { |
| 18441 | | const fields_len = try sema.usizeCast(block, src, fields_val.sliceLen(sema.mod)); |
| 18442 | | if (fields_len == 0) return sema.addType(Type.initTag(.empty_struct_literal)); |
| 18443 | | |
| 18444 | | const types = try sema.arena.alloc(Type, fields_len); |
| 18445 | | const values = try sema.arena.alloc(Value, fields_len); |
| 18446 | | |
| 18447 | | var used_fields: std.AutoArrayHashMapUnmanaged(u32, void) = .{}; |
| 18448 | | defer used_fields.deinit(sema.gpa); |
| 18449 | | try used_fields.ensureTotalCapacity(sema.gpa, fields_len); |
| 18450 | | |
| 18451 | | var i: usize = 0; |
| 18452 | | while (i < fields_len) : (i += 1) { |
| 18453 | | const elem_val = try fields_val.elemValue(sema.mod, sema.arena, i); |
| 18454 | | const field_struct_val = elem_val.castTag(.aggregate).?.data; |
| 18455 | | // TODO use reflection instead of magic numbers here |
| 18456 | | // name: []const u8 |
| 18457 | | const name_val = field_struct_val[0]; |
| 18458 | | // field_type: type, |
| 18459 | | const field_type_val = field_struct_val[1]; |
| 18460 | | //default_value: ?*const anyopaque, |
| 18461 | | const default_value_val = field_struct_val[2]; |
| 18462 | | |
| 18463 | | const field_name = try name_val.toAllocatedBytes( |
| 18464 | | Type.initTag(.const_slice_u8), |
| 18465 | | sema.arena, |
| 18466 | | sema.mod, |
| 18467 | | ); |
| 18468 | | |
| 18469 | | const field_index = std.fmt.parseUnsigned(u32, field_name, 10) catch |err| { |
| 18470 | | return sema.fail( |
| 18471 | | block, |
| 18472 | | src, |
| 18473 | | "tuple cannot have non-numeric field '{s}': {}", |
| 18474 | | .{ field_name, err }, |
| 18475 | | ); |
| 18476 | | }; |
| 18477 | | |
| 18478 | | if (field_index >= fields_len) { |
| 18479 | | return sema.fail( |
| 18480 | | block, |
| 18481 | | src, |
| 18482 | | "tuple field {} exceeds tuple field count", |
| 18483 | | .{field_index}, |
| 18484 | | ); |
| 18485 | | } |
| 18486 | | |
| 18487 | | const gop = used_fields.getOrPutAssumeCapacity(field_index); |
| 18488 | | if (gop.found_existing) { |
| 18489 | | // TODO: better source location |
| 18490 | | return sema.fail(block, src, "duplicate tuple field {}", .{field_index}); |
| 18491 | | } |
| 18492 | | |
| 18493 | | const default_val = if (default_value_val.optionalValue()) |opt_val| blk: { |
| 18494 | | const payload_val = if (opt_val.pointerDecl()) |opt_decl| |
| 18495 | | sema.mod.declPtr(opt_decl).val |
| 18496 | | else |
| 18497 | | opt_val; |
| 18498 | | break :blk try payload_val.copy(sema.arena); |
| 18499 | | } else Value.initTag(.unreachable_value); |
| 18500 | | |
| 18501 | | var buffer: Value.ToTypeBuffer = undefined; |
| 18502 | | types[field_index] = try field_type_val.toType(&buffer).copy(sema.arena); |
| 18503 | | values[field_index] = default_val; |
| 18504 | | } |
| 18505 | | |
| 18506 | | const ty = try Type.Tag.tuple.create(sema.arena, .{ |
| 18507 | | .types = types, |
| 18508 | | .values = values, |
| 18509 | | }); |
| 18510 | | return sema.addType(ty); |
| 18511 | | } |
| 18512 | | |
| 18513 | 18438 | fn reifyStruct( |
| 18514 | 18439 | sema: *Sema, |
| 18515 | 18440 | block: *Block, |
| ... | ... | @@ -18519,6 +18444,7 @@ fn reifyStruct( |
| 18519 | 18444 | backing_int_val: Value, |
| 18520 | 18445 | fields_val: Value, |
| 18521 | 18446 | name_strategy: Zir.Inst.NameStrategy, |
| 18447 | is_tuple: bool, |
| 18522 | 18448 | ) CompileError!Air.Inst.Ref { |
| 18523 | 18449 | var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa); |
| 18524 | 18450 | errdefer new_decl_arena.deinit(); |
| ... | ... | @@ -18542,6 +18468,7 @@ fn reifyStruct( |
| 18542 | 18468 | .layout = layout, |
| 18543 | 18469 | .status = .have_field_types, |
| 18544 | 18470 | .known_non_opv = false, |
| 18471 | .is_tuple = is_tuple, |
| 18545 | 18472 | .namespace = .{ |
| 18546 | 18473 | .parent = block.namespace, |
| 18547 | 18474 | .ty = struct_ty, |
| ... | ... | @@ -23201,6 +23128,7 @@ fn structFieldVal( |
| 23201 | 23128 | }, |
| 23202 | 23129 | .@"struct" => { |
| 23203 | 23130 | const struct_obj = struct_ty.castTag(.@"struct").?.data; |
| 23131 | if (struct_obj.is_tuple) return sema.tupleFieldVal(block, src, struct_byval, field_name, field_name_src, struct_ty); |
| 23204 | 23132 | |
| 23205 | 23133 | const field_index_usize = struct_obj.fields.getIndex(field_name) orelse |
| 23206 | 23134 | return sema.failWithBadStructFieldAccess(block, struct_obj, field_name_src, field_name); |
| ... | ... | @@ -23273,11 +23201,10 @@ fn tupleFieldValByIndex( |
| 23273 | 23201 | field_index: u32, |
| 23274 | 23202 | tuple_ty: Type, |
| 23275 | 23203 | ) CompileError!Air.Inst.Ref { |
| 23276 | | const tuple = tuple_ty.tupleFields(); |
| 23277 | | const field_ty = tuple.types[field_index]; |
| 23204 | const field_ty = tuple_ty.structFieldType(field_index); |
| 23278 | 23205 | |
| 23279 | | if (tuple.values[field_index].tag() != .unreachable_value) { |
| 23280 | | return sema.addConstant(field_ty, tuple.values[field_index]); |
| 23206 | if (tuple_ty.structFieldValueComptime(field_index)) |default_value| { |
| 23207 | return sema.addConstant(field_ty, default_value); |
| 23281 | 23208 | } |
| 23282 | 23209 | |
| 23283 | 23210 | if (try sema.resolveMaybeUndefVal(tuple_byval)) |tuple_val| { |
| ... | ... | @@ -23625,19 +23552,20 @@ fn tupleFieldPtr( |
| 23625 | 23552 | ) CompileError!Air.Inst.Ref { |
| 23626 | 23553 | const tuple_ptr_ty = sema.typeOf(tuple_ptr); |
| 23627 | 23554 | const tuple_ty = tuple_ptr_ty.childType(); |
| 23628 | | const tuple_fields = tuple_ty.tupleFields(); |
| 23555 | _ = try sema.resolveTypeFields(tuple_ty); |
| 23556 | const field_count = tuple_ty.structFieldCount(); |
| 23629 | 23557 | |
| 23630 | | if (tuple_fields.types.len == 0) { |
| 23558 | if (field_count == 0) { |
| 23631 | 23559 | return sema.fail(block, tuple_ptr_src, "indexing into empty tuple is not allowed", .{}); |
| 23632 | 23560 | } |
| 23633 | 23561 | |
| 23634 | | if (field_index >= tuple_fields.types.len) { |
| 23562 | if (field_index >= field_count) { |
| 23635 | 23563 | return sema.fail(block, field_index_src, "index {d} outside tuple of length {d}", .{ |
| 23636 | | field_index, tuple_fields.types.len, |
| 23564 | field_index, field_count, |
| 23637 | 23565 | }); |
| 23638 | 23566 | } |
| 23639 | 23567 | |
| 23640 | | const field_ty = tuple_fields.types[field_index]; |
| 23568 | const field_ty = tuple_ty.structFieldType(field_index); |
| 23641 | 23569 | const ptr_field_ty = try Type.ptr(sema.arena, sema.mod, .{ |
| 23642 | 23570 | .pointee_type = field_ty, |
| 23643 | 23571 | .mutable = tuple_ptr_ty.ptrIsMutable(), |
| ... | ... | @@ -23680,24 +23608,23 @@ fn tupleField( |
| 23680 | 23608 | field_index_src: LazySrcLoc, |
| 23681 | 23609 | field_index: u32, |
| 23682 | 23610 | ) CompileError!Air.Inst.Ref { |
| 23683 | | const tuple_ty = sema.typeOf(tuple); |
| 23684 | | const tuple_fields = tuple_ty.tupleFields(); |
| 23611 | const tuple_ty = try sema.resolveTypeFields(sema.typeOf(tuple)); |
| 23612 | const field_count = tuple_ty.structFieldCount(); |
| 23685 | 23613 | |
| 23686 | | if (tuple_fields.types.len == 0) { |
| 23614 | if (field_count == 0) { |
| 23687 | 23615 | return sema.fail(block, tuple_src, "indexing into empty tuple is not allowed", .{}); |
| 23688 | 23616 | } |
| 23689 | 23617 | |
| 23690 | | if (field_index >= tuple_fields.types.len) { |
| 23618 | if (field_index >= field_count) { |
| 23691 | 23619 | return sema.fail(block, field_index_src, "index {d} outside tuple of length {d}", .{ |
| 23692 | | field_index, tuple_fields.types.len, |
| 23620 | field_index, field_count, |
| 23693 | 23621 | }); |
| 23694 | 23622 | } |
| 23695 | 23623 | |
| 23696 | | const field_ty = tuple_fields.types[field_index]; |
| 23697 | | const field_val = tuple_fields.values[field_index]; |
| 23624 | const field_ty = tuple_ty.structFieldType(field_index); |
| 23698 | 23625 | |
| 23699 | | if (field_val.tag() != .unreachable_value) { |
| 23700 | | return sema.addConstant(field_ty, field_val); // comptime field |
| 23626 | if (tuple_ty.structFieldValueComptime(field_index)) |default_value| { |
| 23627 | return sema.addConstant(field_ty, default_value); // comptime field |
| 23701 | 23628 | } |
| 23702 | 23629 | |
| 23703 | 23630 | if (try sema.resolveMaybeUndefVal(tuple)) |tuple_val| { |
| ... | ... | @@ -24277,7 +24204,7 @@ fn coerceExtra( |
| 24277 | 24204 | |
| 24278 | 24205 | // empty tuple to zero-length slice |
| 24279 | 24206 | // note that this allows coercing to a mutable slice. |
| 24280 | | if (inst_child_ty.tupleFields().types.len == 0) { |
| 24207 | if (inst_child_ty.structFieldCount() == 0) { |
| 24281 | 24208 | const slice_val = try Value.Tag.slice.create(sema.arena, .{ |
| 24282 | 24209 | .ptr = Value.undef, |
| 24283 | 24210 | .len = Value.zero, |
| ... | ... | @@ -25587,9 +25514,9 @@ fn storePtr2( |
| 25587 | 25514 | // fields. |
| 25588 | 25515 | const operand_ty = sema.typeOf(uncasted_operand); |
| 25589 | 25516 | if (operand_ty.isTuple() and elem_ty.zigTypeTag() == .Array) { |
| 25590 | | const tuple = operand_ty.tupleFields(); |
| 25591 | | for (tuple.types) |_, i_usize| { |
| 25592 | | const i = @intCast(u32, i_usize); |
| 25517 | const field_count = operand_ty.structFieldCount(); |
| 25518 | var i: u32 = 0; |
| 25519 | while (i < field_count) : (i += 1) { |
| 25593 | 25520 | const elem_src = operand_src; // TODO better source location |
| 25594 | 25521 | const elem = try sema.tupleField(block, operand_src, uncasted_operand, elem_src, i); |
| 25595 | 25522 | const elem_index = try sema.addIntUnsigned(Type.usize, i); |
| ... | ... | @@ -26681,7 +26608,7 @@ fn checkPtrAttributes(sema: *Sema, dest_ty: Type, inst_ty: Type, in_memory_resul |
| 26681 | 26608 | const inst_info = inst_ty.ptrInfo().data; |
| 26682 | 26609 | const len0 = (inst_info.pointee_type.zigTypeTag() == .Array and (inst_info.pointee_type.arrayLenIncludingSentinel() == 0 or |
| 26683 | 26610 | (inst_info.pointee_type.arrayLen() == 0 and dest_info.sentinel == null and dest_info.size != .C and dest_info.size != .Many))) or |
| 26684 | | (inst_info.pointee_type.isTuple() and inst_info.pointee_type.tupleFields().types.len == 0); |
| 26611 | (inst_info.pointee_type.isTuple() and inst_info.pointee_type.structFieldCount() == 0); |
| 26685 | 26612 | |
| 26686 | 26613 | const ok_cv_qualifiers = |
| 26687 | 26614 | ((inst_info.mutable or !dest_info.mutable) or len0) and |
| ... | ... | @@ -27166,18 +27093,18 @@ fn coerceTupleToStruct( |
| 27166 | 27093 | mem.set(Air.Inst.Ref, field_refs, .none); |
| 27167 | 27094 | |
| 27168 | 27095 | const inst_ty = sema.typeOf(inst); |
| 27169 | | const tuple = inst_ty.tupleFields(); |
| 27170 | 27096 | var runtime_src: ?LazySrcLoc = null; |
| 27171 | | for (tuple.types) |_, i_usize| { |
| 27172 | | const i = @intCast(u32, i_usize); |
| 27097 | const field_count = struct_ty.structFieldCount(); |
| 27098 | var field_i: u32 = 0; |
| 27099 | while (field_i < field_count) : (field_i += 1) { |
| 27173 | 27100 | const field_src = inst_src; // TODO better source location |
| 27174 | 27101 | const field_name = if (inst_ty.castTag(.anon_struct)) |payload| |
| 27175 | | payload.data.names[i] |
| 27102 | payload.data.names[field_i] |
| 27176 | 27103 | else |
| 27177 | | try std.fmt.allocPrint(sema.arena, "{d}", .{i}); |
| 27104 | try std.fmt.allocPrint(sema.arena, "{d}", .{field_i}); |
| 27178 | 27105 | const field_index = try sema.structFieldIndex(block, struct_ty, field_name, field_src); |
| 27179 | 27106 | const field = fields.values()[field_index]; |
| 27180 | | const elem_ref = try sema.tupleField(block, inst_src, inst, field_src, i); |
| 27107 | const elem_ref = try sema.tupleField(block, inst_src, inst, field_src, field_i); |
| 27181 | 27108 | const coerced = try sema.coerce(block, field.ty, elem_ref, field_src); |
| 27182 | 27109 | field_refs[field_index] = coerced; |
| 27183 | 27110 | if (field.is_comptime) { |
| ... | ... | @@ -27186,7 +27113,7 @@ fn coerceTupleToStruct( |
| 27186 | 27113 | }; |
| 27187 | 27114 | |
| 27188 | 27115 | if (!init_val.eql(field.default_val, field.ty, sema.mod)) { |
| 27189 | | return sema.failWithInvalidComptimeFieldStore(block, field_src, inst_ty, i); |
| 27116 | return sema.failWithInvalidComptimeFieldStore(block, field_src, inst_ty, field_i); |
| 27190 | 27117 | } |
| 27191 | 27118 | } |
| 27192 | 27119 | if (runtime_src == null) { |
| ... | ... | @@ -27255,15 +27182,14 @@ fn coerceTupleToTuple( |
| 27255 | 27182 | mem.set(Air.Inst.Ref, field_refs, .none); |
| 27256 | 27183 | |
| 27257 | 27184 | const inst_ty = sema.typeOf(inst); |
| 27258 | | const tuple = inst_ty.tupleFields(); |
| 27259 | 27185 | var runtime_src: ?LazySrcLoc = null; |
| 27260 | | for (tuple.types) |_, i_usize| { |
| 27261 | | const i = @intCast(u32, i_usize); |
| 27186 | var field_i: u32 = 0; |
| 27187 | while (field_i < field_count) : (field_i += 1) { |
| 27262 | 27188 | const field_src = inst_src; // TODO better source location |
| 27263 | 27189 | const field_name = if (inst_ty.castTag(.anon_struct)) |payload| |
| 27264 | | payload.data.names[i] |
| 27190 | payload.data.names[field_i] |
| 27265 | 27191 | else |
| 27266 | | try std.fmt.allocPrint(sema.arena, "{d}", .{i}); |
| 27192 | try std.fmt.allocPrint(sema.arena, "{d}", .{field_i}); |
| 27267 | 27193 | |
| 27268 | 27194 | if (mem.eql(u8, field_name, "len")) { |
| 27269 | 27195 | return sema.fail(block, field_src, "cannot assign to 'len' field of tuple", .{}); |
| ... | ... | @@ -27271,9 +27197,9 @@ fn coerceTupleToTuple( |
| 27271 | 27197 | |
| 27272 | 27198 | const field_index = try sema.tupleFieldIndex(block, tuple_ty, field_name, field_src); |
| 27273 | 27199 | |
| 27274 | | const field_ty = tuple_ty.structFieldType(i); |
| 27275 | | const default_val = tuple_ty.structFieldDefaultValue(i); |
| 27276 | | const elem_ref = try sema.tupleField(block, inst_src, inst, field_src, i); |
| 27200 | const field_ty = tuple_ty.structFieldType(field_i); |
| 27201 | const default_val = tuple_ty.structFieldDefaultValue(field_i); |
| 27202 | const elem_ref = try sema.tupleField(block, inst_src, inst, field_src, field_i); |
| 27277 | 27203 | const coerced = try sema.coerce(block, field_ty, elem_ref, field_src); |
| 27278 | 27204 | field_refs[field_index] = coerced; |
| 27279 | 27205 | if (default_val.tag() != .unreachable_value) { |
| ... | ... | @@ -27282,7 +27208,7 @@ fn coerceTupleToTuple( |
| 27282 | 27208 | }; |
| 27283 | 27209 | |
| 27284 | 27210 | if (!init_val.eql(default_val, field_ty, sema.mod)) { |
| 27285 | | return sema.failWithInvalidComptimeFieldStore(block, field_src, inst_ty, i); |
| 27211 | return sema.failWithInvalidComptimeFieldStore(block, field_src, inst_ty, field_i); |
| 27286 | 27212 | } |
| 27287 | 27213 | } |
| 27288 | 27214 | if (runtime_src == null) { |
| ... | ... | @@ -29665,6 +29591,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void |
| 29665 | 29591 | block_scope.params.deinit(gpa); |
| 29666 | 29592 | } |
| 29667 | 29593 | |
| 29594 | struct_obj.fields = .{}; |
| 29668 | 29595 | try struct_obj.fields.ensureTotalCapacity(decl_arena_allocator, fields_len); |
| 29669 | 29596 | |
| 29670 | 29597 | const Field = struct { |
| ... | ... | @@ -29699,8 +29626,11 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void |
| 29699 | 29626 | const has_type_body = @truncate(u1, cur_bit_bag) != 0; |
| 29700 | 29627 | cur_bit_bag >>= 1; |
| 29701 | 29628 | |
| 29702 | | const field_name_zir = zir.nullTerminatedString(zir.extra[extra_index]); |
| 29703 | | extra_index += 1; |
| 29629 | var field_name_zir: ?[:0]const u8 = null; |
| 29630 | if (!small.is_tuple) { |
| 29631 | field_name_zir = zir.nullTerminatedString(zir.extra[extra_index]); |
| 29632 | extra_index += 1; |
| 29633 | } |
| 29704 | 29634 | extra_index += 1; // doc_comment |
| 29705 | 29635 | |
| 29706 | 29636 | fields[field_i] = .{}; |
| ... | ... | @@ -29713,7 +29643,10 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void |
| 29713 | 29643 | extra_index += 1; |
| 29714 | 29644 | |
| 29715 | 29645 | // This string needs to outlive the ZIR code. |
| 29716 | | const field_name = try decl_arena_allocator.dupe(u8, field_name_zir); |
| 29646 | const field_name = if (field_name_zir) |some| |
| 29647 | try decl_arena_allocator.dupe(u8, some) |
| 29648 | else |
| 29649 | try std.fmt.allocPrint(decl_arena_allocator, "{d}", .{field_i}); |
| 29717 | 29650 | |
| 29718 | 29651 | const gop = struct_obj.fields.getOrPutAssumeCapacity(field_name); |
| 29719 | 29652 | if (gop.found_existing) { |