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)
12351235 break :blk index_ptr;
12361236 };
12371237 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);
12381239 const cond_src = tree.token_locs[for_node.array_expr.firstToken()].start;
12391240 const len_ptr = try addZIRInst(mod, &for_scope.base, cond_src, zir.Inst.FieldPtr, .{
12401241 .object_ptr = array_ptr,
src-self-hosted/type.zig+7
......@@ -2675,6 +2675,13 @@ pub const Type = extern union {
26752675 };
26762676 }
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
26782685 /// This enum does not directly correspond to `std.builtin.TypeId` because
26792686 /// it has extra enum tags in it, as a way of using less memory. For example,
26802687 /// 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 {
137137 ensure_result_used,
138138 /// Emits a compile error if an error is ignored.
139139 ensure_result_non_error,
140 /// Emits a compile error if operand cannot be indexed.
141 ensure_indexable,
140142 /// Create a `E!T` type.
141143 error_union_type,
142144 /// Create an error set.
......@@ -278,6 +280,7 @@ pub const Inst = struct {
278280 .alloc,
279281 .ensure_result_used,
280282 .ensure_result_non_error,
283 .ensure_indexable,
281284 .bitcast_result_ptr,
282285 .ref,
283286 .bitcast_ref,
......@@ -409,6 +412,7 @@ pub const Inst = struct {
409412 .elemptr,
410413 .ensure_result_used,
411414 .ensure_result_non_error,
415 .ensure_indexable,
412416 .@"export",
413417 .floatcast,
414418 .fieldptr,
src-self-hosted/zir_sema.zig+14
......@@ -48,6 +48,7 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!
4848 .declval_in_module => return analyzeInstDeclValInModule(mod, scope, old_inst.castTag(.declval_in_module).?),
4949 .ensure_result_used => return analyzeInstEnsureResultUsed(mod, scope, old_inst.castTag(.ensure_result_used).?),
5050 .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).?),
5152 .ref => return analyzeInstRef(mod, scope, old_inst.castTag(.ref).?),
5253 .ret_ptr => return analyzeInstRetPtr(mod, scope, old_inst.castTag(.ret_ptr).?),
5354 .ret_type => return analyzeInstRetType(mod, scope, old_inst.castTag(.ret_type).?),
......@@ -382,6 +383,19 @@ fn analyzeInstEnsureResultNonError(mod: *Module, scope: *Scope, inst: *zir.Inst.
382383 }
383384}
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
385399fn analyzeInstAlloc(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
386400 const var_type = try resolveType(mod, scope, inst.positionals.operand);
387401 // TODO this should happen only for var allocs