| author | |
| committer | |
| log | e2fd289a33bb35cf4b86daa4d80adb7cc0c2c2b0 |
| tree | abb7d449b2d8e6d505e4ef4598793e3bbe711b16 |
| parent | 06d0dac0fb58c2d20036e34f5c1a1bc9c386c189 |
Allow the subscript expression to infer the resulting type.
Closes #41693 files changed, 30 insertions(+), 6 deletions(-)
src/ir.cpp+11-3| ... | ... | @@ -5910,10 +5910,18 @@ static IrInstSrc *ir_gen_array_access(IrBuilderSrc *irb, Scope *scope, AstNode * |
| 5910 | 5910 | if (array_ref_instruction == irb->codegen->invalid_inst_src) |
| 5911 | 5911 | return array_ref_instruction; |
| 5912 | 5912 | |
| 5913 | // Create an usize-typed result location to hold the subscript value, this | |
| 5914 | // makes it possible for the compiler to infer the subscript expression type | |
| 5915 | // if needed | |
| 5916 | IrInstSrc *usize_type_inst = ir_build_const_type(irb, scope, node, irb->codegen->builtin_types.entry_usize); | |
| 5917 | ResultLocCast *result_loc_cast = ir_build_cast_result_loc(irb, usize_type_inst, no_result_loc()); | |
| 5918 | ||
| 5913 | 5919 | AstNode *subscript_node = node->data.array_access_expr.subscript; |
| 5914 | IrInstSrc *subscript_instruction = ir_gen_node(irb, subscript_node, scope); | |
| 5915 | if (subscript_instruction == irb->codegen->invalid_inst_src) | |
| 5916 | return subscript_instruction; | |
| 5920 | IrInstSrc *subscript_value = ir_gen_node_extra(irb, subscript_node, scope, LValNone, &result_loc_cast->base); | |
| 5921 | if (subscript_value == irb->codegen->invalid_inst_src) | |
| 5922 | return irb->codegen->invalid_inst_src; | |
| 5923 | ||
| 5924 | IrInstSrc *subscript_instruction = ir_build_implicit_cast(irb, scope, subscript_node, subscript_value, result_loc_cast); | |
| 5917 | 5925 | |
| 5918 | 5926 | IrInstSrc *ptr_instruction = ir_build_elem_ptr(irb, scope, node, array_ref_instruction, |
| 5919 | 5927 | subscript_instruction, true, PtrLenSingle, nullptr); |
test/compile_errors.zig+2-2| ... | ... | @@ -3610,11 +3610,11 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 3610 | 3610 | cases.add("array access of non array", |
| 3611 | 3611 | \\export fn f() void { |
| 3612 | 3612 | \\ var bad : bool = undefined; |
| 3613 | \\ bad[bad] = bad[bad]; | |
| 3613 | \\ bad[0] = bad[0]; | |
| 3614 | 3614 | \\} |
| 3615 | 3615 | \\export fn g() void { |
| 3616 | 3616 | \\ var bad : bool = undefined; |
| 3617 | \\ _ = bad[bad]; | |
| 3617 | \\ _ = bad[0]; | |
| 3618 | 3618 | \\} |
| 3619 | 3619 | , &[_][]const u8{ |
| 3620 | 3620 | "tmp.zig:3:8: error: array access of non-array type 'bool'", |
test/stage1/behavior/array.zig+17-1| ... | ... | @@ -1,6 +1,8 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | const expect = std.testing.expect; | |
| 2 | const testing = std.testing; | |
| 3 | 3 | const mem = std.mem; |
| 4 | const expect = testing.expect; | |
| 5 | const expectEqual = testing.expectEqual; | |
| 4 | 6 | |
| 5 | 7 | test "arrays" { |
| 6 | 8 | var array: [5]u32 = undefined; |
| ... | ... | @@ -360,3 +362,17 @@ test "access the null element of a null terminated array" { |
| 360 | 362 | S.doTheTest(); |
| 361 | 363 | comptime S.doTheTest(); |
| 362 | 364 | } |
| 365 | ||
| 366 | test "type deduction for array subscript expression" { | |
| 367 | const S = struct { | |
| 368 | fn doTheTest() void { | |
| 369 | var array = [_]u8{ 0x55, 0xAA }; | |
| 370 | var v0 = true; | |
| 371 | expectEqual(@as(u8, 0xAA), array[if (v0) 1 else 0]); | |
| 372 | var v1 = false; | |
| 373 | expectEqual(@as(u8, 0x55), array[if (v1) 1 else 0]); | |
| 374 | } | |
| 375 | }; | |
| 376 | S.doTheTest(); | |
| 377 | comptime S.doTheTest(); | |
| 378 | } |