From 9e0a930ce3be01923602adbfee13b50842da08b7 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Tue, 26 Jul 2022 16:20:38 +0300 Subject: stage2: add error for comptime control flow in runtime block --- .../comptime_continue_inside_runtime_catch.zig | 16 ++++++++++++++++ .../comptime_continue_inside_runtime_if_bool.zig | 15 +++++++++++++++ .../comptime_continue_inside_runtime_if_error.zig | 15 +++++++++++++++ .../comptime_continue_inside_runtime_if_optional.zig | 15 +++++++++++++++ .../comptime_continue_inside_runtime_orelse.zig | 16 ++++++++++++++++ .../comptime_continue_inside_runtime_switch.zig | 18 ++++++++++++++++++ .../comptime_continue_inside_runtime_while_bool.zig | 15 +++++++++++++++ .../comptime_continue_inside_runtime_while_error.zig | 17 +++++++++++++++++ ...comptime_continue_inside_runtime_while_optional.zig | 15 +++++++++++++++ .../obj/comptime_continue_inside_runtime_catch.zig | 16 ---------------- .../obj/comptime_continue_inside_runtime_if_bool.zig | 15 --------------- .../obj/comptime_continue_inside_runtime_if_error.zig | 15 --------------- .../comptime_continue_inside_runtime_if_optional.zig | 15 --------------- .../obj/comptime_continue_inside_runtime_switch.zig | 18 ------------------ .../comptime_continue_inside_runtime_while_bool.zig | 15 --------------- .../comptime_continue_inside_runtime_while_error.zig | 17 ----------------- ...comptime_continue_inside_runtime_while_optional.zig | 15 --------------- 17 files changed, 142 insertions(+), 126 deletions(-) create mode 100644 test/cases/compile_errors/comptime_continue_inside_runtime_catch.zig create mode 100644 test/cases/compile_errors/comptime_continue_inside_runtime_if_bool.zig create mode 100644 test/cases/compile_errors/comptime_continue_inside_runtime_if_error.zig create mode 100644 test/cases/compile_errors/comptime_continue_inside_runtime_if_optional.zig create mode 100644 test/cases/compile_errors/comptime_continue_inside_runtime_orelse.zig create mode 100644 test/cases/compile_errors/comptime_continue_inside_runtime_switch.zig create mode 100644 test/cases/compile_errors/comptime_continue_inside_runtime_while_bool.zig create mode 100644 test/cases/compile_errors/comptime_continue_inside_runtime_while_error.zig create mode 100644 test/cases/compile_errors/comptime_continue_inside_runtime_while_optional.zig delete mode 100644 test/cases/compile_errors/stage1/obj/comptime_continue_inside_runtime_catch.zig delete mode 100644 test/cases/compile_errors/stage1/obj/comptime_continue_inside_runtime_if_bool.zig delete mode 100644 test/cases/compile_errors/stage1/obj/comptime_continue_inside_runtime_if_error.zig delete mode 100644 test/cases/compile_errors/stage1/obj/comptime_continue_inside_runtime_if_optional.zig delete mode 100644 test/cases/compile_errors/stage1/obj/comptime_continue_inside_runtime_switch.zig delete mode 100644 test/cases/compile_errors/stage1/obj/comptime_continue_inside_runtime_while_bool.zig delete mode 100644 test/cases/compile_errors/stage1/obj/comptime_continue_inside_runtime_while_error.zig delete mode 100644 test/cases/compile_errors/stage1/obj/comptime_continue_inside_runtime_while_optional.zig (limited to 'test/cases') diff --git a/test/cases/compile_errors/comptime_continue_inside_runtime_catch.zig b/test/cases/compile_errors/comptime_continue_inside_runtime_catch.zig new file mode 100644 index 0000000000..9e62420f1f --- /dev/null +++ b/test/cases/compile_errors/comptime_continue_inside_runtime_catch.zig @@ -0,0 +1,16 @@ +export fn entry() void { + const ints = [_]u8{ 1, 2 }; + inline for (ints) |_| { + bad() catch continue; + } +} +fn bad() !void { + return error.Bad; +} + +// error +// backend=stage2 +// target=native +// +// :4:21: error: comptime control flow inside runtime block +// :4:15: note: runtime control flow here diff --git a/test/cases/compile_errors/comptime_continue_inside_runtime_if_bool.zig b/test/cases/compile_errors/comptime_continue_inside_runtime_if_bool.zig new file mode 100644 index 0000000000..b2a7312c52 --- /dev/null +++ b/test/cases/compile_errors/comptime_continue_inside_runtime_if_bool.zig @@ -0,0 +1,15 @@ +export fn entry() void { + var p: usize = undefined; + comptime var q = true; + inline while (q) { + if (p == 11) continue; + q = false; + } +} + +// error +// backend=stage2 +// target=native +// +// :5:22: error: comptime control flow inside runtime block +// :5:15: note: runtime control flow here diff --git a/test/cases/compile_errors/comptime_continue_inside_runtime_if_error.zig b/test/cases/compile_errors/comptime_continue_inside_runtime_if_error.zig new file mode 100644 index 0000000000..194274a1ed --- /dev/null +++ b/test/cases/compile_errors/comptime_continue_inside_runtime_if_error.zig @@ -0,0 +1,15 @@ +export fn entry() void { + var p: anyerror!i32 = undefined; + comptime var q = true; + inline while (q) { + if (p) |_| continue else |_| {} + q = false; + } +} + +// error +// backend=stage2 +// target=native +// +// :5:20: error: comptime control flow inside runtime block +// :5:13: note: runtime control flow here diff --git a/test/cases/compile_errors/comptime_continue_inside_runtime_if_optional.zig b/test/cases/compile_errors/comptime_continue_inside_runtime_if_optional.zig new file mode 100644 index 0000000000..965454ef03 --- /dev/null +++ b/test/cases/compile_errors/comptime_continue_inside_runtime_if_optional.zig @@ -0,0 +1,15 @@ +export fn entry() void { + var p: ?i32 = undefined; + comptime var q = true; + inline while (q) { + if (p) |_| continue; + q = false; + } +} + +// error +// backend=stage2 +// target=native +// +// :5:20: error: comptime control flow inside runtime block +// :5:13: note: runtime control flow here diff --git a/test/cases/compile_errors/comptime_continue_inside_runtime_orelse.zig b/test/cases/compile_errors/comptime_continue_inside_runtime_orelse.zig new file mode 100644 index 0000000000..56b65c1ab7 --- /dev/null +++ b/test/cases/compile_errors/comptime_continue_inside_runtime_orelse.zig @@ -0,0 +1,16 @@ +export fn entry() void { + const ints = [_]u8{ 1, 2 }; + inline for (ints) |_| { + bad() orelse continue; + } +} +fn bad() ?void { + return null; +} + +// error +// backend=stage2 +// target=native +// +// :4:22: error: comptime control flow inside runtime block +// :4:15: note: runtime control flow here diff --git a/test/cases/compile_errors/comptime_continue_inside_runtime_switch.zig b/test/cases/compile_errors/comptime_continue_inside_runtime_switch.zig new file mode 100644 index 0000000000..391ecbdf1a --- /dev/null +++ b/test/cases/compile_errors/comptime_continue_inside_runtime_switch.zig @@ -0,0 +1,18 @@ +export fn entry() void { + var p: i32 = undefined; + comptime var q = true; + inline while (q) { + switch (p) { + 11 => continue, + else => {}, + } + q = false; + } +} + +// error +// backend=stage2 +// target=native +// +// :6:19: error: comptime control flow inside runtime block +// :5:17: note: runtime control flow here diff --git a/test/cases/compile_errors/comptime_continue_inside_runtime_while_bool.zig b/test/cases/compile_errors/comptime_continue_inside_runtime_while_bool.zig new file mode 100644 index 0000000000..54d62e6d37 --- /dev/null +++ b/test/cases/compile_errors/comptime_continue_inside_runtime_while_bool.zig @@ -0,0 +1,15 @@ +export fn entry() void { + var p: usize = undefined; + comptime var q = true; + outer: inline while (q) { + while (p == 11) continue :outer; + q = false; + } +} + +// error +// backend=stage2 +// target=native +// +// :5:25: error: comptime control flow inside runtime block +// :5:18: note: runtime control flow here diff --git a/test/cases/compile_errors/comptime_continue_inside_runtime_while_error.zig b/test/cases/compile_errors/comptime_continue_inside_runtime_while_error.zig new file mode 100644 index 0000000000..0eef1c3374 --- /dev/null +++ b/test/cases/compile_errors/comptime_continue_inside_runtime_while_error.zig @@ -0,0 +1,17 @@ +export fn entry() void { + var p: anyerror!usize = undefined; + comptime var q = true; + outer: inline while (q) { + while (p) |_| { + continue :outer; + } else |_| {} + q = false; + } +} + +// error +// backend=stage2 +// target=native +// +// :6:13: error: comptime control flow inside runtime block +// :5:16: note: runtime control flow here diff --git a/test/cases/compile_errors/comptime_continue_inside_runtime_while_optional.zig b/test/cases/compile_errors/comptime_continue_inside_runtime_while_optional.zig new file mode 100644 index 0000000000..e6753a5911 --- /dev/null +++ b/test/cases/compile_errors/comptime_continue_inside_runtime_while_optional.zig @@ -0,0 +1,15 @@ +export fn entry() void { + var p: ?usize = undefined; + comptime var q = true; + outer: inline while (q) { + while (p) |_| continue :outer; + q = false; + } +} + +// error +// backend=stage2 +// target=native +// +// :5:23: error: comptime control flow inside runtime block +// :5:16: note: runtime control flow here diff --git a/test/cases/compile_errors/stage1/obj/comptime_continue_inside_runtime_catch.zig b/test/cases/compile_errors/stage1/obj/comptime_continue_inside_runtime_catch.zig deleted file mode 100644 index 7eefeb80b4..0000000000 --- a/test/cases/compile_errors/stage1/obj/comptime_continue_inside_runtime_catch.zig +++ /dev/null @@ -1,16 +0,0 @@ -export fn entry() void { - const ints = [_]u8{ 1, 2 }; - inline for (ints) |_| { - bad() catch continue; - } -} -fn bad() !void { - return error.Bad; -} - -// error -// backend=stage1 -// target=native -// -// tmp.zig:4:21: error: comptime control flow inside runtime block -// tmp.zig:4:15: note: runtime block created here diff --git a/test/cases/compile_errors/stage1/obj/comptime_continue_inside_runtime_if_bool.zig b/test/cases/compile_errors/stage1/obj/comptime_continue_inside_runtime_if_bool.zig deleted file mode 100644 index 9ace5ddceb..0000000000 --- a/test/cases/compile_errors/stage1/obj/comptime_continue_inside_runtime_if_bool.zig +++ /dev/null @@ -1,15 +0,0 @@ -export fn entry() void { - var p: usize = undefined; - comptime var q = true; - inline while (q) { - if (p == 11) continue; - q = false; - } -} - -// error -// backend=stage1 -// target=native -// -// tmp.zig:5:22: error: comptime control flow inside runtime block -// tmp.zig:5:9: note: runtime block created here diff --git a/test/cases/compile_errors/stage1/obj/comptime_continue_inside_runtime_if_error.zig b/test/cases/compile_errors/stage1/obj/comptime_continue_inside_runtime_if_error.zig deleted file mode 100644 index 554ba3c43e..0000000000 --- a/test/cases/compile_errors/stage1/obj/comptime_continue_inside_runtime_if_error.zig +++ /dev/null @@ -1,15 +0,0 @@ -export fn entry() void { - var p: anyerror!i32 = undefined; - comptime var q = true; - inline while (q) { - if (p) |_| continue else |_| {} - q = false; - } -} - -// error -// backend=stage1 -// target=native -// -// tmp.zig:5:20: error: comptime control flow inside runtime block -// tmp.zig:5:9: note: runtime block created here diff --git a/test/cases/compile_errors/stage1/obj/comptime_continue_inside_runtime_if_optional.zig b/test/cases/compile_errors/stage1/obj/comptime_continue_inside_runtime_if_optional.zig deleted file mode 100644 index 32c71e5c77..0000000000 --- a/test/cases/compile_errors/stage1/obj/comptime_continue_inside_runtime_if_optional.zig +++ /dev/null @@ -1,15 +0,0 @@ -export fn entry() void { - var p: ?i32 = undefined; - comptime var q = true; - inline while (q) { - if (p) |_| continue; - q = false; - } -} - -// error -// backend=stage1 -// target=native -// -// tmp.zig:5:20: error: comptime control flow inside runtime block -// tmp.zig:5:9: note: runtime block created here diff --git a/test/cases/compile_errors/stage1/obj/comptime_continue_inside_runtime_switch.zig b/test/cases/compile_errors/stage1/obj/comptime_continue_inside_runtime_switch.zig deleted file mode 100644 index d145897b41..0000000000 --- a/test/cases/compile_errors/stage1/obj/comptime_continue_inside_runtime_switch.zig +++ /dev/null @@ -1,18 +0,0 @@ -export fn entry() void { - var p: i32 = undefined; - comptime var q = true; - inline while (q) { - switch (p) { - 11 => continue, - else => {}, - } - q = false; - } -} - -// error -// backend=stage1 -// target=native -// -// tmp.zig:6:19: error: comptime control flow inside runtime block -// tmp.zig:5:9: note: runtime block created here diff --git a/test/cases/compile_errors/stage1/obj/comptime_continue_inside_runtime_while_bool.zig b/test/cases/compile_errors/stage1/obj/comptime_continue_inside_runtime_while_bool.zig deleted file mode 100644 index 8e57854728..0000000000 --- a/test/cases/compile_errors/stage1/obj/comptime_continue_inside_runtime_while_bool.zig +++ /dev/null @@ -1,15 +0,0 @@ -export fn entry() void { - var p: usize = undefined; - comptime var q = true; - outer: inline while (q) { - while (p == 11) continue :outer; - q = false; - } -} - -// error -// backend=stage1 -// target=native -// -// tmp.zig:5:25: error: comptime control flow inside runtime block -// tmp.zig:5:9: note: runtime block created here diff --git a/test/cases/compile_errors/stage1/obj/comptime_continue_inside_runtime_while_error.zig b/test/cases/compile_errors/stage1/obj/comptime_continue_inside_runtime_while_error.zig deleted file mode 100644 index 818455c354..0000000000 --- a/test/cases/compile_errors/stage1/obj/comptime_continue_inside_runtime_while_error.zig +++ /dev/null @@ -1,17 +0,0 @@ -export fn entry() void { - var p: anyerror!usize = undefined; - comptime var q = true; - outer: inline while (q) { - while (p) |_| { - continue :outer; - } else |_| {} - q = false; - } -} - -// error -// backend=stage1 -// target=native -// -// tmp.zig:6:13: error: comptime control flow inside runtime block -// tmp.zig:5:9: note: runtime block created here diff --git a/test/cases/compile_errors/stage1/obj/comptime_continue_inside_runtime_while_optional.zig b/test/cases/compile_errors/stage1/obj/comptime_continue_inside_runtime_while_optional.zig deleted file mode 100644 index ed22cc2cac..0000000000 --- a/test/cases/compile_errors/stage1/obj/comptime_continue_inside_runtime_while_optional.zig +++ /dev/null @@ -1,15 +0,0 @@ -export fn entry() void { - var p: ?usize = undefined; - comptime var q = true; - outer: inline while (q) { - while (p) |_| continue :outer; - q = false; - } -} - -// error -// backend=stage1 -// target=native -// -// tmp.zig:5:23: error: comptime control flow inside runtime block -// tmp.zig:5:9: note: runtime block created here -- cgit v1.2.3 From fdaf9c40d6a351477aacb1af27871f3de12d485e Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Thu, 28 Jul 2022 14:58:20 +0300 Subject: stage2: handle tuple init edge cases --- src/AstGen.zig | 5 +- src/Module.zig | 19 ++++ src/Sema.zig | 126 +++++++++++++++++---- src/Zir.zig | 7 +- src/print_zir.zig | 14 ++- .../cases/compile_errors/tuple_init_edge_cases.zig | 44 +++++++ .../wrong_size_to_an_array_literal.zig | 2 +- 7 files changed, 192 insertions(+), 25 deletions(-) create mode 100644 test/cases/compile_errors/tuple_init_edge_cases.zig (limited to 'test/cases') diff --git a/src/AstGen.zig b/src/AstGen.zig index 0078057eef..b6a7450f3a 100644 --- a/src/AstGen.zig +++ b/src/AstGen.zig @@ -1349,7 +1349,10 @@ fn arrayInitExpr( } } const array_type_inst = try typeExpr(gz, scope, array_init.ast.type_expr); - _ = try gz.addUnNode(.validate_array_init_ty, array_type_inst, array_init.ast.type_expr); + _ = try gz.addPlNode(.validate_array_init_ty, node, Zir.Inst.ArrayInit{ + .ty = array_type_inst, + .init_count = @intCast(u32, array_init.ast.elements.len), + }); break :inst .{ .array = array_type_inst, .elem = .none, diff --git a/src/Module.zig b/src/Module.zig index deff4620b9..4ac2775515 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -2728,6 +2728,21 @@ pub const SrcLoc = struct { }; return nodeToSpan(tree, full.ast.value_expr); }, + .node_offset_init_ty => |node_off| { + const tree = try src_loc.file_scope.getTree(gpa); + const node_tags = tree.nodes.items(.tag); + const parent_node = src_loc.declRelativeToNodeIndex(node_off); + + var buf: [2]Ast.Node.Index = undefined; + const full: Ast.full.ArrayInit = switch (node_tags[parent_node]) { + .array_init_one, .array_init_one_comma => tree.arrayInitOne(buf[0..1], parent_node), + .array_init_dot_two, .array_init_dot_two_comma => tree.arrayInitDotTwo(&buf, parent_node), + .array_init_dot, .array_init_dot_comma => tree.arrayInitDot(parent_node), + .array_init, .array_init_comma => tree.arrayInit(parent_node), + else => unreachable, + }; + return nodeToSpan(tree, full.ast.type_expr); + }, } } @@ -3048,6 +3063,9 @@ pub const LazySrcLoc = union(enum) { /// The source location points to the default value of a field. /// The Decl is determined contextually. node_offset_field_default: i32, + /// The source location points to the type of an array or struct initializer. + /// The Decl is determined contextually. + node_offset_init_ty: i32, pub const nodeOffset = if (TracedOffset.want_tracing) nodeOffsetDebug else nodeOffsetRelease; @@ -3126,6 +3144,7 @@ pub const LazySrcLoc = union(enum) { .node_offset_ptr_hostsize, .node_offset_container_tag, .node_offset_field_default, + .node_offset_init_ty, => .{ .file_scope = decl.getFileScope(), .parent_decl_node = decl.src_node, diff --git a/src/Sema.zig b/src/Sema.zig index 5a70679b8d..74c8f0b48d 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -3493,19 +3493,43 @@ fn validateArrayInitTy( block: *Block, inst: Zir.Inst.Index, ) CompileError!void { - const inst_data = sema.code.instructions.items(.data)[inst].un_node; + const inst_data = sema.code.instructions.items(.data)[inst].pl_node; const src = inst_data.src(); - const ty = try sema.resolveType(block, src, inst_data.operand); + const ty_src: LazySrcLoc = .{ .node_offset_init_ty = inst_data.src_node }; + const extra = sema.code.extraData(Zir.Inst.ArrayInit, inst_data.payload_index).data; + const ty = try sema.resolveType(block, ty_src, extra.ty); switch (ty.zigTypeTag()) { - .Array, .Vector => return, + .Array => { + const array_len = ty.arrayLen(); + if (extra.init_count != array_len) { + return sema.fail(block, src, "expected {d} array elements; found {d}", .{ + array_len, extra.init_count, + }); + } + return; + }, + .Vector => { + const array_len = ty.arrayLen(); + if (extra.init_count != array_len) { + return sema.fail(block, src, "expected {d} vector elements; found {d}", .{ + array_len, extra.init_count, + }); + } + return; + }, .Struct => if (ty.isTuple()) { - // TODO validate element count + const array_len = ty.arrayLen(); + if (extra.init_count > array_len) { + return sema.fail(block, src, "expected at most {d} tuple fields; found {d}", .{ + array_len, extra.init_count, + }); + } return; }, else => {}, } - return sema.failWithArrayInitNotSupported(block, src, ty); + return sema.failWithArrayInitNotSupported(block, ty_src, ty); } fn validateStructInitTy( @@ -3741,6 +3765,15 @@ fn validateStructInit( const default_val = struct_ty.structFieldDefaultValue(i); if (default_val.tag() == .unreachable_value) { + if (struct_ty.isTuple()) { + const template = "missing tuple field with index {d}"; + if (root_msg) |msg| { + try sema.errNote(block, init_src, msg, template, .{i}); + } else { + root_msg = try sema.errMsg(block, init_src, template, .{i}); + } + continue; + } const field_name = struct_ty.structFieldName(i); const template = "missing struct field: {s}"; const args = .{field_name}; @@ -3753,7 +3786,10 @@ fn validateStructInit( } const field_src = init_src; // TODO better source location - const default_field_ptr = try sema.structFieldPtrByIndex(block, init_src, struct_ptr, @intCast(u32, i), field_src, struct_ty, true); + const default_field_ptr = if (struct_ty.isTuple()) + try sema.tupleFieldPtr(block, init_src, struct_ptr, field_src, @intCast(u32, i), true) + else + try sema.structFieldPtrByIndex(block, init_src, struct_ptr, @intCast(u32, i), field_src, struct_ty, true); const field_ty = sema.typeOf(default_field_ptr).childType(); const init = try sema.addConstant(field_ty, default_val); try sema.storePtr2(block, init_src, default_field_ptr, init_src, init, field_src, .store); @@ -3868,6 +3904,15 @@ fn validateStructInit( const default_val = struct_ty.structFieldDefaultValue(i); if (default_val.tag() == .unreachable_value) { + if (struct_ty.isTuple()) { + const template = "missing tuple field with index {d}"; + if (root_msg) |msg| { + try sema.errNote(block, init_src, msg, template, .{i}); + } else { + root_msg = try sema.errMsg(block, init_src, template, .{i}); + } + continue; + } const field_name = struct_ty.structFieldName(i); const template = "missing struct field: {s}"; const args = .{field_name}; @@ -3911,7 +3956,10 @@ fn validateStructInit( if (field_ptr != 0) continue; const field_src = init_src; // TODO better source location - const default_field_ptr = try sema.structFieldPtrByIndex(block, init_src, struct_ptr, @intCast(u32, i), field_src, struct_ty, true); + const default_field_ptr = if (struct_ty.isTuple()) + try sema.tupleFieldPtr(block, init_src, struct_ptr, field_src, @intCast(u32, i), true) + else + try sema.structFieldPtrByIndex(block, init_src, struct_ptr, @intCast(u32, i), field_src, struct_ty, true); const field_ty = sema.typeOf(default_field_ptr).childType(); const init = try sema.addConstant(field_ty, field_values[i]); try sema.storePtr2(block, init_src, default_field_ptr, init_src, init, field_src, .store); @@ -3934,15 +3982,24 @@ fn zirValidateArrayInit( const array_ty = sema.typeOf(array_ptr).childType(); const array_len = array_ty.arrayLen(); - if (instrs.len != array_len) { - if (array_ty.zigTypeTag() == .Array) { - return sema.fail(block, init_src, "expected {d} array elements; found {d}", .{ - array_len, instrs.len, - }); - } else { - return sema.fail(block, init_src, "expected {d} vector elements; found {d}", .{ - array_len, instrs.len, - }); + if (instrs.len != array_len and array_ty.isTuple()) { + const struct_obj = array_ty.castTag(.tuple).?.data; + var root_msg: ?*Module.ErrorMsg = null; + for (struct_obj.values) |default_val, i| { + if (i < instrs.len) continue; + + if (default_val.tag() == .unreachable_value) { + const template = "missing tuple field with index {d}"; + if (root_msg) |msg| { + try sema.errNote(block, init_src, msg, template, .{i}); + } else { + root_msg = try sema.errMsg(block, init_src, template, .{i}); + } + } + } + + if (root_msg) |msg| { + return sema.failWithOwnedErrorMsg(block, msg); } } @@ -3995,10 +4052,17 @@ fn zirValidateArrayInit( } first_block_index = @minimum(first_block_index, block_index); - // Array has one possible value, so value is always comptime-known - if (opt_opv) |opv| { - element_vals[i] = opv; - continue; + if (array_ty.isTuple()) { + if (array_ty.structFieldValueComptime(i)) |opv| { + element_vals[i] = opv; + continue; + } + } else { + // Array has one possible value, so value is always comptime-known + if (opt_opv) |opv| { + element_vals[i] = opv; + continue; + } } // If the next instructon is a store with a comptime operand, this element @@ -14710,6 +14774,22 @@ fn finishStructInit( field_inits[i] = try sema.addConstant(struct_obj.types[i], default_val); } } + } else if (struct_ty.isTuple()) { + const struct_obj = struct_ty.castTag(.tuple).?.data; + for (struct_obj.values) |default_val, i| { + if (field_inits[i] != .none) continue; + + if (default_val.tag() == .unreachable_value) { + const template = "missing tuple field with index {d}"; + if (root_msg) |msg| { + try sema.errNote(block, init_src, msg, template, .{i}); + } else { + root_msg = try sema.errMsg(block, init_src, template, .{i}); + } + } else { + field_inits[i] = try sema.addConstant(struct_obj.types[i], default_val); + } + } } else { const struct_obj = struct_ty.castTag(.@"struct").?.data; for (struct_obj.fields.values()) |field, i| { @@ -20255,7 +20335,7 @@ fn tupleFieldVal( return tupleFieldValByIndex(sema, block, src, tuple_byval, field_index, tuple_ty); } -/// Don't forget to check for "len" before calling this. +/// Asserts that `field_name` is not "len". fn tupleFieldIndex( sema: *Sema, block: *Block, @@ -20263,8 +20343,12 @@ fn tupleFieldIndex( field_name: []const u8, field_name_src: LazySrcLoc, ) CompileError!u32 { + assert(!std.mem.eql(u8, field_name, "len")); if (std.fmt.parseUnsigned(u32, field_name, 10)) |field_index| { if (field_index < tuple_ty.structFieldCount()) return field_index; + return sema.fail(block, field_name_src, "index '{s}' out of bounds of tuple '{}'", .{ + field_name, tuple_ty.fmt(sema.mod), + }); } else |_| {} return sema.fail(block, field_name_src, "no field named '{s}' in tuple '{}'", .{ diff --git a/src/Zir.zig b/src/Zir.zig index 4540032605..ccd677df0b 100644 --- a/src/Zir.zig +++ b/src/Zir.zig @@ -1709,7 +1709,7 @@ pub const Inst = struct { .switch_capture_multi_ref = .switch_capture, .array_base_ptr = .un_node, .field_base_ptr = .un_node, - .validate_array_init_ty = .un_node, + .validate_array_init_ty = .pl_node, .validate_struct_init_ty = .un_node, .validate_struct_init = .pl_node, .validate_struct_init_comptime = .pl_node, @@ -3543,6 +3543,11 @@ pub const Inst = struct { line: u32, column: u32, }; + + pub const ArrayInit = struct { + ty: Ref, + init_count: u32, + }; }; pub const SpecialProng = enum { none, @"else", under }; diff --git a/src/print_zir.zig b/src/print_zir.zig index 7723446f1c..6e33154bbd 100644 --- a/src/print_zir.zig +++ b/src/print_zir.zig @@ -229,7 +229,6 @@ const Writer = struct { .switch_cond_ref, .array_base_ptr, .field_base_ptr, - .validate_array_init_ty, .validate_struct_init_ty, .make_ptr_const, .validate_deref, @@ -246,6 +245,7 @@ const Writer = struct { .bool_br_or, => try self.writeBoolBr(stream, inst), + .validate_array_init_ty => try self.writeValidateArrayInitTy(stream, inst), .array_type_sentinel => try self.writeArrayTypeSentinel(stream, inst), .param_type => try self.writeParamType(stream, inst), .ptr_type => try self.writePtrType(stream, inst), @@ -577,6 +577,18 @@ const Writer = struct { try self.writeSrc(stream, inst_data.src()); } + fn writeValidateArrayInitTy( + self: *Writer, + stream: anytype, + inst: Zir.Inst.Index, + ) (@TypeOf(stream).Error || error{OutOfMemory})!void { + const inst_data = self.code.instructions.items(.data)[inst].pl_node; + const extra = self.code.extraData(Zir.Inst.ArrayInit, inst_data.payload_index).data; + try self.writeInstRef(stream, extra.ty); + try stream.print(", {d}) ", .{extra.init_count}); + try self.writeSrc(stream, inst_data.src()); + } + fn writeArrayTypeSentinel( self: *Writer, stream: anytype, diff --git a/test/cases/compile_errors/tuple_init_edge_cases.zig b/test/cases/compile_errors/tuple_init_edge_cases.zig new file mode 100644 index 0000000000..32b52cdc1f --- /dev/null +++ b/test/cases/compile_errors/tuple_init_edge_cases.zig @@ -0,0 +1,44 @@ +pub export fn entry1() void { + const T = @TypeOf(.{ 123, 3 }); + var b = T{ .@"1" = 3 }; _ = b; + var c = T{ 123, 3 }; _ = c; + var d = T{}; _ = d; +} +pub export fn entry2() void { + var a: u32 = 2; + const T = @TypeOf(.{ 123, a }); + var b = T{ .@"1" = 3 }; _ = b; + var c = T{ 123, 3 }; _ = c; + var d = T{}; _ = d; +} +pub export fn entry3() void { + var a: u32 = 2; + const T = @TypeOf(.{ 123, a }); + var b = T{ .@"0" = 123 }; _ = b; +} +comptime { + var a: u32 = 2; + const T = @TypeOf(.{ 123, a }); + var b = T{ .@"0" = 123 }; _ = b; + var c = T{ 123, 2 }; _ = c; + var d = T{}; _ = d; +} +pub export fn entry4() void { + var a: u32 = 2; + const T = @TypeOf(.{ 123, a }); + var b = T{ 123, 4, 5 }; _ = b; +} +pub export fn entry5() void { + var a: u32 = 2; + const T = @TypeOf(.{ 123, a }); + var b = T{ .@"0" = 123, .@"2" = 123, .@"1" = 123 }; _ = b; +} + +// error +// backend=stage2 +// target=native +// +// :12:14: error: missing tuple field with index 1 +// :17:14: error: missing tuple field with index 1 +// :29:14: error: expected at most 2 tuple fields; found 3 +// :34:30: error: index '2' out of bounds of tuple 'tuple{comptime comptime_int = 123, u32}' diff --git a/test/cases/compile_errors/wrong_size_to_an_array_literal.zig b/test/cases/compile_errors/wrong_size_to_an_array_literal.zig index bb8b3c215c..a38d8d4d85 100644 --- a/test/cases/compile_errors/wrong_size_to_an_array_literal.zig +++ b/test/cases/compile_errors/wrong_size_to_an_array_literal.zig @@ -7,4 +7,4 @@ comptime { // backend=stage2 // target=native // -// :2:31: error: index 2 outside array of length 2 +// :2:24: error: expected 2 array elements; found 3 -- cgit v1.2.3 From daac39364ad94b5ae374f7391653789da3f578a8 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 28 Jul 2022 21:34:32 -0700 Subject: fix compile error test case note column number --- .../method_call_with_first_arg_type_wrong_container.zig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'test/cases') diff --git a/test/cases/compile_errors/method_call_with_first_arg_type_wrong_container.zig b/test/cases/compile_errors/method_call_with_first_arg_type_wrong_container.zig index 9e05a370f9..ad481a6158 100644 --- a/test/cases/compile_errors/method_call_with_first_arg_type_wrong_container.zig +++ b/test/cases/compile_errors/method_call_with_first_arg_type_wrong_container.zig @@ -3,14 +3,14 @@ pub const List = struct { allocator: *Allocator, pub fn init(allocator: *Allocator) List { - return List { + return List{ .len = 0, .allocator = allocator, }; } }; -pub var global_allocator = Allocator { +pub var global_allocator = Allocator{ .field = 1234, }; @@ -28,4 +28,4 @@ export fn foo() void { // target=native // // :23:6: error: no field or member function named 'init' in 'tmp.List' -// :1:14: note: struct declared here +// :1:18: note: struct declared here -- cgit v1.2.3 From 1b1c70ce381cc3c76517c846eafcd3425a40ce9c Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 28 Jul 2022 21:40:05 -0700 Subject: disable failing incremental compilation test case see #12288 now `zig build test-cases -Denable-llvm` passes locally for me. --- test/cases/llvm/shift_right_plus_left.0.zig | 12 ------------ test/cases/llvm/shift_right_plus_left.1.zig | 10 ---------- 2 files changed, 22 deletions(-) delete mode 100644 test/cases/llvm/shift_right_plus_left.0.zig delete mode 100644 test/cases/llvm/shift_right_plus_left.1.zig (limited to 'test/cases') diff --git a/test/cases/llvm/shift_right_plus_left.0.zig b/test/cases/llvm/shift_right_plus_left.0.zig deleted file mode 100644 index 23b733c493..0000000000 --- a/test/cases/llvm/shift_right_plus_left.0.zig +++ /dev/null @@ -1,12 +0,0 @@ -pub fn main() void { - var i: u32 = 16; - assert(i >> 1, 8); -} -fn assert(a: u32, b: u32) void { - if (a != b) unreachable; -} - -// run -// backend=llvm -// target=x86_64-linux,x86_64-macos -// diff --git a/test/cases/llvm/shift_right_plus_left.1.zig b/test/cases/llvm/shift_right_plus_left.1.zig deleted file mode 100644 index 994b67b9d0..0000000000 --- a/test/cases/llvm/shift_right_plus_left.1.zig +++ /dev/null @@ -1,10 +0,0 @@ -pub fn main() void { - var i: u32 = 16; - assert(i << 1, 32); -} -fn assert(a: u32, b: u32) void { - if (a != b) unreachable; -} - -// run -// -- cgit v1.2.3 From 17622b9db14cb1d8dd600b21f60c8a1041e5b0e1 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Fri, 29 Jul 2022 11:55:53 +0300 Subject: Sema: implement `@Type` for functions Closes #12280 --- src/Sema.zig | 194 +++++++++++++++++++-- src/value.zig | 13 ++ .../reify_type.Fn_with_is_generic_true.zig | 17 ++ ...Fn_with_is_var_args_true_and_non-C_callconv.zig | 17 ++ .../reify_type.Fn_with_return_type_null.zig | 17 ++ ...r_exhaustive_enum_with_non-integer_tag_type.zig | 18 ++ ...for_exhaustive_enum_with_undefined_tag_type.zig | 18 ++ ...y_type_for_exhaustive_enum_with_zero_fields.zig | 18 ++ ...type_for_tagged_union_with_extra_enum_field.zig | 36 ++++ ...ype_for_tagged_union_with_extra_union_field.zig | 35 ++++ .../reify_type_for_union_with_zero_fields.zig | 17 ++ .../reify_type_union_payload_is_undefined.zig | 10 ++ .../compile_errors/reify_type_with_Type.Int.zig | 15 ++ .../compile_errors/reify_type_with_undefined.zig | 20 +++ .../obj/reify_type.Fn_with_is_generic_true.zig | 17 -- ...Fn_with_is_var_args_true_and_non-C_callconv.zig | 17 -- .../obj/reify_type.Fn_with_return_type_null.zig | 17 -- ...ify_type.Pointer_with_invalid_address_space.zig | 18 -- ...r_exhaustive_enum_with_non-integer_tag_type.zig | 18 -- ...for_exhaustive_enum_with_undefined_tag_type.zig | 18 -- ...y_type_for_exhaustive_enum_with_zero_fields.zig | 18 -- ...type_for_tagged_union_with_extra_enum_field.zig | 34 ---- ...ype_for_tagged_union_with_extra_union_field.zig | 35 ---- .../obj/reify_type_for_union_with_zero_fields.zig | 17 -- .../obj/reify_type_union_payload_is_undefined.zig | 10 -- .../stage1/obj/reify_type_with_Type.Int.zig | 13 -- .../reify_type_with_non-constant_expression.zig | 11 -- .../stage1/obj/reify_type_with_undefined.zig | 20 --- ...ify_type.Pointer_with_invalid_address_space.zig | 18 ++ .../reify_type_with_non-constant_expression.zig | 11 ++ 30 files changed, 463 insertions(+), 274 deletions(-) create mode 100644 test/cases/compile_errors/reify_type.Fn_with_is_generic_true.zig create mode 100644 test/cases/compile_errors/reify_type.Fn_with_is_var_args_true_and_non-C_callconv.zig create mode 100644 test/cases/compile_errors/reify_type.Fn_with_return_type_null.zig create mode 100644 test/cases/compile_errors/reify_type_for_exhaustive_enum_with_non-integer_tag_type.zig create mode 100644 test/cases/compile_errors/reify_type_for_exhaustive_enum_with_undefined_tag_type.zig create mode 100644 test/cases/compile_errors/reify_type_for_exhaustive_enum_with_zero_fields.zig create mode 100644 test/cases/compile_errors/reify_type_for_tagged_union_with_extra_enum_field.zig create mode 100644 test/cases/compile_errors/reify_type_for_tagged_union_with_extra_union_field.zig create mode 100644 test/cases/compile_errors/reify_type_for_union_with_zero_fields.zig create mode 100644 test/cases/compile_errors/reify_type_union_payload_is_undefined.zig create mode 100644 test/cases/compile_errors/reify_type_with_Type.Int.zig create mode 100644 test/cases/compile_errors/reify_type_with_undefined.zig delete mode 100644 test/cases/compile_errors/stage1/obj/reify_type.Fn_with_is_generic_true.zig delete mode 100644 test/cases/compile_errors/stage1/obj/reify_type.Fn_with_is_var_args_true_and_non-C_callconv.zig delete mode 100644 test/cases/compile_errors/stage1/obj/reify_type.Fn_with_return_type_null.zig delete mode 100644 test/cases/compile_errors/stage1/obj/reify_type.Pointer_with_invalid_address_space.zig delete mode 100644 test/cases/compile_errors/stage1/obj/reify_type_for_exhaustive_enum_with_non-integer_tag_type.zig delete mode 100644 test/cases/compile_errors/stage1/obj/reify_type_for_exhaustive_enum_with_undefined_tag_type.zig delete mode 100644 test/cases/compile_errors/stage1/obj/reify_type_for_exhaustive_enum_with_zero_fields.zig delete mode 100644 test/cases/compile_errors/stage1/obj/reify_type_for_tagged_union_with_extra_enum_field.zig delete mode 100644 test/cases/compile_errors/stage1/obj/reify_type_for_tagged_union_with_extra_union_field.zig delete mode 100644 test/cases/compile_errors/stage1/obj/reify_type_for_union_with_zero_fields.zig delete mode 100644 test/cases/compile_errors/stage1/obj/reify_type_union_payload_is_undefined.zig delete mode 100644 test/cases/compile_errors/stage1/obj/reify_type_with_Type.Int.zig delete mode 100644 test/cases/compile_errors/stage1/obj/reify_type_with_non-constant_expression.zig delete mode 100644 test/cases/compile_errors/stage1/obj/reify_type_with_undefined.zig create mode 100644 test/cases/compile_errors/stage1/reify_type.Pointer_with_invalid_address_space.zig create mode 100644 test/cases/compile_errors/stage1/reify_type_with_non-constant_expression.zig (limited to 'test/cases') diff --git a/src/Sema.zig b/src/Sema.zig index 59b312e000..705fba9b92 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -15759,6 +15759,7 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I const tag_ty = type_info_ty.unionTagType().?; const target = mod.getTarget(); const tag_index = tag_ty.enumTagFieldIndex(union_val.tag, mod).?; + if (union_val.val.anyUndef()) return sema.failWithUseOfUndef(block, src); switch (@intToEnum(std.builtin.TypeId, tag_index)) { .Type => return Air.Inst.Ref.type_type, .Void => return Air.Inst.Ref.void_type, @@ -15828,7 +15829,10 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I const is_allowzero_val = struct_val[6]; const sentinel_val = struct_val[7]; - const abi_align = @intCast(u29, alignment_val.toUnsignedInt(target)); // TODO: Validate this value. + if (!try sema.intFitsInType(block, src, alignment_val, Type.u32, null)) { + return sema.fail(block, src, "alignment must fit in 'u32'", .{}); + } + const abi_align = @intCast(u29, alignment_val.toUnsignedInt(target)); var buffer: Value.ToTypeBuffer = undefined; const unresolved_elem_ty = child_val.toType(&buffer); @@ -15855,6 +15859,39 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I actual_sentinel = (try sema.pointerDeref(block, src, sentinel_ptr_val, ptr_ty)).?; } + if (elem_ty.zigTypeTag() == .NoReturn) { + return sema.fail(block, src, "pointer to noreturn not allowed", .{}); + } else if (elem_ty.zigTypeTag() == .Fn) { + if (ptr_size != .One) { + return sema.fail(block, src, "function pointers must be single pointers", .{}); + } + const fn_align = elem_ty.fnInfo().alignment; + if (abi_align != 0 and fn_align != 0 and + abi_align != fn_align) + { + return sema.fail(block, src, "function pointer alignment disagrees with function alignment", .{}); + } + } else if (ptr_size == .Many and elem_ty.zigTypeTag() == .Opaque) { + return sema.fail(block, src, "unknown-length pointer to opaque not allowed", .{}); + } else if (ptr_size == .C) { + if (!(try sema.validateExternType(elem_ty, .other))) { + const msg = msg: { + const msg = try sema.errMsg(block, src, "C pointers cannot point to non-C-ABI-compatible type '{}'", .{elem_ty.fmt(sema.mod)}); + errdefer msg.destroy(sema.gpa); + + const src_decl = sema.mod.declPtr(block.src_decl); + try sema.explainWhyTypeIsNotExtern(block, src, msg, src.toSrcLoc(src_decl), elem_ty, .other); + + try sema.addDeclaredHereNote(msg, elem_ty); + break :msg msg; + }; + return sema.failWithOwnedErrorMsg(block, msg); + } + if (elem_ty.zigTypeTag() == .Opaque) { + return sema.fail(block, src, "C pointers cannot point to opaque types", .{}); + } + } + const ty = try Type.ptr(sema.arena, mod, .{ .size = ptr_size, .mutable = !is_const_val.toBool(), @@ -15915,6 +15952,10 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I const error_set_ty = try error_set_val.toType(&buffer).copy(sema.arena); const payload_ty = try payload_val.toType(&buffer).copy(sema.arena); + if (error_set_ty.zigTypeTag() != .ErrorSet) { + return sema.fail(block, src, "Type.ErrorUnion.error_set must be an error set type", .{}); + } + const ty = try Type.Tag.error_union.create(sema.arena, .{ .error_set = error_set_ty, .payload = payload_ty, @@ -15928,7 +15969,7 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I const decl_index = slice_val.ptr.pointerDecl().?; try sema.ensureDeclAnalyzed(decl_index); const decl = mod.declPtr(decl_index); - const array_val = decl.val.castTag(.aggregate).?.data; + const array_val: []Value = if (decl.val.castTag(.aggregate)) |some| some.data else &.{}; var names: Module.ErrorSet.NameMap = .{}; try names.ensureUnusedCapacity(sema.arena, array_val.len); @@ -15940,7 +15981,10 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I const name_str = try name_val.toAllocatedBytes(Type.initTag(.const_slice_u8), sema.arena, sema.mod); const kv = try mod.getErrorValue(name_str); - names.putAssumeCapacityNoClobber(kv.key, {}); + const gop = names.getOrPutAssumeCapacity(kv.key); + if (gop.found_existing) { + return sema.fail(block, src, "duplicate error '{s}'", .{name_str}); + } } // names must be sorted @@ -16022,13 +16066,9 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I new_decl.owns_tv = true; errdefer mod.abortAnonDecl(new_decl_index); - // Enum tag type - var buffer: Value.ToTypeBuffer = undefined; - const int_tag_ty = try tag_type_val.toType(&buffer).copy(new_decl_arena_allocator); - enum_obj.* = .{ .owner_decl = new_decl_index, - .tag_ty = int_tag_ty, + .tag_ty = Type.@"null", .tag_ty_inferred = false, .fields = .{}, .values = .{}, @@ -16040,6 +16080,15 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I }, }; + // Enum tag type + var buffer: Value.ToTypeBuffer = undefined; + const int_tag_ty = try tag_type_val.toType(&buffer).copy(new_decl_arena_allocator); + + if (int_tag_ty.zigTypeTag() != .Int) { + return sema.fail(block, src, "Type.Enum.tag_type must be an integer type", .{}); + } + enum_obj.tag_ty = int_tag_ty; + // Fields const fields_len = try sema.usizeCast(block, src, fields_val.sliceLen(mod)); if (fields_len > 0) { @@ -16077,6 +16126,8 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I .mod = mod, }); } + } else { + return sema.fail(block, src, "enums must have at least one field", .{}); } try new_decl.finalizeNewArena(&new_decl_arena); @@ -16186,11 +16237,17 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I }; // Tag type + var tag_ty_field_names: ?Module.EnumFull.NameMap = null; var enum_field_names: ?*Module.EnumNumbered.NameMap = null; const fields_len = try sema.usizeCast(block, src, fields_val.sliceLen(mod)); if (tag_type_val.optionalValue()) |payload_val| { var buffer: Value.ToTypeBuffer = undefined; union_obj.tag_ty = try payload_val.toType(&buffer).copy(new_decl_arena_allocator); + + if (union_obj.tag_ty.zigTypeTag() != .Enum) { + return sema.fail(block, src, "Type.Union.tag_type must be an enum type", .{}); + } + tag_ty_field_names = try union_obj.tag_ty.enumFields().clone(sema.arena); } else { union_obj.tag_ty = try sema.generateUnionTagTypeSimple(block, fields_len, null); enum_field_names = &union_obj.tag_ty.castTag(.enum_simple).?.data.fields; @@ -16222,6 +16279,19 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I set.putAssumeCapacity(field_name, {}); } + if (tag_ty_field_names) |*names| { + const enum_has_field = names.orderedRemove(field_name); + if (!enum_has_field) { + const msg = msg: { + const msg = try sema.errMsg(block, src, "no field named '{s}' in enum '{}'", .{ field_name, union_obj.tag_ty.fmt(sema.mod) }); + errdefer msg.destroy(sema.gpa); + try sema.addDeclaredHereNote(msg, union_obj.tag_ty); + break :msg msg; + }; + return sema.failWithOwnedErrorMsg(block, msg); + } + } + const gop = union_obj.fields.getOrPutAssumeCapacity(field_name); if (gop.found_existing) { // TODO: better source location @@ -16234,12 +16304,108 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I .abi_align = @intCast(u32, alignment_val.toUnsignedInt(target)), }; } + } else { + return sema.fail(block, src, "unions must have at least one field", .{}); + } + + if (tag_ty_field_names) |names| { + if (names.count() > 0) { + const msg = msg: { + const msg = try sema.errMsg(block, src, "enum field(s) missing in union", .{}); + errdefer msg.destroy(sema.gpa); + + const enum_ty = union_obj.tag_ty; + for (names.keys()) |field_name| { + const field_index = enum_ty.enumFieldIndex(field_name).?; + try sema.addFieldErrNote(block, enum_ty, field_index, msg, "field '{s}' missing, declared here", .{field_name}); + } + try sema.addDeclaredHereNote(msg, union_obj.tag_ty); + break :msg msg; + }; + return sema.failWithOwnedErrorMsg(block, msg); + } } try new_decl.finalizeNewArena(&new_decl_arena); return sema.analyzeDeclVal(block, src, new_decl_index); }, - .Fn => return sema.fail(block, src, "TODO: Sema.zirReify for Fn", .{}), + .Fn => { + const struct_val = union_val.val.castTag(.aggregate).?.data; + // TODO use reflection instead of magic numbers here + // calling_convention: CallingConvention, + const cc = struct_val[0].toEnum(std.builtin.CallingConvention); + // alignment: comptime_int, + const alignment_val = struct_val[1]; + // is_generic: bool, + const is_generic = struct_val[2].toBool(); + // is_var_args: bool, + const is_var_args = struct_val[3].toBool(); + // return_type: ?type, + const return_type_val = struct_val[4]; + // args: []const Param, + const args_val = struct_val[5]; + + if (is_generic) { + return sema.fail(block, src, "Type.Fn.is_generic must be false for @Type", .{}); + } + + if (is_var_args and cc != .C) { + return sema.fail(block, src, "varargs functions must have C calling convention", .{}); + } + + const alignment = @intCast(u29, alignment_val.toUnsignedInt(target)); // TODO: Validate this value. + var buf: Value.ToTypeBuffer = undefined; + + const args: []Value = if (args_val.castTag(.aggregate)) |some| some.data else &.{}; + var param_types = try sema.arena.alloc(Type, args.len); + var comptime_params = try sema.arena.alloc(bool, args.len); + var noalias_bits: u32 = 0; + for (args) |arg, i| { + const arg_val = arg.castTag(.aggregate).?.data; + // TODO use reflection instead of magic numbers here + // is_generic: bool, + const arg_is_generic = arg_val[0].toBool(); + // is_noalias: bool, + const arg_is_noalias = arg_val[1].toBool(); + // arg_type: ?type, + const param_type_val = arg_val[2]; + + if (arg_is_generic) { + return sema.fail(block, src, "Type.Fn.Param.is_generic must be false for @Type", .{}); + } + + if (arg_is_noalias) { + noalias_bits = @as(u32, 1) << (std.math.cast(u5, i) orelse + return sema.fail(block, src, "this compiler implementation only supports 'noalias' on the first 32 parameters", .{})); + } + + const param_type = param_type_val.optionalValue() orelse + return sema.fail(block, src, "Type.Fn.Param.arg_type must be non-null for @Type", .{}); + + param_types[i] = try param_type.toType(&buf).copy(sema.arena); + } + + const return_type = return_type_val.optionalValue() orelse + return sema.fail(block, src, "Type.Fn.return_type must be non-null for @Type", .{}); + + var fn_info = Type.Payload.Function.Data{ + .param_types = param_types, + .comptime_params = comptime_params.ptr, + .noalias_bits = noalias_bits, + .return_type = try return_type.toType(&buf).copy(sema.arena), + .alignment = alignment, + .cc = cc, + .is_var_args = is_var_args, + .is_generic = false, + .align_is_generic = false, + .cc_is_generic = false, + .section_is_generic = false, + .addrspace_is_generic = false, + }; + + const ty = try Type.Tag.function.create(sema.arena, fn_info); + return sema.addType(ty); + }, .BoundFn => @panic("TODO delete BoundFn from the language"), .Frame => @panic("TODO implement https://github.com/ziglang/zig/issues/10710"), } @@ -16382,6 +16548,11 @@ fn reifyStruct( // alignment: comptime_int, const alignment_val = field_struct_val[4]; + if (!try sema.intFitsInType(block, src, alignment_val, Type.u32, null)) { + return sema.fail(block, src, "alignment must fit in 'u32'", .{}); + } + const abi_align = @intCast(u29, alignment_val.toUnsignedInt(target)); + const field_name = try name_val.toAllocatedBytes( Type.initTag(.const_slice_u8), new_decl_arena_allocator, @@ -16405,7 +16576,7 @@ fn reifyStruct( var buffer: Value.ToTypeBuffer = undefined; gop.value_ptr.* = .{ .ty = try field_type_val.toType(&buffer).copy(new_decl_arena_allocator), - .abi_align = @intCast(u32, alignment_val.toUnsignedInt(target)), + .abi_align = abi_align, .default_val = default_val, .is_comptime = is_comptime_val.toBool(), .offset = undefined, @@ -27314,7 +27485,8 @@ fn enumFieldSrcLoc( .container_decl_arg_trailing, => tree.containerDeclArg(enum_node), - else => unreachable, + // Container was constructed with `@Type`. + else => return LazySrcLoc.nodeOffset(node_offset), }; var it_index: usize = 0; for (container_decl.ast.members) |member_node| { diff --git a/src/value.zig b/src/value.zig index 0d0be76542..3f3a2df4c3 100644 --- a/src/value.zig +++ b/src/value.zig @@ -2766,6 +2766,19 @@ pub const Value = extern union { return self.isUndef(); } + /// Returns true if any value contained in `self` is undefined. + /// TODO: check for cases such as array that is not marked undef but all the element + /// values are marked undef, or struct that is not marked undef but all fields are marked + /// undef, etc. + pub fn anyUndef(self: Value) bool { + if (self.castTag(.aggregate)) |aggregate| { + for (aggregate.data) |val| { + if (val.anyUndef()) return true; + } + } + return self.isUndef(); + } + /// Asserts the value is not undefined and not unreachable. /// Integer value 0 is considered null because of C pointers. pub fn isNull(self: Value) bool { diff --git a/test/cases/compile_errors/reify_type.Fn_with_is_generic_true.zig b/test/cases/compile_errors/reify_type.Fn_with_is_generic_true.zig new file mode 100644 index 0000000000..cf80c9f4ba --- /dev/null +++ b/test/cases/compile_errors/reify_type.Fn_with_is_generic_true.zig @@ -0,0 +1,17 @@ +const Foo = @Type(.{ + .Fn = .{ + .calling_convention = .Unspecified, + .alignment = 0, + .is_generic = true, + .is_var_args = false, + .return_type = u0, + .args = &.{}, + }, +}); +comptime { _ = Foo; } + +// error +// backend=stage2 +// target=native +// +// :1:13: error: Type.Fn.is_generic must be false for @Type diff --git a/test/cases/compile_errors/reify_type.Fn_with_is_var_args_true_and_non-C_callconv.zig b/test/cases/compile_errors/reify_type.Fn_with_is_var_args_true_and_non-C_callconv.zig new file mode 100644 index 0000000000..8328ee9b97 --- /dev/null +++ b/test/cases/compile_errors/reify_type.Fn_with_is_var_args_true_and_non-C_callconv.zig @@ -0,0 +1,17 @@ +const Foo = @Type(.{ + .Fn = .{ + .calling_convention = .Unspecified, + .alignment = 0, + .is_generic = false, + .is_var_args = true, + .return_type = u0, + .args = &.{}, + }, +}); +comptime { _ = Foo; } + +// error +// backend=stage2 +// target=native +// +// :1:13: error: varargs functions must have C calling convention diff --git a/test/cases/compile_errors/reify_type.Fn_with_return_type_null.zig b/test/cases/compile_errors/reify_type.Fn_with_return_type_null.zig new file mode 100644 index 0000000000..f6587dcd7e --- /dev/null +++ b/test/cases/compile_errors/reify_type.Fn_with_return_type_null.zig @@ -0,0 +1,17 @@ +const Foo = @Type(.{ + .Fn = .{ + .calling_convention = .Unspecified, + .alignment = 0, + .is_generic = false, + .is_var_args = false, + .return_type = null, + .args = &.{}, + }, +}); +comptime { _ = Foo; } + +// error +// backend=stage2 +// target=native +// +// :1:13: error: Type.Fn.return_type must be non-null for @Type diff --git a/test/cases/compile_errors/reify_type_for_exhaustive_enum_with_non-integer_tag_type.zig b/test/cases/compile_errors/reify_type_for_exhaustive_enum_with_non-integer_tag_type.zig new file mode 100644 index 0000000000..e72b783d83 --- /dev/null +++ b/test/cases/compile_errors/reify_type_for_exhaustive_enum_with_non-integer_tag_type.zig @@ -0,0 +1,18 @@ +const Tag = @Type(.{ + .Enum = .{ + .layout = .Auto, + .tag_type = bool, + .fields = &.{}, + .decls = &.{}, + .is_exhaustive = false, + }, +}); +export fn entry() void { + _ = @intToEnum(Tag, 0); +} + +// error +// backend=stage2 +// target=native +// +// :1:13: error: Type.Enum.tag_type must be an integer type diff --git a/test/cases/compile_errors/reify_type_for_exhaustive_enum_with_undefined_tag_type.zig b/test/cases/compile_errors/reify_type_for_exhaustive_enum_with_undefined_tag_type.zig new file mode 100644 index 0000000000..1c237a17bd --- /dev/null +++ b/test/cases/compile_errors/reify_type_for_exhaustive_enum_with_undefined_tag_type.zig @@ -0,0 +1,18 @@ +const Tag = @Type(.{ + .Enum = .{ + .layout = .Auto, + .tag_type = undefined, + .fields = &.{}, + .decls = &.{}, + .is_exhaustive = false, + }, +}); +export fn entry() void { + _ = @intToEnum(Tag, 0); +} + +// error +// backend=stage2 +// target=native +// +// :1:13: error: use of undefined value here causes undefined behavior diff --git a/test/cases/compile_errors/reify_type_for_exhaustive_enum_with_zero_fields.zig b/test/cases/compile_errors/reify_type_for_exhaustive_enum_with_zero_fields.zig new file mode 100644 index 0000000000..44876e938a --- /dev/null +++ b/test/cases/compile_errors/reify_type_for_exhaustive_enum_with_zero_fields.zig @@ -0,0 +1,18 @@ +const Tag = @Type(.{ + .Enum = .{ + .layout = .Auto, + .tag_type = u1, + .fields = &.{}, + .decls = &.{}, + .is_exhaustive = true, + }, +}); +export fn entry() void { + _ = @intToEnum(Tag, 0); +} + +// error +// backend=stage2 +// target=native +// +// :1:13: error: enums must have at least one field diff --git a/test/cases/compile_errors/reify_type_for_tagged_union_with_extra_enum_field.zig b/test/cases/compile_errors/reify_type_for_tagged_union_with_extra_enum_field.zig new file mode 100644 index 0000000000..ccd0000494 --- /dev/null +++ b/test/cases/compile_errors/reify_type_for_tagged_union_with_extra_enum_field.zig @@ -0,0 +1,36 @@ +const Tag = @Type(.{ + .Enum = .{ + .layout = .Auto, + .tag_type = u2, + .fields = &.{ + .{ .name = "signed", .value = 0 }, + .{ .name = "unsigned", .value = 1 }, + .{ .name = "arst", .value = 2 }, + }, + .decls = &.{}, + .is_exhaustive = true, + }, +}); +const Tagged = @Type(.{ + .Union = .{ + .layout = .Auto, + .tag_type = Tag, + .fields = &.{ + .{ .name = "signed", .field_type = i32, .alignment = @alignOf(i32) }, + .{ .name = "unsigned", .field_type = u32, .alignment = @alignOf(u32) }, + }, + .decls = &.{}, + }, +}); +export fn entry() void { + var tagged = Tagged{ .signed = -1 }; + tagged = .{ .unsigned = 1 }; +} + +// error +// backend=stage2 +// target=native +// +// :14:16: error: enum field(s) missing in union +// :1:13: note: field 'arst' missing, declared here +// :1:13: note: enum declared here diff --git a/test/cases/compile_errors/reify_type_for_tagged_union_with_extra_union_field.zig b/test/cases/compile_errors/reify_type_for_tagged_union_with_extra_union_field.zig new file mode 100644 index 0000000000..414bf2ce5e --- /dev/null +++ b/test/cases/compile_errors/reify_type_for_tagged_union_with_extra_union_field.zig @@ -0,0 +1,35 @@ +const Tag = @Type(.{ + .Enum = .{ + .layout = .Auto, + .tag_type = u1, + .fields = &.{ + .{ .name = "signed", .value = 0 }, + .{ .name = "unsigned", .value = 1 }, + }, + .decls = &.{}, + .is_exhaustive = true, + }, +}); +const Tagged = @Type(.{ + .Union = .{ + .layout = .Auto, + .tag_type = Tag, + .fields = &.{ + .{ .name = "signed", .field_type = i32, .alignment = @alignOf(i32) }, + .{ .name = "unsigned", .field_type = u32, .alignment = @alignOf(u32) }, + .{ .name = "arst", .field_type = f32, .alignment = @alignOf(f32) }, + }, + .decls = &.{}, + }, +}); +export fn entry() void { + var tagged = Tagged{ .signed = -1 }; + tagged = .{ .unsigned = 1 }; +} + +// error +// backend=stage2 +// target=native +// +// :13:16: error: no field named 'arst' in enum 'tmp.Tag__enum_264' +// :1:13: note: enum declared here diff --git a/test/cases/compile_errors/reify_type_for_union_with_zero_fields.zig b/test/cases/compile_errors/reify_type_for_union_with_zero_fields.zig new file mode 100644 index 0000000000..0b4f395c81 --- /dev/null +++ b/test/cases/compile_errors/reify_type_for_union_with_zero_fields.zig @@ -0,0 +1,17 @@ +const Untagged = @Type(.{ + .Union = .{ + .layout = .Auto, + .tag_type = null, + .fields = &.{}, + .decls = &.{}, + }, +}); +export fn entry() void { + _ = Untagged{}; +} + +// error +// backend=stage2 +// target=native +// +// :1:18: error: unions must have at least one field diff --git a/test/cases/compile_errors/reify_type_union_payload_is_undefined.zig b/test/cases/compile_errors/reify_type_union_payload_is_undefined.zig new file mode 100644 index 0000000000..410bb92658 --- /dev/null +++ b/test/cases/compile_errors/reify_type_union_payload_is_undefined.zig @@ -0,0 +1,10 @@ +const Foo = @Type(.{ + .Struct = undefined, +}); +comptime { _ = Foo; } + +// error +// backend=stage2 +// target=native +// +// :1:13: error: use of undefined value here causes undefined behavior diff --git a/test/cases/compile_errors/reify_type_with_Type.Int.zig b/test/cases/compile_errors/reify_type_with_Type.Int.zig new file mode 100644 index 0000000000..bd98912a03 --- /dev/null +++ b/test/cases/compile_errors/reify_type_with_Type.Int.zig @@ -0,0 +1,15 @@ +const builtin = @import("std").builtin; +export fn entry() void { + _ = @Type(builtin.Type.Int{ + .signedness = .signed, + .bits = 8, + }); +} + +// error +// backend=stage2 +// target=native +// +// :3:31: error: expected type 'builtin.Type', found 'builtin.Type.Int' +// :?:?: note: struct declared here +// :?:?: note: union declared here diff --git a/test/cases/compile_errors/reify_type_with_undefined.zig b/test/cases/compile_errors/reify_type_with_undefined.zig new file mode 100644 index 0000000000..e5753fa420 --- /dev/null +++ b/test/cases/compile_errors/reify_type_with_undefined.zig @@ -0,0 +1,20 @@ +comptime { + _ = @Type(.{ .Array = .{ .len = 0, .child = u8, .sentinel = undefined } }); +} +comptime { + _ = @Type(.{ + .Struct = .{ + .fields = undefined, + .decls = undefined, + .is_tuple = false, + .layout = .Auto, + }, + }); +} + +// error +// backend=stage2 +// target=native +// +// :2:9: error: use of undefined value here causes undefined behavior +// :5:9: error: use of undefined value here causes undefined behavior diff --git a/test/cases/compile_errors/stage1/obj/reify_type.Fn_with_is_generic_true.zig b/test/cases/compile_errors/stage1/obj/reify_type.Fn_with_is_generic_true.zig deleted file mode 100644 index f2849b5eb4..0000000000 --- a/test/cases/compile_errors/stage1/obj/reify_type.Fn_with_is_generic_true.zig +++ /dev/null @@ -1,17 +0,0 @@ -const Foo = @Type(.{ - .Fn = .{ - .calling_convention = .Unspecified, - .alignment = 0, - .is_generic = true, - .is_var_args = false, - .return_type = u0, - .args = &.{}, - }, -}); -comptime { _ = Foo; } - -// error -// backend=stage1 -// target=native -// -// tmp.zig:1:20: error: Type.Fn.is_generic must be false for @Type diff --git a/test/cases/compile_errors/stage1/obj/reify_type.Fn_with_is_var_args_true_and_non-C_callconv.zig b/test/cases/compile_errors/stage1/obj/reify_type.Fn_with_is_var_args_true_and_non-C_callconv.zig deleted file mode 100644 index 4d449e9eb9..0000000000 --- a/test/cases/compile_errors/stage1/obj/reify_type.Fn_with_is_var_args_true_and_non-C_callconv.zig +++ /dev/null @@ -1,17 +0,0 @@ -const Foo = @Type(.{ - .Fn = .{ - .calling_convention = .Unspecified, - .alignment = 0, - .is_generic = false, - .is_var_args = true, - .return_type = u0, - .args = &.{}, - }, -}); -comptime { _ = Foo; } - -// error -// backend=stage1 -// target=native -// -// tmp.zig:1:20: error: varargs functions must have C calling convention diff --git a/test/cases/compile_errors/stage1/obj/reify_type.Fn_with_return_type_null.zig b/test/cases/compile_errors/stage1/obj/reify_type.Fn_with_return_type_null.zig deleted file mode 100644 index 98cbc37d41..0000000000 --- a/test/cases/compile_errors/stage1/obj/reify_type.Fn_with_return_type_null.zig +++ /dev/null @@ -1,17 +0,0 @@ -const Foo = @Type(.{ - .Fn = .{ - .calling_convention = .Unspecified, - .alignment = 0, - .is_generic = false, - .is_var_args = false, - .return_type = null, - .args = &.{}, - }, -}); -comptime { _ = Foo; } - -// error -// backend=stage1 -// target=native -// -// tmp.zig:1:20: error: Type.Fn.return_type must be non-null for @Type diff --git a/test/cases/compile_errors/stage1/obj/reify_type.Pointer_with_invalid_address_space.zig b/test/cases/compile_errors/stage1/obj/reify_type.Pointer_with_invalid_address_space.zig deleted file mode 100644 index 1ca97ce250..0000000000 --- a/test/cases/compile_errors/stage1/obj/reify_type.Pointer_with_invalid_address_space.zig +++ /dev/null @@ -1,18 +0,0 @@ -export fn entry() void { - _ = @Type(.{ .Pointer = .{ - .size = .One, - .is_const = false, - .is_volatile = false, - .alignment = 1, - .address_space = .gs, - .child = u8, - .is_allowzero = false, - .sentinel = null, - }}); -} - -// error -// backend=stage1 -// target=native -// -// tmp.zig:2:16: error: address space 'gs' not available in stage 1 compiler, must be .generic diff --git a/test/cases/compile_errors/stage1/obj/reify_type_for_exhaustive_enum_with_non-integer_tag_type.zig b/test/cases/compile_errors/stage1/obj/reify_type_for_exhaustive_enum_with_non-integer_tag_type.zig deleted file mode 100644 index 56d05578be..0000000000 --- a/test/cases/compile_errors/stage1/obj/reify_type_for_exhaustive_enum_with_non-integer_tag_type.zig +++ /dev/null @@ -1,18 +0,0 @@ -const Tag = @Type(.{ - .Enum = .{ - .layout = .Auto, - .tag_type = bool, - .fields = &.{}, - .decls = &.{}, - .is_exhaustive = false, - }, -}); -export fn entry() void { - _ = @intToEnum(Tag, 0); -} - -// error -// backend=stage1 -// target=native -// -// tmp.zig:1:20: error: Type.Enum.tag_type must be an integer type, not 'bool' diff --git a/test/cases/compile_errors/stage1/obj/reify_type_for_exhaustive_enum_with_undefined_tag_type.zig b/test/cases/compile_errors/stage1/obj/reify_type_for_exhaustive_enum_with_undefined_tag_type.zig deleted file mode 100644 index e6454d2ee5..0000000000 --- a/test/cases/compile_errors/stage1/obj/reify_type_for_exhaustive_enum_with_undefined_tag_type.zig +++ /dev/null @@ -1,18 +0,0 @@ -const Tag = @Type(.{ - .Enum = .{ - .layout = .Auto, - .tag_type = undefined, - .fields = &.{}, - .decls = &.{}, - .is_exhaustive = false, - }, -}); -export fn entry() void { - _ = @intToEnum(Tag, 0); -} - -// error -// backend=stage1 -// target=native -// -// tmp.zig:1:20: error: use of undefined value here causes undefined behavior diff --git a/test/cases/compile_errors/stage1/obj/reify_type_for_exhaustive_enum_with_zero_fields.zig b/test/cases/compile_errors/stage1/obj/reify_type_for_exhaustive_enum_with_zero_fields.zig deleted file mode 100644 index d3ce70c1b0..0000000000 --- a/test/cases/compile_errors/stage1/obj/reify_type_for_exhaustive_enum_with_zero_fields.zig +++ /dev/null @@ -1,18 +0,0 @@ -const Tag = @Type(.{ - .Enum = .{ - .layout = .Auto, - .tag_type = u1, - .fields = &.{}, - .decls = &.{}, - .is_exhaustive = true, - }, -}); -export fn entry() void { - _ = @intToEnum(Tag, 0); -} - -// error -// backend=stage1 -// target=native -// -// tmp.zig:1:20: error: enums must have 1 or more fields diff --git a/test/cases/compile_errors/stage1/obj/reify_type_for_tagged_union_with_extra_enum_field.zig b/test/cases/compile_errors/stage1/obj/reify_type_for_tagged_union_with_extra_enum_field.zig deleted file mode 100644 index 0c56cb91ea..0000000000 --- a/test/cases/compile_errors/stage1/obj/reify_type_for_tagged_union_with_extra_enum_field.zig +++ /dev/null @@ -1,34 +0,0 @@ -const Tag = @Type(.{ - .Enum = .{ - .layout = .Auto, - .tag_type = u2, - .fields = &.{ - .{ .name = "signed", .value = 0 }, - .{ .name = "unsigned", .value = 1 }, - .{ .name = "arst", .value = 2 }, - }, - .decls = &.{}, - .is_exhaustive = true, - }, -}); -const Tagged = @Type(.{ - .Union = .{ - .layout = .Auto, - .tag_type = Tag, - .fields = &.{ - .{ .name = "signed", .field_type = i32, .alignment = @alignOf(i32) }, - .{ .name = "unsigned", .field_type = u32, .alignment = @alignOf(u32) }, - }, - .decls = &.{}, - }, -}); -export fn entry() void { - var tagged = Tagged{ .signed = -1 }; - tagged = .{ .unsigned = 1 }; -} - -// error -// backend=stage1 -// target=native -// -// tmp.zig:14:23: error: enum field missing: 'arst' diff --git a/test/cases/compile_errors/stage1/obj/reify_type_for_tagged_union_with_extra_union_field.zig b/test/cases/compile_errors/stage1/obj/reify_type_for_tagged_union_with_extra_union_field.zig deleted file mode 100644 index 63cf1f178e..0000000000 --- a/test/cases/compile_errors/stage1/obj/reify_type_for_tagged_union_with_extra_union_field.zig +++ /dev/null @@ -1,35 +0,0 @@ -const Tag = @Type(.{ - .Enum = .{ - .layout = .Auto, - .tag_type = u1, - .fields = &.{ - .{ .name = "signed", .value = 0 }, - .{ .name = "unsigned", .value = 1 }, - }, - .decls = &.{}, - .is_exhaustive = true, - }, -}); -const Tagged = @Type(.{ - .Union = .{ - .layout = .Auto, - .tag_type = Tag, - .fields = &.{ - .{ .name = "signed", .field_type = i32, .alignment = @alignOf(i32) }, - .{ .name = "unsigned", .field_type = u32, .alignment = @alignOf(u32) }, - .{ .name = "arst", .field_type = f32, .alignment = @alignOf(f32) }, - }, - .decls = &.{}, - }, -}); -export fn entry() void { - var tagged = Tagged{ .signed = -1 }; - tagged = .{ .unsigned = 1 }; -} - -// error -// backend=stage1 -// target=native -// -// tmp.zig:13:23: error: enum field not found: 'arst' -// tmp.zig:1:20: note: enum declared here diff --git a/test/cases/compile_errors/stage1/obj/reify_type_for_union_with_zero_fields.zig b/test/cases/compile_errors/stage1/obj/reify_type_for_union_with_zero_fields.zig deleted file mode 100644 index 578f902697..0000000000 --- a/test/cases/compile_errors/stage1/obj/reify_type_for_union_with_zero_fields.zig +++ /dev/null @@ -1,17 +0,0 @@ -const Untagged = @Type(.{ - .Union = .{ - .layout = .Auto, - .tag_type = null, - .fields = &.{}, - .decls = &.{}, - }, -}); -export fn entry() void { - _ = Untagged{}; -} - -// error -// backend=stage1 -// target=native -// -// tmp.zig:1:25: error: unions must have 1 or more fields diff --git a/test/cases/compile_errors/stage1/obj/reify_type_union_payload_is_undefined.zig b/test/cases/compile_errors/stage1/obj/reify_type_union_payload_is_undefined.zig deleted file mode 100644 index 47be31c711..0000000000 --- a/test/cases/compile_errors/stage1/obj/reify_type_union_payload_is_undefined.zig +++ /dev/null @@ -1,10 +0,0 @@ -const Foo = @Type(.{ - .Struct = undefined, -}); -comptime { _ = Foo; } - -// error -// backend=stage1 -// target=native -// -// tmp.zig:1:20: error: use of undefined value here causes undefined behavior diff --git a/test/cases/compile_errors/stage1/obj/reify_type_with_Type.Int.zig b/test/cases/compile_errors/stage1/obj/reify_type_with_Type.Int.zig deleted file mode 100644 index 116bd86e0f..0000000000 --- a/test/cases/compile_errors/stage1/obj/reify_type_with_Type.Int.zig +++ /dev/null @@ -1,13 +0,0 @@ -const builtin = @import("std").builtin; -export fn entry() void { - _ = @Type(builtin.Type.Int{ - .signedness = .signed, - .bits = 8, - }); -} - -// error -// backend=stage1 -// target=native -// -// tmp.zig:3:31: error: expected type 'std.builtin.Type', found 'std.builtin.Type.Int' diff --git a/test/cases/compile_errors/stage1/obj/reify_type_with_non-constant_expression.zig b/test/cases/compile_errors/stage1/obj/reify_type_with_non-constant_expression.zig deleted file mode 100644 index 7eec6b395a..0000000000 --- a/test/cases/compile_errors/stage1/obj/reify_type_with_non-constant_expression.zig +++ /dev/null @@ -1,11 +0,0 @@ -const builtin = @import("std").builtin; -var globalTypeInfo : builtin.Type = undefined; -export fn entry() void { - _ = @Type(globalTypeInfo); -} - -// error -// backend=stage1 -// target=native -// -// tmp.zig:4:15: error: unable to evaluate constant expression diff --git a/test/cases/compile_errors/stage1/obj/reify_type_with_undefined.zig b/test/cases/compile_errors/stage1/obj/reify_type_with_undefined.zig deleted file mode 100644 index 1de93ccdf6..0000000000 --- a/test/cases/compile_errors/stage1/obj/reify_type_with_undefined.zig +++ /dev/null @@ -1,20 +0,0 @@ -comptime { - _ = @Type(.{ .Array = .{ .len = 0, .child = u8, .sentinel = undefined } }); -} -comptime { - _ = @Type(.{ - .Struct = .{ - .fields = undefined, - .decls = undefined, - .is_tuple = false, - .layout = .Auto, - }, - }); -} - -// error -// backend=stage1 -// target=native -// -// tmp.zig:2:16: error: use of undefined value here causes undefined behavior -// tmp.zig:5:16: error: use of undefined value here causes undefined behavior diff --git a/test/cases/compile_errors/stage1/reify_type.Pointer_with_invalid_address_space.zig b/test/cases/compile_errors/stage1/reify_type.Pointer_with_invalid_address_space.zig new file mode 100644 index 0000000000..1ca97ce250 --- /dev/null +++ b/test/cases/compile_errors/stage1/reify_type.Pointer_with_invalid_address_space.zig @@ -0,0 +1,18 @@ +export fn entry() void { + _ = @Type(.{ .Pointer = .{ + .size = .One, + .is_const = false, + .is_volatile = false, + .alignment = 1, + .address_space = .gs, + .child = u8, + .is_allowzero = false, + .sentinel = null, + }}); +} + +// error +// backend=stage1 +// target=native +// +// tmp.zig:2:16: error: address space 'gs' not available in stage 1 compiler, must be .generic diff --git a/test/cases/compile_errors/stage1/reify_type_with_non-constant_expression.zig b/test/cases/compile_errors/stage1/reify_type_with_non-constant_expression.zig new file mode 100644 index 0000000000..7eec6b395a --- /dev/null +++ b/test/cases/compile_errors/stage1/reify_type_with_non-constant_expression.zig @@ -0,0 +1,11 @@ +const builtin = @import("std").builtin; +var globalTypeInfo : builtin.Type = undefined; +export fn entry() void { + _ = @Type(globalTypeInfo); +} + +// error +// backend=stage1 +// target=native +// +// tmp.zig:4:15: error: unable to evaluate constant expression -- cgit v1.2.3 From 4758752e5d64a3e36086483de569188f62519bac Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Fri, 29 Jul 2022 12:30:27 +0300 Subject: Sema: implement coercion from tuples to tuples Closes #12242 --- src/Sema.zig | 107 ++++++++++++++++++++- test/behavior/tuple.zig | 15 +++ .../type_mismatch_with_tuple_concatenation.zig | 11 --- .../type_mismatch_with_tuple_concatenation.zig | 10 ++ 4 files changed, 130 insertions(+), 13 deletions(-) delete mode 100644 test/cases/compile_errors/stage1/test/type_mismatch_with_tuple_concatenation.zig create mode 100644 test/cases/compile_errors/type_mismatch_with_tuple_concatenation.zig (limited to 'test/cases') diff --git a/src/Sema.zig b/src/Sema.zig index 705fba9b92..31a0e41d95 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -24528,8 +24528,7 @@ fn coerceTupleToStruct( const struct_ty = try sema.resolveTypeFields(block, dest_ty_src, dest_ty); if (struct_ty.isTupleOrAnonStruct()) { - // NOTE remember to handle comptime fields - return sema.fail(block, dest_ty_src, "TODO: implement coercion from tuples to tuples", .{}); + return sema.coerceTupleToTuple(block, struct_ty, inst, inst_src); } const fields = struct_ty.structFields(); @@ -24612,6 +24611,110 @@ fn coerceTupleToStruct( ); } +fn coerceTupleToTuple( + sema: *Sema, + block: *Block, + tuple_ty: Type, + inst: Air.Inst.Ref, + inst_src: LazySrcLoc, +) !Air.Inst.Ref { + const field_count = tuple_ty.structFieldCount(); + const field_vals = try sema.arena.alloc(Value, field_count); + const field_refs = try sema.arena.alloc(Air.Inst.Ref, field_vals.len); + mem.set(Air.Inst.Ref, field_refs, .none); + + const inst_ty = sema.typeOf(inst); + const tuple = inst_ty.tupleFields(); + var runtime_src: ?LazySrcLoc = null; + for (tuple.types) |_, i_usize| { + const i = @intCast(u32, i_usize); + const field_src = inst_src; // TODO better source location + const field_name = if (inst_ty.castTag(.anon_struct)) |payload| + payload.data.names[i] + else + try std.fmt.allocPrint(sema.arena, "{d}", .{i}); + + if (mem.eql(u8, field_name, "len")) { + return sema.fail(block, field_src, "cannot assign to 'len' field of tuple", .{}); + } + + const field_index = try sema.tupleFieldIndex(block, tuple_ty, field_name, field_src); + + const field_ty = tuple_ty.structFieldType(i); + const default_val = tuple_ty.structFieldDefaultValue(i); + const elem_ref = try tupleField(sema, block, inst_src, inst, field_src, i); + const coerced = try sema.coerce(block, field_ty, elem_ref, field_src); + field_refs[field_index] = coerced; + if (default_val.tag() != .unreachable_value) { + const init_val = (try sema.resolveMaybeUndefVal(block, field_src, coerced)) orelse { + return sema.failWithNeededComptime(block, field_src, "value stored in comptime field must be comptime known"); + }; + + if (!init_val.eql(default_val, field_ty, sema.mod)) { + return sema.failWithInvalidComptimeFieldStore(block, field_src, inst_ty, i); + } + } + if (runtime_src == null) { + if (try sema.resolveMaybeUndefVal(block, field_src, coerced)) |field_val| { + field_vals[field_index] = field_val; + } else { + runtime_src = field_src; + } + } + } + + // Populate default field values and report errors for missing fields. + var root_msg: ?*Module.ErrorMsg = null; + + for (field_refs) |*field_ref, i| { + if (field_ref.* != .none) continue; + + const default_val = tuple_ty.structFieldDefaultValue(i); + const field_ty = tuple_ty.structFieldType(i); + + const field_src = inst_src; // TODO better source location + if (default_val.tag() == .unreachable_value) { + if (tuple_ty.isTuple()) { + const template = "missing tuple field: {d}"; + if (root_msg) |msg| { + try sema.errNote(block, field_src, msg, template, .{i}); + } else { + root_msg = try sema.errMsg(block, field_src, template, .{i}); + } + continue; + } + const template = "missing struct field: {s}"; + const args = .{tuple_ty.structFieldName(i)}; + if (root_msg) |msg| { + try sema.errNote(block, field_src, msg, template, args); + } else { + root_msg = try sema.errMsg(block, field_src, template, args); + } + continue; + } + if (runtime_src == null) { + field_vals[i] = default_val; + } else { + field_ref.* = try sema.addConstant(field_ty, default_val); + } + } + + if (root_msg) |msg| { + try sema.addDeclaredHereNote(msg, tuple_ty); + return sema.failWithOwnedErrorMsg(block, msg); + } + + if (runtime_src) |rs| { + try sema.requireRuntimeBlock(block, inst_src, rs); + return block.addAggregateInit(tuple_ty, field_refs); + } + + return sema.addConstant( + tuple_ty, + try Value.Tag.aggregate.create(sema.arena, field_vals), + ); +} + fn analyzeDeclVal( sema: *Sema, block: *Block, diff --git a/test/behavior/tuple.zig b/test/behavior/tuple.zig index 4c43ef6be6..14297bd61c 100644 --- a/test/behavior/tuple.zig +++ b/test/behavior/tuple.zig @@ -275,3 +275,18 @@ test "tuple in tuple passed to generic function" { const x = comptime S.pair(1.5, 2.5); try S.foo(.{x}); } + +test "coerce tuple to tuple" { + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; + + const T = std.meta.Tuple(&.{u8}); + const S = struct { + fn foo(x: T) !void { + try expect(x[0] == 123); + } + }; + try S.foo(.{123}); +} diff --git a/test/cases/compile_errors/stage1/test/type_mismatch_with_tuple_concatenation.zig b/test/cases/compile_errors/stage1/test/type_mismatch_with_tuple_concatenation.zig deleted file mode 100644 index 5983224676..0000000000 --- a/test/cases/compile_errors/stage1/test/type_mismatch_with_tuple_concatenation.zig +++ /dev/null @@ -1,11 +0,0 @@ -export fn entry() void { - var x = .{}; - x = x ++ .{ 1, 2, 3 }; -} - -// error -// backend=stage1 -// target=native -// is_test=1 -// -// tmp.zig:3:11: error: expected type 'struct:2:14', found 'struct:3:11' diff --git a/test/cases/compile_errors/type_mismatch_with_tuple_concatenation.zig b/test/cases/compile_errors/type_mismatch_with_tuple_concatenation.zig new file mode 100644 index 0000000000..4e9bdfa2e5 --- /dev/null +++ b/test/cases/compile_errors/type_mismatch_with_tuple_concatenation.zig @@ -0,0 +1,10 @@ +export fn entry() void { + var x = .{}; + x = x ++ .{ 1, 2, 3 }; +} + +// error +// backend=stage2 +// target=native +// +// :3:11: error: index '0' out of bounds of tuple '@TypeOf(.{})' -- cgit v1.2.3 From 02dc0732604236a57b43b9612d9b0571f06f905a Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Thu, 28 Jul 2022 22:21:49 +0300 Subject: Sema: check comptime slice sentinel --- src/Sema.zig | 96 +++++++++++++++++++--- ...not_match_memory_at_target_index_terminated.zig | 74 +++++++++++++++++ ...t_match_memory_at_target_index_unterminated.zig | 74 +++++++++++++++++ ...ice-sentinel_does_not_match_target-sentinel.zig | 74 +++++++++++++++++ ..._slice-sentinel_is_out_of_bounds_terminated.zig | 67 +++++++++++++++ ...lice-sentinel_is_out_of_bounds_unterminated.zig | 67 +++++++++++++++ .../comptime_slice_of_an_undefined_slice.zig | 11 +++ ...not_match_memory_at_target_index_terminated.zig | 67 --------------- ...t_match_memory_at_target_index_unterminated.zig | 67 --------------- ...ice-sentinel_does_not_match_target-sentinel.zig | 67 --------------- ..._slice-sentinel_is_out_of_bounds_terminated.zig | 67 --------------- ...lice-sentinel_is_out_of_bounds_unterminated.zig | 67 --------------- .../obj/comptime_slice_of_an_undefined_slice.zig | 11 --- 13 files changed, 450 insertions(+), 359 deletions(-) create mode 100644 test/cases/compile_errors/comptime_slice-sentinel_does_not_match_memory_at_target_index_terminated.zig create mode 100644 test/cases/compile_errors/comptime_slice-sentinel_does_not_match_memory_at_target_index_unterminated.zig create mode 100644 test/cases/compile_errors/comptime_slice-sentinel_does_not_match_target-sentinel.zig create mode 100644 test/cases/compile_errors/comptime_slice-sentinel_is_out_of_bounds_terminated.zig create mode 100644 test/cases/compile_errors/comptime_slice-sentinel_is_out_of_bounds_unterminated.zig create mode 100644 test/cases/compile_errors/comptime_slice_of_an_undefined_slice.zig delete mode 100644 test/cases/compile_errors/stage1/obj/comptime_slice-sentinel_does_not_match_memory_at_target_index_terminated.zig delete mode 100644 test/cases/compile_errors/stage1/obj/comptime_slice-sentinel_does_not_match_memory_at_target_index_unterminated.zig delete mode 100644 test/cases/compile_errors/stage1/obj/comptime_slice-sentinel_does_not_match_target-sentinel.zig delete mode 100644 test/cases/compile_errors/stage1/obj/comptime_slice-sentinel_is_out_of_bounds_terminated.zig delete mode 100644 test/cases/compile_errors/stage1/obj/comptime_slice-sentinel_is_out_of_bounds_unterminated.zig delete mode 100644 test/cases/compile_errors/stage1/obj/comptime_slice_of_an_undefined_slice.zig (limited to 'test/cases') diff --git a/src/Sema.zig b/src/Sema.zig index 31a0e41d95..a0829d6eb7 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -25150,7 +25150,10 @@ fn analyzeSlice( if (!end_is_len) { const end = try sema.coerce(block, Type.usize, uncasted_end_opt, end_src); if (try sema.resolveDefinedValue(block, end_src, end)) |end_val| { - if (try sema.resolveDefinedValue(block, src, ptr_or_slice)) |slice_val| { + if (try sema.resolveMaybeUndefVal(block, src, ptr_or_slice)) |slice_val| { + if (slice_val.isUndef()) { + return sema.fail(block, src, "slice of undefined", .{}); + } const has_sentinel = slice_ty.sentinel() != null; var int_payload: Value.Payload.U64 = .{ .base = .{ .tag = .int_u64 }, @@ -25213,8 +25216,8 @@ fn analyzeSlice( }; // requirement: start <= end - if (try sema.resolveDefinedValue(block, src, end)) |end_val| { - if (try sema.resolveDefinedValue(block, src, start)) |start_val| { + if (try sema.resolveDefinedValue(block, end_src, end)) |end_val| { + if (try sema.resolveDefinedValue(block, start_src, start)) |start_val| { if (try sema.compare(block, src, start_val, .gt, end_val, Type.usize)) { return sema.fail( block, @@ -25226,6 +25229,45 @@ fn analyzeSlice( }, ); } + if (try sema.resolveMaybeUndefVal(block, ptr_src, new_ptr)) |ptr_val| sentinel_check: { + const expected_sentinel = sentinel orelse break :sentinel_check; + const start_int = start_val.getUnsignedInt(sema.mod.getTarget()).?; + const end_int = end_val.getUnsignedInt(sema.mod.getTarget()).?; + const sentinel_index = try sema.usizeCast(block, end_src, end_int - start_int); + + const elem_ptr = try ptr_val.elemPtr(sema.typeOf(new_ptr), sema.arena, sentinel_index, sema.mod); + const res = try sema.pointerDerefExtra(block, src, elem_ptr, elem_ty, false); + const actual_sentinel = switch (res) { + .runtime_load => break :sentinel_check, + .val => |v| v, + .needed_well_defined => |ty| return sema.fail( + block, + src, + "comptime dereference requires '{}' to have a well-defined layout, but it does not.", + .{ty.fmt(sema.mod)}, + ), + .out_of_bounds => |ty| return sema.fail( + block, + end_src, + "slice end index {d} exceeds bounds of containing decl of type '{}'", + .{ end_int, ty.fmt(sema.mod) }, + ), + }; + + if (!actual_sentinel.eql(expected_sentinel, elem_ty, sema.mod)) { + const msg = msg: { + const msg = try sema.errMsg(block, src, "value in memory does not match slice sentinel", .{}); + errdefer msg.destroy(sema.gpa); + try sema.errNote(block, src, msg, "expected '{}', found '{}'", .{ + expected_sentinel.fmtValue(elem_ty, sema.mod), + actual_sentinel.fmtValue(elem_ty, sema.mod), + }); + + break :msg msg; + }; + return sema.failWithOwnedErrorMsg(block, msg); + } + } } } @@ -27866,9 +27908,36 @@ pub fn analyzeAddrspace( /// Returns `null` if the pointer contents cannot be loaded at comptime. fn pointerDeref(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value, ptr_ty: Type) CompileError!?Value { const load_ty = ptr_ty.childType(); + const res = try sema.pointerDerefExtra(block, src, ptr_val, load_ty, true); + switch (res) { + .runtime_load => return null, + .val => |v| return v, + .needed_well_defined => |ty| return sema.fail( + block, + src, + "comptime dereference requires '{}' to have a well-defined layout, but it does not.", + .{ty.fmt(sema.mod)}, + ), + .out_of_bounds => |ty| return sema.fail( + block, + src, + "dereference of '{}' exceeds bounds of containing decl of type '{}'", + .{ ptr_ty.fmt(sema.mod), ty.fmt(sema.mod) }, + ), + } +} + +const DerefResult = union(enum) { + runtime_load, + val: Value, + needed_well_defined: Type, + out_of_bounds: Type, +}; + +fn pointerDerefExtra(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value, load_ty: Type, want_mutable: bool) CompileError!DerefResult { const target = sema.mod.getTarget(); const deref = sema.beginComptimePtrLoad(block, src, ptr_val, load_ty) catch |err| switch (err) { - error.RuntimeLoad => return null, + error.RuntimeLoad => return DerefResult{ .runtime_load = {} }, else => |e| return e, }; @@ -27879,39 +27948,40 @@ fn pointerDeref(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value, ptr if (coerce_in_mem_ok) { // We have a Value that lines up in virtual memory exactly with what we want to load, // and it is in-memory coercible to load_ty. It may be returned without modifications. - if (deref.is_mutable) { + if (deref.is_mutable and want_mutable) { // The decl whose value we are obtaining here may be overwritten with // a different value upon further semantic analysis, which would // invalidate this memory. So we must copy here. - return try tv.val.copy(sema.arena); + return DerefResult{ .val = try tv.val.copy(sema.arena) }; } - return tv.val; + return DerefResult{ .val = tv.val }; } } // The type is not in-memory coercible or the direct dereference failed, so it must // be bitcast according to the pointer type we are performing the load through. - if (!load_ty.hasWellDefinedLayout()) - return sema.fail(block, src, "comptime dereference requires '{}' to have a well-defined layout, but it does not.", .{load_ty.fmt(sema.mod)}); + if (!load_ty.hasWellDefinedLayout()) { + return DerefResult{ .needed_well_defined = load_ty }; + } const load_sz = try sema.typeAbiSize(block, src, load_ty); // Try the smaller bit-cast first, since that's more efficient than using the larger `parent` if (deref.pointee) |tv| if (load_sz <= try sema.typeAbiSize(block, src, tv.ty)) - return try sema.bitCastVal(block, src, tv.val, tv.ty, load_ty, 0); + return DerefResult{ .val = try sema.bitCastVal(block, src, tv.val, tv.ty, load_ty, 0) }; // If that fails, try to bit-cast from the largest parent value with a well-defined layout if (deref.parent) |parent| if (load_sz + parent.byte_offset <= try sema.typeAbiSize(block, src, parent.tv.ty)) - return try sema.bitCastVal(block, src, parent.tv.val, parent.tv.ty, load_ty, parent.byte_offset); + return DerefResult{ .val = try sema.bitCastVal(block, src, parent.tv.val, parent.tv.ty, load_ty, parent.byte_offset) }; if (deref.ty_without_well_defined_layout) |bad_ty| { // We got no parent for bit-casting, or the parent we got was too small. Either way, the problem // is that some type we encountered when de-referencing does not have a well-defined layout. - return sema.fail(block, src, "comptime dereference requires '{}' to have a well-defined layout, but it does not.", .{bad_ty.fmt(sema.mod)}); + return DerefResult{ .needed_well_defined = bad_ty }; } else { // If all encountered types had well-defined layouts, the parent is the root decl and it just // wasn't big enough for the load. - return sema.fail(block, src, "dereference of '{}' exceeds bounds of containing decl of type '{}'", .{ ptr_ty.fmt(sema.mod), deref.parent.?.tv.ty.fmt(sema.mod) }); + return DerefResult{ .out_of_bounds = deref.parent.?.tv.ty }; } } diff --git a/test/cases/compile_errors/comptime_slice-sentinel_does_not_match_memory_at_target_index_terminated.zig b/test/cases/compile_errors/comptime_slice-sentinel_does_not_match_memory_at_target_index_terminated.zig new file mode 100644 index 0000000000..ffa21af10a --- /dev/null +++ b/test/cases/compile_errors/comptime_slice-sentinel_does_not_match_memory_at_target_index_terminated.zig @@ -0,0 +1,74 @@ +export fn foo_array() void { + comptime { + var target = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + const slice = target[0..3 :0]; + _ = slice; + } +} +export fn foo_ptr_array() void { + comptime { + var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + var target = &buf; + const slice = target[0..3 :0]; + _ = slice; + } +} +export fn foo_vector_ConstPtrSpecialBaseArray() void { + comptime { + var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + var target: [*]u8 = &buf; + const slice = target[0..3 :0]; + _ = slice; + } +} +export fn foo_vector_ConstPtrSpecialRef() void { + comptime { + var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + var target: [*]u8 = @ptrCast([*]u8, &buf); + const slice = target[0..3 :0]; + _ = slice; + } +} +export fn foo_cvector_ConstPtrSpecialBaseArray() void { + comptime { + var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + var target: [*c]u8 = &buf; + const slice = target[0..3 :0]; + _ = slice; + } +} +export fn foo_cvector_ConstPtrSpecialRef() void { + comptime { + var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + var target: [*c]u8 = @ptrCast([*c]u8, &buf); + const slice = target[0..3 :0]; + _ = slice; + } +} +export fn foo_slice() void { + comptime { + var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + var target: []u8 = &buf; + const slice = target[0..3 :0]; + _ = slice; + } +} + +// error +// backend=stage2 +// target=native +// +// :4:29: error: value in memory does not match slice sentinel +// :4:29: note: expected '0', found '100' +// :12:29: error: value in memory does not match slice sentinel +// :12:29: note: expected '0', found '100' +// :20:29: error: value in memory does not match slice sentinel +// :20:29: note: expected '0', found '100' +// :28:29: error: value in memory does not match slice sentinel +// :28:29: note: expected '0', found '100' +// :36:29: error: value in memory does not match slice sentinel +// :36:29: note: expected '0', found '100' +// :44:29: error: value in memory does not match slice sentinel +// :44:29: note: expected '0', found '100' +// :52:29: error: value in memory does not match slice sentinel +// :52:29: note: expected '0', found '100' diff --git a/test/cases/compile_errors/comptime_slice-sentinel_does_not_match_memory_at_target_index_unterminated.zig b/test/cases/compile_errors/comptime_slice-sentinel_does_not_match_memory_at_target_index_unterminated.zig new file mode 100644 index 0000000000..c5bb2d9643 --- /dev/null +++ b/test/cases/compile_errors/comptime_slice-sentinel_does_not_match_memory_at_target_index_unterminated.zig @@ -0,0 +1,74 @@ +export fn foo_array() void { + comptime { + var target = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + const slice = target[0..3 :0]; + _ = slice; + } +} +export fn foo_ptr_array() void { + comptime { + var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + var target = &buf; + const slice = target[0..3 :0]; + _ = slice; + } +} +export fn foo_vector_ConstPtrSpecialBaseArray() void { + comptime { + var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + var target: [*]u8 = &buf; + const slice = target[0..3 :0]; + _ = slice; + } +} +export fn foo_vector_ConstPtrSpecialRef() void { + comptime { + var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + var target: [*]u8 = @ptrCast([*]u8, &buf); + const slice = target[0..3 :0]; + _ = slice; + } +} +export fn foo_cvector_ConstPtrSpecialBaseArray() void { + comptime { + var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + var target: [*c]u8 = &buf; + const slice = target[0..3 :0]; + _ = slice; + } +} +export fn foo_cvector_ConstPtrSpecialRef() void { + comptime { + var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + var target: [*c]u8 = @ptrCast([*c]u8, &buf); + const slice = target[0..3 :0]; + _ = slice; + } +} +export fn foo_slice() void { + comptime { + var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + var target: []u8 = &buf; + const slice = target[0..3 :0]; + _ = slice; + } +} + +// error +// backend=stage2 +// target=native +// +// :4:29: error: value in memory does not match slice sentinel +// :4:29: note: expected '0', found '100' +// :12:29: error: value in memory does not match slice sentinel +// :12:29: note: expected '0', found '100' +// :20:29: error: value in memory does not match slice sentinel +// :20:29: note: expected '0', found '100' +// :28:29: error: value in memory does not match slice sentinel +// :28:29: note: expected '0', found '100' +// :36:29: error: value in memory does not match slice sentinel +// :36:29: note: expected '0', found '100' +// :44:29: error: value in memory does not match slice sentinel +// :44:29: note: expected '0', found '100' +// :52:29: error: value in memory does not match slice sentinel +// :52:29: note: expected '0', found '100' diff --git a/test/cases/compile_errors/comptime_slice-sentinel_does_not_match_target-sentinel.zig b/test/cases/compile_errors/comptime_slice-sentinel_does_not_match_target-sentinel.zig new file mode 100644 index 0000000000..b574df8833 --- /dev/null +++ b/test/cases/compile_errors/comptime_slice-sentinel_does_not_match_target-sentinel.zig @@ -0,0 +1,74 @@ +export fn foo_array() void { + comptime { + var target = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + const slice = target[0..14 :255]; + _ = slice; + } +} +export fn foo_ptr_array() void { + comptime { + var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + var target = &buf; + const slice = target[0..14 :255]; + _ = slice; + } +} +export fn foo_vector_ConstPtrSpecialBaseArray() void { + comptime { + var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + var target: [*]u8 = &buf; + const slice = target[0..14 :255]; + _ = slice; + } +} +export fn foo_vector_ConstPtrSpecialRef() void { + comptime { + var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + var target: [*]u8 = @ptrCast([*]u8, &buf); + const slice = target[0..14 :255]; + _ = slice; + } +} +export fn foo_cvector_ConstPtrSpecialBaseArray() void { + comptime { + var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + var target: [*c]u8 = &buf; + const slice = target[0..14 :255]; + _ = slice; + } +} +export fn foo_cvector_ConstPtrSpecialRef() void { + comptime { + var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + var target: [*c]u8 = @ptrCast([*c]u8, &buf); + const slice = target[0..14 :255]; + _ = slice; + } +} +export fn foo_slice() void { + comptime { + var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + var target: []u8 = &buf; + const slice = target[0..14 :255]; + _ = slice; + } +} + +// error +// backend=stage2 +// target=native +// +// :4:29: error: value in memory does not match slice sentinel +// :4:29: note: expected '255', found '0' +// :12:29: error: value in memory does not match slice sentinel +// :12:29: note: expected '255', found '0' +// :20:29: error: value in memory does not match slice sentinel +// :20:29: note: expected '255', found '0' +// :28:29: error: value in memory does not match slice sentinel +// :28:29: note: expected '255', found '0' +// :36:29: error: value in memory does not match slice sentinel +// :36:29: note: expected '255', found '0' +// :44:29: error: value in memory does not match slice sentinel +// :44:29: note: expected '255', found '0' +// :52:29: error: value in memory does not match slice sentinel +// :52:29: note: expected '255', found '0' diff --git a/test/cases/compile_errors/comptime_slice-sentinel_is_out_of_bounds_terminated.zig b/test/cases/compile_errors/comptime_slice-sentinel_is_out_of_bounds_terminated.zig new file mode 100644 index 0000000000..86bd4ce8bb --- /dev/null +++ b/test/cases/compile_errors/comptime_slice-sentinel_is_out_of_bounds_terminated.zig @@ -0,0 +1,67 @@ +export fn foo_array() void { + comptime { + var target = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + const slice = target[0..15 :1]; + _ = slice; + } +} +export fn foo_ptr_array() void { + comptime { + var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + var target = &buf; + const slice = target[0..15 :0]; + _ = slice; + } +} +export fn foo_vector_ConstPtrSpecialBaseArray() void { + comptime { + var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + var target: [*]u8 = &buf; + const slice = target[0..15 :0]; + _ = slice; + } +} +export fn foo_vector_ConstPtrSpecialRef() void { + comptime { + var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + var target: [*]u8 = @ptrCast([*]u8, &buf); + const slice = target[0..15 :0]; + _ = slice; + } +} +export fn foo_cvector_ConstPtrSpecialBaseArray() void { + comptime { + var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + var target: [*c]u8 = &buf; + const slice = target[0..15 :0]; + _ = slice; + } +} +export fn foo_cvector_ConstPtrSpecialRef() void { + comptime { + var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + var target: [*c]u8 = @ptrCast([*c]u8, &buf); + const slice = target[0..15 :0]; + _ = slice; + } +} +export fn foo_slice() void { + comptime { + var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + var target: []u8 = &buf; + const slice = target[0..15 :0]; + _ = slice; + } +} + +// error +// backend=stage2 +// target=native +// +// :4:33: error: slice end index 15 exceeds bounds of containing decl of type '[14:0]u8' +// :12:33: error: slice end index 15 exceeds bounds of containing decl of type '[14:0]u8' +// :20:33: error: slice end index 15 exceeds bounds of containing decl of type '[14:0]u8' +// :28:33: error: slice end index 15 exceeds bounds of containing decl of type '[14:0]u8' +// :36:33: error: slice end index 15 exceeds bounds of containing decl of type '[14:0]u8' +// :44:33: error: slice end index 15 exceeds bounds of containing decl of type '[14:0]u8' +// :52:33: error: end index 15 out of bounds for slice of length 14 diff --git a/test/cases/compile_errors/comptime_slice-sentinel_is_out_of_bounds_unterminated.zig b/test/cases/compile_errors/comptime_slice-sentinel_is_out_of_bounds_unterminated.zig new file mode 100644 index 0000000000..e1b8a5bc2d --- /dev/null +++ b/test/cases/compile_errors/comptime_slice-sentinel_is_out_of_bounds_unterminated.zig @@ -0,0 +1,67 @@ +export fn foo_array() void { + comptime { + var target = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + const slice = target[0..14 :0]; + _ = slice; + } +} +export fn foo_ptr_array() void { + comptime { + var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + var target = &buf; + const slice = target[0..14 :0]; + _ = slice; + } +} +export fn foo_vector_ConstPtrSpecialBaseArray() void { + comptime { + var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + var target: [*]u8 = &buf; + const slice = target[0..14 :0]; + _ = slice; + } +} +export fn foo_vector_ConstPtrSpecialRef() void { + comptime { + var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + var target: [*]u8 = @ptrCast([*]u8, &buf); + const slice = target[0..14 :0]; + _ = slice; + } +} +export fn foo_cvector_ConstPtrSpecialBaseArray() void { + comptime { + var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + var target: [*c]u8 = &buf; + const slice = target[0..14 :0]; + _ = slice; + } +} +export fn foo_cvector_ConstPtrSpecialRef() void { + comptime { + var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + var target: [*c]u8 = @ptrCast([*c]u8, &buf); + const slice = target[0..14 :0]; + _ = slice; + } +} +export fn foo_slice() void { + comptime { + var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; + var target: []u8 = &buf; + const slice = target[0..14 :0]; + _ = slice; + } +} + +// error +// backend=stage2 +// target=native +// +// :4:33: error: slice end index 14 exceeds bounds of containing decl of type '[14]u8' +// :12:33: error: slice end index 14 exceeds bounds of containing decl of type '[14]u8' +// :20:33: error: slice end index 14 exceeds bounds of containing decl of type '[14]u8' +// :28:33: error: slice end index 14 exceeds bounds of containing decl of type '[14]u8' +// :36:33: error: slice end index 14 exceeds bounds of containing decl of type '[14]u8' +// :44:33: error: slice end index 14 exceeds bounds of containing decl of type '[14]u8' +// :52:33: error: slice end index 14 exceeds bounds of containing decl of type '[14]u8' diff --git a/test/cases/compile_errors/comptime_slice_of_an_undefined_slice.zig b/test/cases/compile_errors/comptime_slice_of_an_undefined_slice.zig new file mode 100644 index 0000000000..d1b22d86b7 --- /dev/null +++ b/test/cases/compile_errors/comptime_slice_of_an_undefined_slice.zig @@ -0,0 +1,11 @@ +comptime { + var a: []u8 = undefined; + var b = a[0..10]; + _ = b; +} + +// error +// backend=stage2 +// target=native +// +// :3:14: error: slice of undefined diff --git a/test/cases/compile_errors/stage1/obj/comptime_slice-sentinel_does_not_match_memory_at_target_index_terminated.zig b/test/cases/compile_errors/stage1/obj/comptime_slice-sentinel_does_not_match_memory_at_target_index_terminated.zig deleted file mode 100644 index 598d23a305..0000000000 --- a/test/cases/compile_errors/stage1/obj/comptime_slice-sentinel_does_not_match_memory_at_target_index_terminated.zig +++ /dev/null @@ -1,67 +0,0 @@ -export fn foo_array() void { - comptime { - var target = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; - const slice = target[0..3 :0]; - _ = slice; - } -} -export fn foo_ptr_array() void { - comptime { - var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; - var target = &buf; - const slice = target[0..3 :0]; - _ = slice; - } -} -export fn foo_vector_ConstPtrSpecialBaseArray() void { - comptime { - var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; - var target: [*]u8 = &buf; - const slice = target[0..3 :0]; - _ = slice; - } -} -export fn foo_vector_ConstPtrSpecialRef() void { - comptime { - var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; - var target: [*]u8 = @ptrCast([*]u8, &buf); - const slice = target[0..3 :0]; - _ = slice; - } -} -export fn foo_cvector_ConstPtrSpecialBaseArray() void { - comptime { - var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; - var target: [*c]u8 = &buf; - const slice = target[0..3 :0]; - _ = slice; - } -} -export fn foo_cvector_ConstPtrSpecialRef() void { - comptime { - var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; - var target: [*c]u8 = @ptrCast([*c]u8, &buf); - const slice = target[0..3 :0]; - _ = slice; - } -} -export fn foo_slice() void { - comptime { - var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; - var target: []u8 = &buf; - const slice = target[0..3 :0]; - _ = slice; - } -} - -// error -// backend=stage1 -// target=native -// -// :4:29: error: slice-sentinel does not match memory at target index -// :12:29: error: slice-sentinel does not match memory at target index -// :20:29: error: slice-sentinel does not match memory at target index -// :28:29: error: slice-sentinel does not match memory at target index -// :36:29: error: slice-sentinel does not match memory at target index -// :44:29: error: slice-sentinel does not match memory at target index -// :52:29: error: slice-sentinel does not match memory at target index diff --git a/test/cases/compile_errors/stage1/obj/comptime_slice-sentinel_does_not_match_memory_at_target_index_unterminated.zig b/test/cases/compile_errors/stage1/obj/comptime_slice-sentinel_does_not_match_memory_at_target_index_unterminated.zig deleted file mode 100644 index d6b469aaf1..0000000000 --- a/test/cases/compile_errors/stage1/obj/comptime_slice-sentinel_does_not_match_memory_at_target_index_unterminated.zig +++ /dev/null @@ -1,67 +0,0 @@ -export fn foo_array() void { - comptime { - var target = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; - const slice = target[0..3 :0]; - _ = slice; - } -} -export fn foo_ptr_array() void { - comptime { - var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; - var target = &buf; - const slice = target[0..3 :0]; - _ = slice; - } -} -export fn foo_vector_ConstPtrSpecialBaseArray() void { - comptime { - var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; - var target: [*]u8 = &buf; - const slice = target[0..3 :0]; - _ = slice; - } -} -export fn foo_vector_ConstPtrSpecialRef() void { - comptime { - var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; - var target: [*]u8 = @ptrCast([*]u8, &buf); - const slice = target[0..3 :0]; - _ = slice; - } -} -export fn foo_cvector_ConstPtrSpecialBaseArray() void { - comptime { - var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; - var target: [*c]u8 = &buf; - const slice = target[0..3 :0]; - _ = slice; - } -} -export fn foo_cvector_ConstPtrSpecialRef() void { - comptime { - var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; - var target: [*c]u8 = @ptrCast([*c]u8, &buf); - const slice = target[0..3 :0]; - _ = slice; - } -} -export fn foo_slice() void { - comptime { - var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; - var target: []u8 = &buf; - const slice = target[0..3 :0]; - _ = slice; - } -} - -// error -// backend=stage1 -// target=native -// -// :4:29: error: slice-sentinel does not match memory at target index -// :12:29: error: slice-sentinel does not match memory at target index -// :20:29: error: slice-sentinel does not match memory at target index -// :28:29: error: slice-sentinel does not match memory at target index -// :36:29: error: slice-sentinel does not match memory at target index -// :44:29: error: slice-sentinel does not match memory at target index -// :52:29: error: slice-sentinel does not match memory at target index diff --git a/test/cases/compile_errors/stage1/obj/comptime_slice-sentinel_does_not_match_target-sentinel.zig b/test/cases/compile_errors/stage1/obj/comptime_slice-sentinel_does_not_match_target-sentinel.zig deleted file mode 100644 index b204cfc684..0000000000 --- a/test/cases/compile_errors/stage1/obj/comptime_slice-sentinel_does_not_match_target-sentinel.zig +++ /dev/null @@ -1,67 +0,0 @@ -export fn foo_array() void { - comptime { - var target = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; - const slice = target[0..14 :255]; - _ = slice; - } -} -export fn foo_ptr_array() void { - comptime { - var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; - var target = &buf; - const slice = target[0..14 :255]; - _ = slice; - } -} -export fn foo_vector_ConstPtrSpecialBaseArray() void { - comptime { - var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; - var target: [*]u8 = &buf; - const slice = target[0..14 :255]; - _ = slice; - } -} -export fn foo_vector_ConstPtrSpecialRef() void { - comptime { - var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; - var target: [*]u8 = @ptrCast([*]u8, &buf); - const slice = target[0..14 :255]; - _ = slice; - } -} -export fn foo_cvector_ConstPtrSpecialBaseArray() void { - comptime { - var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; - var target: [*c]u8 = &buf; - const slice = target[0..14 :255]; - _ = slice; - } -} -export fn foo_cvector_ConstPtrSpecialRef() void { - comptime { - var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; - var target: [*c]u8 = @ptrCast([*c]u8, &buf); - const slice = target[0..14 :255]; - _ = slice; - } -} -export fn foo_slice() void { - comptime { - var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; - var target: []u8 = &buf; - const slice = target[0..14 :255]; - _ = slice; - } -} - -// error -// backend=stage1 -// target=native -// -// :4:29: error: slice-sentinel does not match target-sentinel -// :12:29: error: slice-sentinel does not match target-sentinel -// :20:29: error: slice-sentinel does not match target-sentinel -// :28:29: error: slice-sentinel does not match target-sentinel -// :36:29: error: slice-sentinel does not match target-sentinel -// :44:29: error: slice-sentinel does not match target-sentinel -// :52:29: error: slice-sentinel does not match target-sentinel diff --git a/test/cases/compile_errors/stage1/obj/comptime_slice-sentinel_is_out_of_bounds_terminated.zig b/test/cases/compile_errors/stage1/obj/comptime_slice-sentinel_is_out_of_bounds_terminated.zig deleted file mode 100644 index 82c19126c0..0000000000 --- a/test/cases/compile_errors/stage1/obj/comptime_slice-sentinel_is_out_of_bounds_terminated.zig +++ /dev/null @@ -1,67 +0,0 @@ -export fn foo_array() void { - comptime { - var target = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; - const slice = target[0..15 :1]; - _ = slice; - } -} -export fn foo_ptr_array() void { - comptime { - var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; - var target = &buf; - const slice = target[0..15 :0]; - _ = slice; - } -} -export fn foo_vector_ConstPtrSpecialBaseArray() void { - comptime { - var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; - var target: [*]u8 = &buf; - const slice = target[0..15 :0]; - _ = slice; - } -} -export fn foo_vector_ConstPtrSpecialRef() void { - comptime { - var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; - var target: [*]u8 = @ptrCast([*]u8, &buf); - const slice = target[0..15 :0]; - _ = slice; - } -} -export fn foo_cvector_ConstPtrSpecialBaseArray() void { - comptime { - var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; - var target: [*c]u8 = &buf; - const slice = target[0..15 :0]; - _ = slice; - } -} -export fn foo_cvector_ConstPtrSpecialRef() void { - comptime { - var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; - var target: [*c]u8 = @ptrCast([*c]u8, &buf); - const slice = target[0..15 :0]; - _ = slice; - } -} -export fn foo_slice() void { - comptime { - var buf = [_:0]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; - var target: []u8 = &buf; - const slice = target[0..15 :0]; - _ = slice; - } -} - -// error -// backend=stage1 -// target=native -// -// :4:29: error: out of bounds slice -// :12:29: error: out of bounds slice -// :20:29: error: out of bounds slice -// :28:29: error: out of bounds slice -// :36:29: error: out of bounds slice -// :44:29: error: out of bounds slice -// :52:29: error: out of bounds slice diff --git a/test/cases/compile_errors/stage1/obj/comptime_slice-sentinel_is_out_of_bounds_unterminated.zig b/test/cases/compile_errors/stage1/obj/comptime_slice-sentinel_is_out_of_bounds_unterminated.zig deleted file mode 100644 index 952b17600a..0000000000 --- a/test/cases/compile_errors/stage1/obj/comptime_slice-sentinel_is_out_of_bounds_unterminated.zig +++ /dev/null @@ -1,67 +0,0 @@ -export fn foo_array() void { - comptime { - var target = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; - const slice = target[0..14 :0]; - _ = slice; - } -} -export fn foo_ptr_array() void { - comptime { - var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; - var target = &buf; - const slice = target[0..14 :0]; - _ = slice; - } -} -export fn foo_vector_ConstPtrSpecialBaseArray() void { - comptime { - var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; - var target: [*]u8 = &buf; - const slice = target[0..14 :0]; - _ = slice; - } -} -export fn foo_vector_ConstPtrSpecialRef() void { - comptime { - var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; - var target: [*]u8 = @ptrCast([*]u8, &buf); - const slice = target[0..14 :0]; - _ = slice; - } -} -export fn foo_cvector_ConstPtrSpecialBaseArray() void { - comptime { - var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; - var target: [*c]u8 = &buf; - const slice = target[0..14 :0]; - _ = slice; - } -} -export fn foo_cvector_ConstPtrSpecialRef() void { - comptime { - var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; - var target: [*c]u8 = @ptrCast([*c]u8, &buf); - const slice = target[0..14 :0]; - _ = slice; - } -} -export fn foo_slice() void { - comptime { - var buf = [_]u8{ 'a', 'b', 'c', 'd' } ++ [_]u8{undefined} ** 10; - var target: []u8 = &buf; - const slice = target[0..14 :0]; - _ = slice; - } -} - -// error -// backend=stage1 -// target=native -// -// :4:29: error: slice-sentinel is out of bounds -// :12:29: error: slice-sentinel is out of bounds -// :20:29: error: slice-sentinel is out of bounds -// :28:29: error: slice-sentinel is out of bounds -// :36:29: error: slice-sentinel is out of bounds -// :44:29: error: slice-sentinel is out of bounds -// :52:29: error: slice-sentinel is out of bounds diff --git a/test/cases/compile_errors/stage1/obj/comptime_slice_of_an_undefined_slice.zig b/test/cases/compile_errors/stage1/obj/comptime_slice_of_an_undefined_slice.zig deleted file mode 100644 index 4aa519f41e..0000000000 --- a/test/cases/compile_errors/stage1/obj/comptime_slice_of_an_undefined_slice.zig +++ /dev/null @@ -1,11 +0,0 @@ -comptime { - var a: []u8 = undefined; - var b = a[0..10]; - _ = b; -} - -// error -// backend=stage1 -// target=native -// -// tmp.zig:3:14: error: slice of undefined -- cgit v1.2.3