zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit e2fd289a33bb35cf4b86daa4d80adb7cc0c2c2b0 (tree)
parent 06d0dac0fb58c2d20036e34f5c1a1bc9c386c189
Author: LemonBoy <thatlemon@gmail.com>
Date:   Tue,  3 Mar 2020 12:13:13 +0100

ir: Create usize result_loc for array subscript expr

Allow the subscript expression to infer the resulting type.

Closes #4169

Diffstat:
Msrc/ir.cpp | 14+++++++++++---
Mtest/compile_errors.zig | 4++--
Mtest/stage1/behavior/array.zig | 18+++++++++++++++++-
3 files changed, 30 insertions(+), 6 deletions(-)

diff --git a/src/ir.cpp b/src/ir.cpp @@ -5910,10 +5910,18 @@ static IrInstSrc *ir_gen_array_access(IrBuilderSrc *irb, Scope *scope, AstNode * if (array_ref_instruction == irb->codegen->invalid_inst_src) return array_ref_instruction; + // Create an usize-typed result location to hold the subscript value, this + // makes it possible for the compiler to infer the subscript expression type + // if needed + IrInstSrc *usize_type_inst = ir_build_const_type(irb, scope, node, irb->codegen->builtin_types.entry_usize); + ResultLocCast *result_loc_cast = ir_build_cast_result_loc(irb, usize_type_inst, no_result_loc()); + AstNode *subscript_node = node->data.array_access_expr.subscript; - IrInstSrc *subscript_instruction = ir_gen_node(irb, subscript_node, scope); - if (subscript_instruction == irb->codegen->invalid_inst_src) - return subscript_instruction; + IrInstSrc *subscript_value = ir_gen_node_extra(irb, subscript_node, scope, LValNone, &result_loc_cast->base); + if (subscript_value == irb->codegen->invalid_inst_src) + return irb->codegen->invalid_inst_src; + + IrInstSrc *subscript_instruction = ir_build_implicit_cast(irb, scope, subscript_node, subscript_value, result_loc_cast); IrInstSrc *ptr_instruction = ir_build_elem_ptr(irb, scope, node, array_ref_instruction, subscript_instruction, true, PtrLenSingle, nullptr); diff --git a/test/compile_errors.zig b/test/compile_errors.zig @@ -3610,11 +3610,11 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { cases.add("array access of non array", \\export fn f() void { \\ var bad : bool = undefined; - \\ bad[bad] = bad[bad]; + \\ bad[0] = bad[0]; \\} \\export fn g() void { \\ var bad : bool = undefined; - \\ _ = bad[bad]; + \\ _ = bad[0]; \\} , &[_][]const u8{ "tmp.zig:3:8: error: array access of non-array type 'bool'", diff --git a/test/stage1/behavior/array.zig b/test/stage1/behavior/array.zig @@ -1,6 +1,8 @@ const std = @import("std"); -const expect = std.testing.expect; +const testing = std.testing; const mem = std.mem; +const expect = testing.expect; +const expectEqual = testing.expectEqual; test "arrays" { var array: [5]u32 = undefined; @@ -360,3 +362,17 @@ test "access the null element of a null terminated array" { S.doTheTest(); comptime S.doTheTest(); } + +test "type deduction for array subscript expression" { + const S = struct { + fn doTheTest() void { + var array = [_]u8{ 0x55, 0xAA }; + var v0 = true; + expectEqual(@as(u8, 0xAA), array[if (v0) 1 else 0]); + var v1 = false; + expectEqual(@as(u8, 0x55), array[if (v1) 1 else 0]); + } + }; + S.doTheTest(); + comptime S.doTheTest(); +}