Commit e2fd289a33

LemonBoy <thatlemon@gmail.com>
2020-03-03 12:13:13
ir: Create usize result_loc for array subscript expr
Allow the subscript expression to infer the resulting type. Closes #4169
1 parent 06d0dac
Changed files (3)
src
test
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);
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();
+}
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'",