diff --git a/src/Sema.zig b/src/Sema.zig index 64db6a9bed4f0278ae0413b68593b175dd883ddd..5010d86c9a8cb16d86879bc46fe3d6cba543e58b 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -8378,19 +8378,15 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError block, src, msg, - "unhandled error value: error.{s}", + "unhandled error value: 'error.{s}'", .{error_name}, ); } } if (maybe_msg) |msg| { - try sema.mod.errNoteNonLazy( - operand_ty.declSrcLoc(sema.mod), - msg, - "error set '{}' declared here", - .{operand_ty.fmt(sema.mod)}, - ); + maybe_msg = null; + try sema.addDeclaredHereNote(msg, operand_ty); return sema.failWithOwnedErrorMsg(block, msg); } @@ -17143,9 +17139,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr const field_index = struct_obj.fields.getIndex(field_name) orelse return sema.failWithBadStructFieldAccess(block, struct_obj, name_src, field_name); - if (field_ptr_ty.zigTypeTag() != .Pointer) { - return sema.fail(block, ty_src, "expected pointer type, found '{}'", .{field_ptr_ty.fmt(sema.mod)}); - } + try sema.checkPtrOperand(block, ptr_src, field_ptr_ty); const field = struct_obj.fields.values()[field_index]; const field_ptr_ty_info = field_ptr_ty.ptrInfo().data; @@ -17168,8 +17162,29 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr const result_ptr = try Type.ptr(sema.arena, sema.mod, ptr_ty_data); if (try sema.resolveDefinedValue(block, src, casted_field_ptr)) |field_ptr_val| { - const payload = field_ptr_val.castTag(.field_ptr).?.data; - return sema.addConstant(result_ptr, payload.container_ptr); + const payload = field_ptr_val.castTag(.field_ptr) orelse { + return sema.fail(block, ptr_src, "pointer value not based on parent struct", .{}); + }; + if (payload.data.field_index != field_index) { + const msg = msg: { + const msg = try sema.errMsg( + block, + src, + "field '{s}' has index '{d}' but pointer value is index '{d}' of struct '{}'", + .{ + field_name, + field_index, + payload.data.field_index, + struct_ty.fmt(sema.mod), + }, + ); + errdefer msg.destroy(sema.gpa); + try sema.addDeclaredHereNote(msg, struct_ty); + break :msg msg; + }; + return sema.failWithOwnedErrorMsg(block, msg); + } + return sema.addConstant(result_ptr, payload.data.container_ptr); } try sema.requireRuntimeBlock(block, src); @@ -18515,7 +18530,16 @@ fn fieldVal( kw_name, child_type.fmt(sema.mod), field_name, }); }, - else => return sema.fail(block, src, "type '{}' has no members", .{child_type.fmt(sema.mod)}), + else => { + const msg = msg: { + const msg = try sema.errMsg(block, src, "type '{}' has no members", .{child_type.fmt(sema.mod)}); + errdefer msg.destroy(sema.gpa); + if (child_type.isSlice()) try sema.errNote(block, src, msg, "slice values have 'len' and 'ptr' members", .{}); + if (child_type.zigTypeTag() == .Array) try sema.errNote(block, src, msg, "array values have 'len' member", .{}); + break :msg msg; + }; + return sema.failWithOwnedErrorMsg(block, msg); + }, } }, .Struct => if (is_pointer_to) { @@ -18739,7 +18763,7 @@ fn fieldPtr( }, else => {}, } - return sema.fail(block, src, "type '{}' does not support field access (fieldPtr, {}.{s})", .{ object_ty.fmt(sema.mod), object_ptr_ty.fmt(sema.mod), field_name }); + return sema.fail(block, src, "type '{}' does not support field access", .{object_ty.fmt(sema.mod)}); } fn fieldCallBind( diff --git a/test/cases/compile_errors/division_by_zero.zig b/test/cases/compile_errors/division_by_zero.zig new file mode 100644 index 0000000000000000000000000000000000000000..2e2f7e2be2a70d4efde71ce4c66ded5d75e6560b --- /dev/null +++ b/test/cases/compile_errors/division_by_zero.zig @@ -0,0 +1,17 @@ +const lit_int_x = 1 / 0; +const lit_float_x = 1.0 / 0.0; +const int_x = @as(u32, 1) / @as(u32, 0); +const float_x = @as(f32, 1.0) / @as(f32, 0.0); + +export fn entry1() usize { return @sizeOf(@TypeOf(lit_int_x)); } +export fn entry2() usize { return @sizeOf(@TypeOf(lit_float_x)); } +export fn entry3() usize { return @sizeOf(@TypeOf(int_x)); } +export fn entry4() usize { return @sizeOf(@TypeOf(float_x)); } // no error on purpose + +// error +// backend=stage2 +// target=native +// +// :1:23: error: division by zero here causes undefined behavior +// :2:27: error: division by zero here causes undefined behavior +// :3:29: error: division by zero here causes undefined behavior diff --git a/test/cases/compile_errors/error_not_handled_in_switch.zig b/test/cases/compile_errors/error_not_handled_in_switch.zig new file mode 100644 index 0000000000000000000000000000000000000000..8f0d26a4a92bd745a012c79742b7802bdd971e6b --- /dev/null +++ b/test/cases/compile_errors/error_not_handled_in_switch.zig @@ -0,0 +1,21 @@ +export fn entry() void { + foo(452) catch |err| switch (err) { + error.Foo => {}, + }; +} +fn foo(x: i32) !void { + switch (x) { + 0 ... 10 => return error.Foo, + 11 ... 20 => return error.Bar, + 21 ... 30 => return error.Baz, + else => {}, + } +} + +// error +// backend=llvm +// target=native +// +// :2:26: error: switch must handle all possibilities +// :2:26: note: unhandled error value: 'error.Bar' +// :2:26: note: unhandled error value: 'error.Baz' diff --git a/test/cases/compile_errors/fieldParentPtr-comptime_field_ptr_not_based_on_struct.zig b/test/cases/compile_errors/fieldParentPtr-comptime_field_ptr_not_based_on_struct.zig new file mode 100644 index 0000000000000000000000000000000000000000..7f57268f0645ad067a928eed8155f402db10d9f0 --- /dev/null +++ b/test/cases/compile_errors/fieldParentPtr-comptime_field_ptr_not_based_on_struct.zig @@ -0,0 +1,17 @@ +const Foo = struct { + a: i32, + b: i32, +}; +const foo = Foo { .a = 1, .b = 2, }; + +comptime { + const field_ptr = @intToPtr(*i32, 0x1234); + const another_foo_ptr = @fieldParentPtr(Foo, "b", field_ptr); + _ = another_foo_ptr; +} + +// error +// backend=stage2 +// target=native +// +// :9:55: error: pointer value not based on parent struct diff --git a/test/cases/compile_errors/fieldParentPtr-comptime_wrong_field_index.zig b/test/cases/compile_errors/fieldParentPtr-comptime_wrong_field_index.zig new file mode 100644 index 0000000000000000000000000000000000000000..a73409aea3368300a6a397f0dffc2db57f913c7a --- /dev/null +++ b/test/cases/compile_errors/fieldParentPtr-comptime_wrong_field_index.zig @@ -0,0 +1,17 @@ +const Foo = struct { + a: i32, + b: i32, +}; +const foo = Foo { .a = 1, .b = 2, }; + +comptime { + const another_foo_ptr = @fieldParentPtr(Foo, "b", &foo.a); + _ = another_foo_ptr; +} + +// error +// backend=stage2 +// target=native +// +// :8:29: error: field 'b' has index '1' but pointer value is index '0' of struct 'tmp.Foo' +// :1:13: note: struct declared here diff --git a/test/cases/compile_errors/fieldParentPtr-field_pointer_is_not_pointer.zig b/test/cases/compile_errors/fieldParentPtr-field_pointer_is_not_pointer.zig new file mode 100644 index 0000000000000000000000000000000000000000..8a57d08c3ba166886fa0936c8af7e7419668a680 --- /dev/null +++ b/test/cases/compile_errors/fieldParentPtr-field_pointer_is_not_pointer.zig @@ -0,0 +1,12 @@ +const Foo = extern struct { + a: i32, +}; +export fn foo(a: i32) *Foo { + return @fieldParentPtr(Foo, "a", a); +} + +// error +// backend=stage2 +// target=native +// +// :5:38: error: expected pointer type, found 'i32' diff --git a/test/cases/compile_errors/field_access_of_opaque_type.zig b/test/cases/compile_errors/field_access_of_opaque_type.zig new file mode 100644 index 0000000000000000000000000000000000000000..f9ec483305cfa3a0abb06d8467d14bccbd6d1b10 --- /dev/null +++ b/test/cases/compile_errors/field_access_of_opaque_type.zig @@ -0,0 +1,16 @@ +const MyType = opaque {}; + +export fn entry() bool { + var x: i32 = 1; + return bar(@ptrCast(*MyType, &x)); +} + +fn bar(x: *MyType) bool { + return x.blah; +} + +// error +// backend=stage2 +// target=native +// +// :9:13: error: type '*tmp.MyType' does not support field access diff --git a/test/cases/compile_errors/field_access_of_slices.zig b/test/cases/compile_errors/field_access_of_slices.zig new file mode 100644 index 0000000000000000000000000000000000000000..1fbfda9646916ac61a61afe496065ca012a3dbeb --- /dev/null +++ b/test/cases/compile_errors/field_access_of_slices.zig @@ -0,0 +1,12 @@ +export fn entry() void { + var slice: []i32 = undefined; + const info = @TypeOf(slice).unknown; + _ = info; +} + +// error +// backend=stage2 +// target=native +// +// :3:32: error: type '[]i32' has no members +// :3:32: note: slice values have 'len' and 'ptr' members diff --git a/test/cases/compile_errors/field_access_of_unknown_length_pointer.zig b/test/cases/compile_errors/field_access_of_unknown_length_pointer.zig new file mode 100644 index 0000000000000000000000000000000000000000..2f526277fe152d0f3fd558fd066cc4fe05c79b07 --- /dev/null +++ b/test/cases/compile_errors/field_access_of_unknown_length_pointer.zig @@ -0,0 +1,13 @@ +const Foo = extern struct { + a: i32, +}; + +export fn entry(foo: [*]Foo) void { + foo.a += 1; +} + +// error +// backend=stage2 +// target=native +// +// :6:8: error: type '[*]tmp.Foo' does not support field access diff --git a/test/cases/compile_errors/stage1/error_equality_but_sets_have_no_common_members.zig b/test/cases/compile_errors/stage1/error_equality_but_sets_have_no_common_members.zig new file mode 100644 index 0000000000000000000000000000000000000000..d42169b5036f40ba0725358de24a370d58b85bc9 --- /dev/null +++ b/test/cases/compile_errors/stage1/error_equality_but_sets_have_no_common_members.zig @@ -0,0 +1,16 @@ +const Set1 = error{A, C}; +const Set2 = error{B, D}; +export fn entry() void { + foo(Set1.A); +} +fn foo(x: Set1) void { + if (x == Set2.B) { + + } +} + +// error +// backend=stage1 +// target=native +// +// tmp.zig:7:11: error: error sets 'Set1' and 'Set2' have no common errors diff --git a/test/cases/compile_errors/stage1/obj/division_by_zero.zig b/test/cases/compile_errors/stage1/obj/division_by_zero.zig deleted file mode 100644 index 3023f0c6f3f729891880630b31d43754fc1957ed..0000000000000000000000000000000000000000 --- a/test/cases/compile_errors/stage1/obj/division_by_zero.zig +++ /dev/null @@ -1,18 +0,0 @@ -const lit_int_x = 1 / 0; -const lit_float_x = 1.0 / 0.0; -const int_x = @as(u32, 1) / @as(u32, 0); -const float_x = @as(f32, 1.0) / @as(f32, 0.0); - -export fn entry1() usize { return @sizeOf(@TypeOf(lit_int_x)); } -export fn entry2() usize { return @sizeOf(@TypeOf(lit_float_x)); } -export fn entry3() usize { return @sizeOf(@TypeOf(int_x)); } -export fn entry4() usize { return @sizeOf(@TypeOf(float_x)); } - -// error -// backend=stage1 -// target=native -// -// tmp.zig:1:21: error: division by zero -// tmp.zig:2:25: error: division by zero -// tmp.zig:3:27: error: division by zero -// tmp.zig:4:31: error: division by zero diff --git a/test/cases/compile_errors/stage1/obj/error_equality_but_sets_have_no_common_members.zig b/test/cases/compile_errors/stage1/obj/error_equality_but_sets_have_no_common_members.zig deleted file mode 100644 index d42169b5036f40ba0725358de24a370d58b85bc9..0000000000000000000000000000000000000000 --- a/test/cases/compile_errors/stage1/obj/error_equality_but_sets_have_no_common_members.zig +++ /dev/null @@ -1,16 +0,0 @@ -const Set1 = error{A, C}; -const Set2 = error{B, D}; -export fn entry() void { - foo(Set1.A); -} -fn foo(x: Set1) void { - if (x == Set2.B) { - - } -} - -// error -// backend=stage1 -// target=native -// -// tmp.zig:7:11: error: error sets 'Set1' and 'Set2' have no common errors diff --git a/test/cases/compile_errors/stage1/obj/error_not_handled_in_switch.zig b/test/cases/compile_errors/stage1/obj/error_not_handled_in_switch.zig deleted file mode 100644 index 12ee35daef7d556a854562dc3afdec5bb17ab7d0..0000000000000000000000000000000000000000 --- a/test/cases/compile_errors/stage1/obj/error_not_handled_in_switch.zig +++ /dev/null @@ -1,20 +0,0 @@ -export fn entry() void { - foo(452) catch |err| switch (err) { - error.Foo => {}, - }; -} -fn foo(x: i32) !void { - switch (x) { - 0 ... 10 => return error.Foo, - 11 ... 20 => return error.Bar, - 21 ... 30 => return error.Baz, - else => {}, - } -} - -// error -// backend=stage1 -// target=native -// -// tmp.zig:2:26: error: error.Baz not handled in switch -// tmp.zig:2:26: error: error.Bar not handled in switch diff --git a/test/cases/compile_errors/stage1/obj/fieldParentPtr-comptime_field_ptr_not_based_on_struct.zig b/test/cases/compile_errors/stage1/obj/fieldParentPtr-comptime_field_ptr_not_based_on_struct.zig deleted file mode 100644 index 9375f4639a020f37f1f1320d0978f131279303df..0000000000000000000000000000000000000000 --- a/test/cases/compile_errors/stage1/obj/fieldParentPtr-comptime_field_ptr_not_based_on_struct.zig +++ /dev/null @@ -1,17 +0,0 @@ -const Foo = struct { - a: i32, - b: i32, -}; -const foo = Foo { .a = 1, .b = 2, }; - -comptime { - const field_ptr = @intToPtr(*i32, 0x1234); - const another_foo_ptr = @fieldParentPtr(Foo, "b", field_ptr); - _ = another_foo_ptr; -} - -// error -// backend=stage1 -// target=native -// -// tmp.zig:9:55: error: pointer value not based on parent struct diff --git a/test/cases/compile_errors/stage1/obj/fieldParentPtr-comptime_wrong_field_index.zig b/test/cases/compile_errors/stage1/obj/fieldParentPtr-comptime_wrong_field_index.zig deleted file mode 100644 index c322543dc01886dc35b4f455ffce8fe92a8aed12..0000000000000000000000000000000000000000 --- a/test/cases/compile_errors/stage1/obj/fieldParentPtr-comptime_wrong_field_index.zig +++ /dev/null @@ -1,16 +0,0 @@ -const Foo = struct { - a: i32, - b: i32, -}; -const foo = Foo { .a = 1, .b = 2, }; - -comptime { - const another_foo_ptr = @fieldParentPtr(Foo, "b", &foo.a); - _ = another_foo_ptr; -} - -// error -// backend=stage1 -// target=native -// -// tmp.zig:8:29: error: field 'b' has index 1 but pointer value is index 0 of struct 'Foo' diff --git a/test/cases/compile_errors/stage1/obj/fieldParentPtr-field_pointer_is_not_pointer.zig b/test/cases/compile_errors/stage1/obj/fieldParentPtr-field_pointer_is_not_pointer.zig deleted file mode 100644 index 71360e56810662e40958a553e4f180c82248db8c..0000000000000000000000000000000000000000 --- a/test/cases/compile_errors/stage1/obj/fieldParentPtr-field_pointer_is_not_pointer.zig +++ /dev/null @@ -1,12 +0,0 @@ -const Foo = extern struct { - a: i32, -}; -export fn foo(a: i32) *Foo { - return @fieldParentPtr(Foo, "a", a); -} - -// error -// backend=stage1 -// target=native -// -// tmp.zig:5:38: error: expected pointer, found 'i32' diff --git a/test/cases/compile_errors/stage1/obj/field_access_of_opaque_type.zig b/test/cases/compile_errors/stage1/obj/field_access_of_opaque_type.zig deleted file mode 100644 index 963c89dafe79b6ac6b7c0d63c11f30dd458725a2..0000000000000000000000000000000000000000 --- a/test/cases/compile_errors/stage1/obj/field_access_of_opaque_type.zig +++ /dev/null @@ -1,16 +0,0 @@ -const MyType = opaque {}; - -export fn entry() bool { - var x: i32 = 1; - return bar(@ptrCast(*MyType, &x)); -} - -fn bar(x: *MyType) bool { - return x.blah; -} - -// error -// backend=stage1 -// target=native -// -// tmp.zig:9:13: error: no member named 'blah' in opaque type 'MyType' diff --git a/test/cases/compile_errors/stage1/obj/field_access_of_slices.zig b/test/cases/compile_errors/stage1/obj/field_access_of_slices.zig deleted file mode 100644 index 45ca7113674e923e0c53ea970f518ac96e8cd8ba..0000000000000000000000000000000000000000 --- a/test/cases/compile_errors/stage1/obj/field_access_of_slices.zig +++ /dev/null @@ -1,11 +0,0 @@ -export fn entry() void { - var slice: []i32 = undefined; - const info = @TypeOf(slice).unknown; - _ = info; -} - -// error -// backend=stage1 -// target=native -// -// tmp.zig:3:32: error: type 'type' does not support field access diff --git a/test/cases/compile_errors/stage1/obj/field_access_of_unknown_length_pointer.zig b/test/cases/compile_errors/stage1/obj/field_access_of_unknown_length_pointer.zig deleted file mode 100644 index f9a37cabccbe99a588faf9f1e1237eb46322dcd8..0000000000000000000000000000000000000000 --- a/test/cases/compile_errors/stage1/obj/field_access_of_unknown_length_pointer.zig +++ /dev/null @@ -1,13 +0,0 @@ -const Foo = extern struct { - a: i32, -}; - -export fn entry(foo: [*]Foo) void { - foo.a += 1; -} - -// error -// backend=stage1 -// target=native -// -// tmp.zig:6:8: error: type '[*]Foo' does not support field access