| ... | @@ -5027,6 +5027,7 @@ fn finishGenericCall( | ... | @@ -5027,6 +5027,7 @@ fn finishGenericCall( |
| 5027 | try sema.requireRuntimeBlock(block, call_src); | 5027 | try sema.requireRuntimeBlock(block, call_src); |
| 5028 | | 5028 | |
| 5029 | const comptime_args = callee.comptime_args.?; | 5029 | const comptime_args = callee.comptime_args.?; |
| | 5030 | const new_fn_info = callee.owner_decl.ty.fnInfo(); |
| 5030 | const runtime_args_len = count: { | 5031 | const runtime_args_len = count: { |
| 5031 | var count: u32 = 0; | 5032 | var count: u32 = 0; |
| 5032 | var arg_i: usize = 0; | 5033 | var arg_i: usize = 0; |
| ... | @@ -5045,7 +5046,6 @@ fn finishGenericCall( | ... | @@ -5045,7 +5046,6 @@ fn finishGenericCall( |
| 5045 | }; | 5046 | }; |
| 5046 | const runtime_args = try sema.arena.alloc(Air.Inst.Ref, runtime_args_len); | 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 | var runtime_i: u32 = 0; | 5049 | var runtime_i: u32 = 0; |
| 5050 | var total_i: u32 = 0; | 5050 | var total_i: u32 = 0; |
| 5051 | for (fn_info.param_body) |inst| { | 5051 | for (fn_info.param_body) |inst| { |
| ... | @@ -5055,7 +5055,7 @@ fn finishGenericCall( | ... | @@ -5055,7 +5055,7 @@ fn finishGenericCall( |
| 5055 | } | 5055 | } |
| 5056 | const is_runtime = comptime_args[total_i].val.tag() == .generic_poison; | 5056 | const is_runtime = comptime_args[total_i].val.tag() == .generic_poison; |
| 5057 | if (is_runtime) { | 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 | const arg_src = call_src; // TODO: better source location | 5059 | const arg_src = call_src; // TODO: better source location |
| 5060 | const uncasted_arg = uncasted_args[total_i]; | 5060 | const uncasted_arg = uncasted_args[total_i]; |
| 5061 | try sema.resolveTypeFully(block, arg_src, param_ty); | 5061 | try sema.resolveTypeFully(block, arg_src, param_ty); |
| ... | @@ -5066,7 +5066,7 @@ fn finishGenericCall( | ... | @@ -5066,7 +5066,7 @@ fn finishGenericCall( |
| 5066 | total_i += 1; | 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 | try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.Call).Struct.fields.len + | 5071 | try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.Call).Struct.fields.len + |
| 5072 | runtime_args_len); | 5072 | runtime_args_len); |
| ... | @@ -15222,6 +15222,19 @@ fn structFieldPtr( | ... | @@ -15222,6 +15222,19 @@ fn structFieldPtr( |
| 15222 | | 15222 | |
| 15223 | const struct_ty = try sema.resolveTypeFields(block, src, unresolved_struct_ty); | 15223 | const struct_ty = try sema.resolveTypeFields(block, src, unresolved_struct_ty); |
| 15224 | try sema.resolveStructLayout(block, src, struct_ty); | 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 | const struct_obj = struct_ty.castTag(.@"struct").?.data; | 15238 | const struct_obj = struct_ty.castTag(.@"struct").?.data; |
| 15226 | | 15239 | |
| 15227 | const field_index_big = struct_obj.fields.getIndex(field_name) orelse | 15240 | const field_index_big = struct_obj.fields.getIndex(field_name) orelse |
| ... | @@ -15324,15 +15337,7 @@ fn structFieldVal( | ... | @@ -15324,15 +15337,7 @@ fn structFieldVal( |
| 15324 | switch (struct_ty.tag()) { | 15337 | switch (struct_ty.tag()) { |
| 15325 | .tuple, .empty_struct_literal => return sema.tupleFieldVal(block, src, struct_byval, field_name, field_name_src, struct_ty), | 15338 | .tuple, .empty_struct_literal => return sema.tupleFieldVal(block, src, struct_byval, field_name, field_name_src, struct_ty), |
| 15326 | .anon_struct => { | 15339 | .anon_struct => { |
| 15327 | const anon_struct = struct_ty.castTag(.anon_struct).?.data; | 15340 | const field_index = try sema.anonStructFieldIndex(block, struct_ty, field_name, field_name_src); |
| 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 | }; | | |
| 15336 | return tupleFieldValByIndex(sema, block, src, struct_byval, field_index, struct_ty); | 15341 | return tupleFieldValByIndex(sema, block, src, struct_byval, field_index, struct_ty); |
| 15337 | }, | 15342 | }, |
| 15338 | .@"struct" => { | 15343 | .@"struct" => { |
| ... | @@ -15376,7 +15381,18 @@ fn tupleFieldVal( | ... | @@ -15376,7 +15381,18 @@ fn tupleFieldVal( |
| 15376 | if (mem.eql(u8, field_name, "len")) { | 15381 | if (mem.eql(u8, field_name, "len")) { |
| 15377 | return sema.addIntUnsigned(Type.usize, tuple_ty.structFieldCount()); | 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 | const field_index = std.fmt.parseUnsigned(u32, field_name, 10) catch |err| { | 15396 | const field_index = std.fmt.parseUnsigned(u32, field_name, 10) catch |err| { |
| 15381 | return sema.fail(block, field_name_src, "tuple {} has no such field '{s}': {s}", .{ | 15397 | return sema.fail(block, field_name_src, "tuple {} has no such field '{s}': {s}", .{ |
| 15382 | tuple_ty, field_name, @errorName(err), | 15398 | tuple_ty, field_name, @errorName(err), |
| ... | @@ -15387,7 +15403,7 @@ fn tupleFieldVal( | ... | @@ -15387,7 +15403,7 @@ fn tupleFieldVal( |
| 15387 | tuple_ty, field_name, | 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 | fn tupleFieldValByIndex( | 15409 | fn tupleFieldValByIndex( |
| ... | @@ -15685,15 +15701,15 @@ fn tupleFieldPtr( | ... | @@ -15685,15 +15701,15 @@ fn tupleFieldPtr( |
| 15685 | ) CompileError!Air.Inst.Ref { | 15701 | ) CompileError!Air.Inst.Ref { |
| 15686 | const tuple_ptr_ty = sema.typeOf(tuple_ptr); | 15702 | const tuple_ptr_ty = sema.typeOf(tuple_ptr); |
| 15687 | const tuple_ty = tuple_ptr_ty.childType(); | 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 | return sema.fail(block, field_index_src, "index {d} outside tuple of length {d}", .{ | 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 | const target = sema.mod.getTarget(); | 15713 | const target = sema.mod.getTarget(); |
| 15698 | const ptr_field_ty = try Type.ptr(sema.arena, target, .{ | 15714 | const ptr_field_ty = try Type.ptr(sema.arena, target, .{ |
| 15699 | .pointee_type = field_ty, | 15715 | .pointee_type = field_ty, |
| ... | @@ -20470,3 +20486,21 @@ fn structFieldIndex( | ... | @@ -20470,3 +20486,21 @@ fn structFieldIndex( |
| 20470 | return sema.failWithBadStructFieldAccess(block, struct_obj, field_src, field_name); | 20486 | return sema.failWithBadStructFieldAccess(block, struct_obj, field_src, field_name); |
| 20471 | return @intCast(u32, field_index_usize); | 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 | } |