mirror of
https://github.com/ziglang/zig.git
synced 2026-01-21 14:55:25 +00:00
implement error for unbounded for loops
This commit is contained in:
parent
e89bfedd8d
commit
8b05205bb7
@ -6394,11 +6394,13 @@ fn forExpr(
|
||||
}
|
||||
}
|
||||
|
||||
if (!any_len_checks) {
|
||||
return astgen.failNode(node, "unbounded for loop", .{});
|
||||
}
|
||||
|
||||
// We use a dedicated ZIR instruction to assert the lengths to assist with
|
||||
// nicer error reporting as well as fewer ZIR bytes emitted.
|
||||
const len: Zir.Inst.Ref = len: {
|
||||
if (!any_len_checks) break :len .none;
|
||||
|
||||
const lens_len = @intCast(u32, lens.len);
|
||||
try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.MultiOp).Struct.fields.len + lens_len);
|
||||
const len = try parent_gz.addPlNode(.for_len, node, Zir.Inst.MultiOp{
|
||||
@ -6424,9 +6426,6 @@ fn forExpr(
|
||||
defer cond_scope.unstack();
|
||||
|
||||
// Check the condition.
|
||||
if (!any_len_checks) {
|
||||
return astgen.failNode(node, "TODO: handle infinite for loop", .{});
|
||||
}
|
||||
const cond = try cond_scope.addPlNode(.cmp_lt, node, Zir.Inst.Bin{
|
||||
.lhs = index,
|
||||
.rhs = len,
|
||||
|
||||
26
src/Sema.zig
26
src/Sema.zig
@ -3975,7 +3975,31 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
|
||||
}
|
||||
|
||||
if (len == .none) {
|
||||
return sema.fail(block, src, "non-obvious infinite loop", .{});
|
||||
const msg = msg: {
|
||||
const msg = try sema.errMsg(block, src, "unbounded for loop", .{});
|
||||
errdefer msg.destroy(gpa);
|
||||
for (args, 0..) |zir_arg, i_usize| {
|
||||
const i = @intCast(u32, i_usize);
|
||||
if (zir_arg == .none) continue;
|
||||
const object = try sema.resolveInst(zir_arg);
|
||||
const object_ty = sema.typeOf(object);
|
||||
// Each arg could be an indexable, or a range, in which case the length
|
||||
// is passed directly as an integer.
|
||||
switch (object_ty.zigTypeTag()) {
|
||||
.Int, .ComptimeInt => continue,
|
||||
else => {},
|
||||
}
|
||||
const arg_src: LazySrcLoc = .{ .for_input = .{
|
||||
.for_node_offset = inst_data.src_node,
|
||||
.input_index = i,
|
||||
} };
|
||||
try sema.errNote(block, arg_src, msg, "type '{}' has no upper bound", .{
|
||||
object_ty.fmt(sema.mod),
|
||||
});
|
||||
}
|
||||
break :msg msg;
|
||||
};
|
||||
return sema.failWithOwnedErrorMsg(msg);
|
||||
}
|
||||
|
||||
// Now for the runtime checks.
|
||||
|
||||
@ -378,3 +378,22 @@ test "raw pointer and slice" {
|
||||
try expect(buf[2] == 'a');
|
||||
try expect(buf[3] == 'h');
|
||||
}
|
||||
|
||||
test "raw pointer and counter" {
|
||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||
|
||||
var buf: [10]u8 = undefined;
|
||||
const ptr: [*]u8 = &buf;
|
||||
|
||||
for (ptr, 0..4) |*a, b| {
|
||||
a.* = @intCast(u8, 'A' + b);
|
||||
}
|
||||
|
||||
try expect(buf[0] == 'A');
|
||||
try expect(buf[1] == 'B');
|
||||
try expect(buf[2] == 'C');
|
||||
try expect(buf[3] == 'D');
|
||||
}
|
||||
|
||||
@ -16,6 +16,13 @@ export fn c() void {
|
||||
_ = byte;
|
||||
}
|
||||
}
|
||||
export fn d() void {
|
||||
const x: [*]const u8 = "hello";
|
||||
const y: [*]const u8 = "world";
|
||||
for (x, 0.., y) |x1, x2, x3| {
|
||||
_ = x1; _ = x2; _ = x3;
|
||||
}
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
@ -28,3 +35,6 @@ export fn c() void {
|
||||
// :9:14: note: for loop operand must be an array, slice, tuple, or vector
|
||||
// :15:16: error: pointer capture of non pointer type '[10]u8'
|
||||
// :15:10: note: consider using '&' here
|
||||
// :22:5: error: unbounded for loop
|
||||
// :22:10: note: type '[*]const u8' has no upper bound
|
||||
// :22:18: note: type '[*]const u8' has no upper bound
|
||||
|
||||
11
test/cases/compile_errors/for_unbounded.zig
Normal file
11
test/cases/compile_errors/for_unbounded.zig
Normal file
@ -0,0 +1,11 @@
|
||||
export fn b() void {
|
||||
for (0..) |i| {
|
||||
_ = i;
|
||||
}
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :2:5: error: unbounded for loop
|
||||
Loading…
x
Reference in New Issue
Block a user