mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 21:08:36 +00:00
stage2: add helpful error message for invalid for operands
This commit is contained in:
parent
b1aa2857ff
commit
bcd04089eb
@ -1235,6 +1235,7 @@ fn forExpr(mod: *Module, scope: *Scope, rl: ResultLoc, for_node: *ast.Node.For)
|
||||
break :blk index_ptr;
|
||||
};
|
||||
const array_ptr = try expr(mod, &for_scope.base, .ref, for_node.array_expr);
|
||||
_ = try addZIRUnOp(mod, &for_scope.base, for_node.array_expr.firstToken(), .ensure_indexable, array_ptr);
|
||||
const cond_src = tree.token_locs[for_node.array_expr.firstToken()].start;
|
||||
const len_ptr = try addZIRInst(mod, &for_scope.base, cond_src, zir.Inst.FieldPtr, .{
|
||||
.object_ptr = array_ptr,
|
||||
|
||||
@ -2675,6 +2675,13 @@ pub const Type = extern union {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn isIndexable(self: Type) bool {
|
||||
const zig_tag = self.zigTypeTag();
|
||||
// TODO tuples are indexable
|
||||
return zig_tag == .Array or zig_tag == .Vector or self.isSlice() or
|
||||
(self.isSinglePointer() and self.elemType().zigTypeTag() == .Array);
|
||||
}
|
||||
|
||||
/// This enum does not directly correspond to `std.builtin.TypeId` because
|
||||
/// it has extra enum tags in it, as a way of using less memory. For example,
|
||||
/// even though Zig recognizes `*align(10) i32` and `*i32` both as Pointer types
|
||||
|
||||
@ -137,6 +137,8 @@ pub const Inst = struct {
|
||||
ensure_result_used,
|
||||
/// Emits a compile error if an error is ignored.
|
||||
ensure_result_non_error,
|
||||
/// Emits a compile error if operand cannot be indexed.
|
||||
ensure_indexable,
|
||||
/// Create a `E!T` type.
|
||||
error_union_type,
|
||||
/// Create an error set.
|
||||
@ -278,6 +280,7 @@ pub const Inst = struct {
|
||||
.alloc,
|
||||
.ensure_result_used,
|
||||
.ensure_result_non_error,
|
||||
.ensure_indexable,
|
||||
.bitcast_result_ptr,
|
||||
.ref,
|
||||
.bitcast_ref,
|
||||
@ -409,6 +412,7 @@ pub const Inst = struct {
|
||||
.elemptr,
|
||||
.ensure_result_used,
|
||||
.ensure_result_non_error,
|
||||
.ensure_indexable,
|
||||
.@"export",
|
||||
.floatcast,
|
||||
.fieldptr,
|
||||
|
||||
@ -48,6 +48,7 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!
|
||||
.declval_in_module => return analyzeInstDeclValInModule(mod, scope, old_inst.castTag(.declval_in_module).?),
|
||||
.ensure_result_used => return analyzeInstEnsureResultUsed(mod, scope, old_inst.castTag(.ensure_result_used).?),
|
||||
.ensure_result_non_error => return analyzeInstEnsureResultNonError(mod, scope, old_inst.castTag(.ensure_result_non_error).?),
|
||||
.ensure_indexable => return analyzeInstEnsureIndexable(mod, scope, old_inst.castTag(.ensure_indexable).?),
|
||||
.ref => return analyzeInstRef(mod, scope, old_inst.castTag(.ref).?),
|
||||
.ret_ptr => return analyzeInstRetPtr(mod, scope, old_inst.castTag(.ret_ptr).?),
|
||||
.ret_type => return analyzeInstRetType(mod, scope, old_inst.castTag(.ret_type).?),
|
||||
@ -382,6 +383,19 @@ fn analyzeInstEnsureResultNonError(mod: *Module, scope: *Scope, inst: *zir.Inst.
|
||||
}
|
||||
}
|
||||
|
||||
fn analyzeInstEnsureIndexable(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
|
||||
const operand = try resolveInst(mod, scope, inst.positionals.operand);
|
||||
const elem_ty = operand.ty.elemType();
|
||||
if (elem_ty.isIndexable()) {
|
||||
return mod.constVoid(scope, operand.src);
|
||||
} else {
|
||||
// TODO error notes
|
||||
// error: type '{}' does not support indexing
|
||||
// note: for loop operand must be an array, a slice or a tuple
|
||||
return mod.fail(scope, operand.src, "for loop operand must be an array, a slice or a tuple", .{});
|
||||
}
|
||||
}
|
||||
|
||||
fn analyzeInstAlloc(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
|
||||
const var_type = try resolveType(mod, scope, inst.positionals.operand);
|
||||
// TODO this should happen only for var allocs
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user