| ... | ... | @@ -5027,6 +5027,7 @@ fn finishGenericCall( |
| 5027 | 5027 | try sema.requireRuntimeBlock(block, call_src); |
| 5028 | 5028 | |
| 5029 | 5029 | const comptime_args = callee.comptime_args.?; |
| 5030 | const new_fn_info = callee.owner_decl.ty.fnInfo(); |
| 5030 | 5031 | const runtime_args_len = count: { |
| 5031 | 5032 | var count: u32 = 0; |
| 5032 | 5033 | var arg_i: usize = 0; |
| ... | ... | @@ -5045,7 +5046,6 @@ fn finishGenericCall( |
| 5045 | 5046 | }; |
| 5046 | 5047 | const runtime_args = try sema.arena.alloc(Air.Inst.Ref, runtime_args_len); |
| 5047 | 5048 | { |
| 5048 | | const new_fn_ty = callee.owner_decl.ty; |
| 5049 | 5049 | var runtime_i: u32 = 0; |
| 5050 | 5050 | var total_i: u32 = 0; |
| 5051 | 5051 | for (fn_info.param_body) |inst| { |
| ... | ... | @@ -5055,7 +5055,7 @@ fn finishGenericCall( |
| 5055 | 5055 | } |
| 5056 | 5056 | const is_runtime = comptime_args[total_i].val.tag() == .generic_poison; |
| 5057 | 5057 | if (is_runtime) { |
| 5058 | | const param_ty = new_fn_ty.fnParamType(runtime_i); |
| 5058 | const param_ty = new_fn_info.param_types[runtime_i]; |
| 5059 | 5059 | const arg_src = call_src; // TODO: better source location |
| 5060 | 5060 | const uncasted_arg = uncasted_args[total_i]; |
| 5061 | 5061 | try sema.resolveTypeFully(block, arg_src, param_ty); |
| ... | ... | @@ -5066,7 +5066,7 @@ fn finishGenericCall( |
| 5066 | 5066 | total_i += 1; |
| 5067 | 5067 | } |
| 5068 | 5068 | |
| 5069 | | try sema.resolveTypeFully(block, call_src, new_fn_ty.fnReturnType()); |
| 5069 | try sema.resolveTypeFully(block, call_src, new_fn_info.return_type); |
| 5070 | 5070 | } |
| 5071 | 5071 | try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.Call).Struct.fields.len + |
| 5072 | 5072 | runtime_args_len); |
| ... | ... | @@ -15222,6 +15222,19 @@ fn structFieldPtr( |
| 15222 | 15222 | |
| 15223 | 15223 | const struct_ty = try sema.resolveTypeFields(block, src, unresolved_struct_ty); |
| 15224 | 15224 | try sema.resolveStructLayout(block, src, struct_ty); |
| 15225 | |
| 15226 | if (struct_ty.isTuple()) { |
| 15227 | if (mem.eql(u8, field_name, "len")) { |
| 15228 | const len_inst = try sema.addIntUnsigned(Type.usize, struct_ty.structFieldCount()); |
| 15229 | return sema.analyzeRef(block, src, len_inst); |
| 15230 | } |
| 15231 | const field_index = try sema.tupleFieldIndex(block, struct_ty, field_name, field_name_src); |
| 15232 | return sema.tupleFieldPtr(block, struct_ptr, field_index, src, field_name_src); |
| 15233 | } else if (struct_ty.isAnonStruct()) { |
| 15234 | const field_index = try sema.anonStructFieldIndex(block, struct_ty, field_name, field_name_src); |
| 15235 | return sema.tupleFieldPtr(block, struct_ptr, field_index, src, field_name_src); |
| 15236 | } |
| 15237 | |
| 15225 | 15238 | const struct_obj = struct_ty.castTag(.@"struct").?.data; |
| 15226 | 15239 | |
| 15227 | 15240 | const field_index_big = struct_obj.fields.getIndex(field_name) orelse |
| ... | ... | @@ -15324,15 +15337,7 @@ fn structFieldVal( |
| 15324 | 15337 | switch (struct_ty.tag()) { |
| 15325 | 15338 | .tuple, .empty_struct_literal => return sema.tupleFieldVal(block, src, struct_byval, field_name, field_name_src, struct_ty), |
| 15326 | 15339 | .anon_struct => { |
| 15327 | | const anon_struct = struct_ty.castTag(.anon_struct).?.data; |
| 15328 | | |
| 15329 | | const field_index = for (anon_struct.names) |name, i| { |
| 15330 | | if (mem.eql(u8, name, field_name)) break @intCast(u32, i); |
| 15331 | | } else { |
| 15332 | | return sema.fail(block, field_name_src, "anonymous struct {} has no such field '{s}'", .{ |
| 15333 | | struct_ty, field_name, |
| 15334 | | }); |
| 15335 | | }; |
| 15340 | const field_index = try sema.anonStructFieldIndex(block, struct_ty, field_name, field_name_src); |
| 15336 | 15341 | return tupleFieldValByIndex(sema, block, src, struct_byval, field_index, struct_ty); |
| 15337 | 15342 | }, |
| 15338 | 15343 | .@"struct" => { |
| ... | ... | @@ -15376,7 +15381,18 @@ fn tupleFieldVal( |
| 15376 | 15381 | if (mem.eql(u8, field_name, "len")) { |
| 15377 | 15382 | return sema.addIntUnsigned(Type.usize, tuple_ty.structFieldCount()); |
| 15378 | 15383 | } |
| 15384 | const field_index = try sema.tupleFieldIndex(block, tuple_ty, field_name, field_name_src); |
| 15385 | return tupleFieldValByIndex(sema, block, src, tuple_byval, field_index, tuple_ty); |
| 15386 | } |
| 15379 | 15387 | |
| 15388 | /// Don't forget to check for "len" before calling this. |
| 15389 | fn tupleFieldIndex( |
| 15390 | sema: *Sema, |
| 15391 | block: *Block, |
| 15392 | tuple_ty: Type, |
| 15393 | field_name: []const u8, |
| 15394 | field_name_src: LazySrcLoc, |
| 15395 | ) CompileError!u32 { |
| 15380 | 15396 | const field_index = std.fmt.parseUnsigned(u32, field_name, 10) catch |err| { |
| 15381 | 15397 | return sema.fail(block, field_name_src, "tuple {} has no such field '{s}': {s}", .{ |
| 15382 | 15398 | tuple_ty, field_name, @errorName(err), |
| ... | ... | @@ -15387,7 +15403,7 @@ fn tupleFieldVal( |
| 15387 | 15403 | tuple_ty, field_name, |
| 15388 | 15404 | }); |
| 15389 | 15405 | } |
| 15390 | | return tupleFieldValByIndex(sema, block, src, tuple_byval, field_index, tuple_ty); |
| 15406 | return field_index; |
| 15391 | 15407 | } |
| 15392 | 15408 | |
| 15393 | 15409 | fn tupleFieldValByIndex( |
| ... | ... | @@ -15685,15 +15701,15 @@ fn tupleFieldPtr( |
| 15685 | 15701 | ) CompileError!Air.Inst.Ref { |
| 15686 | 15702 | const tuple_ptr_ty = sema.typeOf(tuple_ptr); |
| 15687 | 15703 | const tuple_ty = tuple_ptr_ty.childType(); |
| 15688 | | const tuple_info = tuple_ty.castTag(.tuple).?.data; |
| 15704 | const tuple = tuple_ty.tupleFields(); |
| 15689 | 15705 | |
| 15690 | | if (field_index > tuple_info.types.len) { |
| 15706 | if (field_index > tuple.types.len) { |
| 15691 | 15707 | return sema.fail(block, field_index_src, "index {d} outside tuple of length {d}", .{ |
| 15692 | | field_index, tuple_info.types.len, |
| 15708 | field_index, tuple.types.len, |
| 15693 | 15709 | }); |
| 15694 | 15710 | } |
| 15695 | 15711 | |
| 15696 | | const field_ty = tuple_info.types[field_index]; |
| 15712 | const field_ty = tuple.types[field_index]; |
| 15697 | 15713 | const target = sema.mod.getTarget(); |
| 15698 | 15714 | const ptr_field_ty = try Type.ptr(sema.arena, target, .{ |
| 15699 | 15715 | .pointee_type = field_ty, |
| ... | ... | @@ -20470,3 +20486,21 @@ fn structFieldIndex( |
| 20470 | 20486 | return sema.failWithBadStructFieldAccess(block, struct_obj, field_src, field_name); |
| 20471 | 20487 | return @intCast(u32, field_index_usize); |
| 20472 | 20488 | } |
| 20489 | |
| 20490 | fn anonStructFieldIndex( |
| 20491 | sema: *Sema, |
| 20492 | block: *Block, |
| 20493 | struct_ty: Type, |
| 20494 | field_name: []const u8, |
| 20495 | field_src: LazySrcLoc, |
| 20496 | ) !u32 { |
| 20497 | const anon_struct = struct_ty.castTag(.anon_struct).?.data; |
| 20498 | for (anon_struct.names) |name, i| { |
| 20499 | if (mem.eql(u8, name, field_name)) { |
| 20500 | return @intCast(u32, i); |
| 20501 | } |
| 20502 | } |
| 20503 | return sema.fail(block, field_src, "anonymous struct {} has no such field '{s}'", .{ |
| 20504 | struct_ty, field_name, |
| 20505 | }); |
| 20506 | } |