authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-08-25 19:31:39+03:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-26 19:50:56-07:00
logbcd04089ebf563659972c1a0fe1864521b128d37
tree7f64f0b59b209712229d74113674cb7572a77a9d
parentb1aa2857ffc631041a36e26b606c060eec1aa6bb

stage2: add helpful error message for invalid for operands


4 files changed, 26 insertions(+), 0 deletions(-)

src-self-hosted/astgen.zig+1
...@@ -1235,6 +1235,7 @@ fn forExpr(mod: *Module, scope: *Scope, rl: ResultLoc, for_node: *ast.Node.For)...@@ -1235,6 +1235,7 @@ fn forExpr(mod: *Module, scope: *Scope, rl: ResultLoc, for_node: *ast.Node.For)
1235 break :blk index_ptr;1235 break :blk index_ptr;
1236 };1236 };
1237 const array_ptr = try expr(mod, &for_scope.base, .ref, for_node.array_expr);1237 const array_ptr = try expr(mod, &for_scope.base, .ref, for_node.array_expr);
1238 _ = try addZIRUnOp(mod, &for_scope.base, for_node.array_expr.firstToken(), .ensure_indexable, array_ptr);
1238 const cond_src = tree.token_locs[for_node.array_expr.firstToken()].start;1239 const cond_src = tree.token_locs[for_node.array_expr.firstToken()].start;
1239 const len_ptr = try addZIRInst(mod, &for_scope.base, cond_src, zir.Inst.FieldPtr, .{1240 const len_ptr = try addZIRInst(mod, &for_scope.base, cond_src, zir.Inst.FieldPtr, .{
1240 .object_ptr = array_ptr,1241 .object_ptr = array_ptr,
src-self-hosted/type.zig+7
...@@ -2675,6 +2675,13 @@ pub const Type = extern union {...@@ -2675,6 +2675,13 @@ pub const Type = extern union {
2675 };2675 };
2676 }2676 }
26772677
2678 pub fn isIndexable(self: Type) bool {
2679 const zig_tag = self.zigTypeTag();
2680 // TODO tuples are indexable
2681 return zig_tag == .Array or zig_tag == .Vector or self.isSlice() or
2682 (self.isSinglePointer() and self.elemType().zigTypeTag() == .Array);
2683 }
2684
2678 /// This enum does not directly correspond to `std.builtin.TypeId` because2685 /// This enum does not directly correspond to `std.builtin.TypeId` because
2679 /// it has extra enum tags in it, as a way of using less memory. For example,2686 /// it has extra enum tags in it, as a way of using less memory. For example,
2680 /// even though Zig recognizes `*align(10) i32` and `*i32` both as Pointer types2687 /// even though Zig recognizes `*align(10) i32` and `*i32` both as Pointer types
src-self-hosted/zir.zig+4
...@@ -137,6 +137,8 @@ pub const Inst = struct {...@@ -137,6 +137,8 @@ pub const Inst = struct {
137 ensure_result_used,137 ensure_result_used,
138 /// Emits a compile error if an error is ignored.138 /// Emits a compile error if an error is ignored.
139 ensure_result_non_error,139 ensure_result_non_error,
140 /// Emits a compile error if operand cannot be indexed.
141 ensure_indexable,
140 /// Create a `E!T` type.142 /// Create a `E!T` type.
141 error_union_type,143 error_union_type,
142 /// Create an error set.144 /// Create an error set.
...@@ -278,6 +280,7 @@ pub const Inst = struct {...@@ -278,6 +280,7 @@ pub const Inst = struct {
278 .alloc,280 .alloc,
279 .ensure_result_used,281 .ensure_result_used,
280 .ensure_result_non_error,282 .ensure_result_non_error,
283 .ensure_indexable,
281 .bitcast_result_ptr,284 .bitcast_result_ptr,
282 .ref,285 .ref,
283 .bitcast_ref,286 .bitcast_ref,
...@@ -409,6 +412,7 @@ pub const Inst = struct {...@@ -409,6 +412,7 @@ pub const Inst = struct {
409 .elemptr,412 .elemptr,
410 .ensure_result_used,413 .ensure_result_used,
411 .ensure_result_non_error,414 .ensure_result_non_error,
415 .ensure_indexable,
412 .@"export",416 .@"export",
413 .floatcast,417 .floatcast,
414 .fieldptr,418 .fieldptr,
src-self-hosted/zir_sema.zig+14
...@@ -48,6 +48,7 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!...@@ -48,6 +48,7 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!
48 .declval_in_module => return analyzeInstDeclValInModule(mod, scope, old_inst.castTag(.declval_in_module).?),48 .declval_in_module => return analyzeInstDeclValInModule(mod, scope, old_inst.castTag(.declval_in_module).?),
49 .ensure_result_used => return analyzeInstEnsureResultUsed(mod, scope, old_inst.castTag(.ensure_result_used).?),49 .ensure_result_used => return analyzeInstEnsureResultUsed(mod, scope, old_inst.castTag(.ensure_result_used).?),
50 .ensure_result_non_error => return analyzeInstEnsureResultNonError(mod, scope, old_inst.castTag(.ensure_result_non_error).?),50 .ensure_result_non_error => return analyzeInstEnsureResultNonError(mod, scope, old_inst.castTag(.ensure_result_non_error).?),
51 .ensure_indexable => return analyzeInstEnsureIndexable(mod, scope, old_inst.castTag(.ensure_indexable).?),
51 .ref => return analyzeInstRef(mod, scope, old_inst.castTag(.ref).?),52 .ref => return analyzeInstRef(mod, scope, old_inst.castTag(.ref).?),
52 .ret_ptr => return analyzeInstRetPtr(mod, scope, old_inst.castTag(.ret_ptr).?),53 .ret_ptr => return analyzeInstRetPtr(mod, scope, old_inst.castTag(.ret_ptr).?),
53 .ret_type => return analyzeInstRetType(mod, scope, old_inst.castTag(.ret_type).?),54 .ret_type => return analyzeInstRetType(mod, scope, old_inst.castTag(.ret_type).?),
...@@ -382,6 +383,19 @@ fn analyzeInstEnsureResultNonError(mod: *Module, scope: *Scope, inst: *zir.Inst....@@ -382,6 +383,19 @@ fn analyzeInstEnsureResultNonError(mod: *Module, scope: *Scope, inst: *zir.Inst.
382 }383 }
383}384}
384385
386fn analyzeInstEnsureIndexable(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
387 const operand = try resolveInst(mod, scope, inst.positionals.operand);
388 const elem_ty = operand.ty.elemType();
389 if (elem_ty.isIndexable()) {
390 return mod.constVoid(scope, operand.src);
391 } else {
392 // TODO error notes
393 // error: type '{}' does not support indexing
394 // note: for loop operand must be an array, a slice or a tuple
395 return mod.fail(scope, operand.src, "for loop operand must be an array, a slice or a tuple", .{});
396 }
397}
398
385fn analyzeInstAlloc(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {399fn analyzeInstAlloc(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
386 const var_type = try resolveType(mod, scope, inst.positionals.operand);400 const var_type = try resolveType(mod, scope, inst.positionals.operand);
387 // TODO this should happen only for var allocs401 // TODO this should happen only for var allocs