| author | |
| committer | |
| log | a6bf8c2593ae6e60d4c4804d4e9fd87fe29885ed |
| tree | 57b34649c7efdf725967eb06ccb1af26ba077749 |
| parent | e6ebf56dd6cf2e2c23af952d2e9e327703c9cd02 |
19 files changed, 179 insertions(+), 153 deletions(-)
src/Sema.zig+38-14| ... | @@ -8378,19 +8378,15 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -8378,19 +8378,15 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 8378 | block, | 8378 | block, |
| 8379 | src, | 8379 | src, |
| 8380 | msg, | 8380 | msg, |
| 8381 | "unhandled error value: error.{s}", | 8381 | "unhandled error value: 'error.{s}'", |
| 8382 | .{error_name}, | 8382 | .{error_name}, |
| 8383 | ); | 8383 | ); |
| 8384 | } | 8384 | } |
| 8385 | } | 8385 | } |
| 8386 | 8386 | ||
| 8387 | if (maybe_msg) |msg| { | 8387 | if (maybe_msg) |msg| { |
| 8388 | try sema.mod.errNoteNonLazy( | 8388 | maybe_msg = null; |
| 8389 | operand_ty.declSrcLoc(sema.mod), | 8389 | try sema.addDeclaredHereNote(msg, operand_ty); |
| 8390 | msg, | ||
| 8391 | "error set '{}' declared here", | ||
| 8392 | .{operand_ty.fmt(sema.mod)}, | ||
| 8393 | ); | ||
| 8394 | return sema.failWithOwnedErrorMsg(block, msg); | 8390 | return sema.failWithOwnedErrorMsg(block, msg); |
| 8395 | } | 8391 | } |
| 8396 | 8392 | ||
| ... | @@ -17143,9 +17139,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr | ... | @@ -17143,9 +17139,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr |
| 17143 | const field_index = struct_obj.fields.getIndex(field_name) orelse | 17139 | const field_index = struct_obj.fields.getIndex(field_name) orelse |
| 17144 | return sema.failWithBadStructFieldAccess(block, struct_obj, name_src, field_name); | 17140 | return sema.failWithBadStructFieldAccess(block, struct_obj, name_src, field_name); |
| 17145 | 17141 | ||
| 17146 | if (field_ptr_ty.zigTypeTag() != .Pointer) { | 17142 | try sema.checkPtrOperand(block, ptr_src, field_ptr_ty); |
| 17147 | return sema.fail(block, ty_src, "expected pointer type, found '{}'", .{field_ptr_ty.fmt(sema.mod)}); | ||
| 17148 | } | ||
| 17149 | const field = struct_obj.fields.values()[field_index]; | 17143 | const field = struct_obj.fields.values()[field_index]; |
| 17150 | const field_ptr_ty_info = field_ptr_ty.ptrInfo().data; | 17144 | const field_ptr_ty_info = field_ptr_ty.ptrInfo().data; |
| 17151 | 17145 | ||
| ... | @@ -17168,8 +17162,29 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr | ... | @@ -17168,8 +17162,29 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr |
| 17168 | const result_ptr = try Type.ptr(sema.arena, sema.mod, ptr_ty_data); | 17162 | const result_ptr = try Type.ptr(sema.arena, sema.mod, ptr_ty_data); |
| 17169 | 17163 | ||
| 17170 | if (try sema.resolveDefinedValue(block, src, casted_field_ptr)) |field_ptr_val| { | 17164 | if (try sema.resolveDefinedValue(block, src, casted_field_ptr)) |field_ptr_val| { |
| 17171 | const payload = field_ptr_val.castTag(.field_ptr).?.data; | 17165 | const payload = field_ptr_val.castTag(.field_ptr) orelse { |
| 17172 | return sema.addConstant(result_ptr, payload.container_ptr); | 17166 | return sema.fail(block, ptr_src, "pointer value not based on parent struct", .{}); |
| 17167 | }; | ||
| 17168 | if (payload.data.field_index != field_index) { | ||
| 17169 | const msg = msg: { | ||
| 17170 | const msg = try sema.errMsg( | ||
| 17171 | block, | ||
| 17172 | src, | ||
| 17173 | "field '{s}' has index '{d}' but pointer value is index '{d}' of struct '{}'", | ||
| 17174 | .{ | ||
| 17175 | field_name, | ||
| 17176 | field_index, | ||
| 17177 | payload.data.field_index, | ||
| 17178 | struct_ty.fmt(sema.mod), | ||
| 17179 | }, | ||
| 17180 | ); | ||
| 17181 | errdefer msg.destroy(sema.gpa); | ||
| 17182 | try sema.addDeclaredHereNote(msg, struct_ty); | ||
| 17183 | break :msg msg; | ||
| 17184 | }; | ||
| 17185 | return sema.failWithOwnedErrorMsg(block, msg); | ||
| 17186 | } | ||
| 17187 | return sema.addConstant(result_ptr, payload.data.container_ptr); | ||
| 17173 | } | 17188 | } |
| 17174 | 17189 | ||
| 17175 | try sema.requireRuntimeBlock(block, src); | 17190 | try sema.requireRuntimeBlock(block, src); |
| ... | @@ -18515,7 +18530,16 @@ fn fieldVal( | ... | @@ -18515,7 +18530,16 @@ fn fieldVal( |
| 18515 | kw_name, child_type.fmt(sema.mod), field_name, | 18530 | kw_name, child_type.fmt(sema.mod), field_name, |
| 18516 | }); | 18531 | }); |
| 18517 | }, | 18532 | }, |
| 18518 | else => return sema.fail(block, src, "type '{}' has no members", .{child_type.fmt(sema.mod)}), | 18533 | else => { |
| 18534 | const msg = msg: { | ||
| 18535 | const msg = try sema.errMsg(block, src, "type '{}' has no members", .{child_type.fmt(sema.mod)}); | ||
| 18536 | errdefer msg.destroy(sema.gpa); | ||
| 18537 | if (child_type.isSlice()) try sema.errNote(block, src, msg, "slice values have 'len' and 'ptr' members", .{}); | ||
| 18538 | if (child_type.zigTypeTag() == .Array) try sema.errNote(block, src, msg, "array values have 'len' member", .{}); | ||
| 18539 | break :msg msg; | ||
| 18540 | }; | ||
| 18541 | return sema.failWithOwnedErrorMsg(block, msg); | ||
| 18542 | }, | ||
| 18519 | } | 18543 | } |
| 18520 | }, | 18544 | }, |
| 18521 | .Struct => if (is_pointer_to) { | 18545 | .Struct => if (is_pointer_to) { |
| ... | @@ -18739,7 +18763,7 @@ fn fieldPtr( | ... | @@ -18739,7 +18763,7 @@ fn fieldPtr( |
| 18739 | }, | 18763 | }, |
| 18740 | else => {}, | 18764 | else => {}, |
| 18741 | } | 18765 | } |
| 18742 | 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 }); | 18766 | return sema.fail(block, src, "type '{}' does not support field access", .{object_ty.fmt(sema.mod)}); |
| 18743 | } | 18767 | } |
| 18744 | 18768 | ||
| 18745 | fn fieldCallBind( | 18769 | fn fieldCallBind( |
test/cases/compile_errors/division_by_zero.zig created+17| ... | @@ -0,0 +1,17 @@ | ||
| 1 | const lit_int_x = 1 / 0; | ||
| 2 | const lit_float_x = 1.0 / 0.0; | ||
| 3 | const int_x = @as(u32, 1) / @as(u32, 0); | ||
| 4 | const float_x = @as(f32, 1.0) / @as(f32, 0.0); | ||
| 5 | |||
| 6 | export fn entry1() usize { return @sizeOf(@TypeOf(lit_int_x)); } | ||
| 7 | export fn entry2() usize { return @sizeOf(@TypeOf(lit_float_x)); } | ||
| 8 | export fn entry3() usize { return @sizeOf(@TypeOf(int_x)); } | ||
| 9 | export fn entry4() usize { return @sizeOf(@TypeOf(float_x)); } // no error on purpose | ||
| 10 | |||
| 11 | // error | ||
| 12 | // backend=stage2 | ||
| 13 | // target=native | ||
| 14 | // | ||
| 15 | // :1:23: error: division by zero here causes undefined behavior | ||
| 16 | // :2:27: error: division by zero here causes undefined behavior | ||
| 17 | // :3:29: error: division by zero here causes undefined behavior | ||
test/cases/compile_errors/error_not_handled_in_switch.zig created+21| ... | @@ -0,0 +1,21 @@ | ||
| 1 | export fn entry() void { | ||
| 2 | foo(452) catch |err| switch (err) { | ||
| 3 | error.Foo => {}, | ||
| 4 | }; | ||
| 5 | } | ||
| 6 | fn foo(x: i32) !void { | ||
| 7 | switch (x) { | ||
| 8 | 0 ... 10 => return error.Foo, | ||
| 9 | 11 ... 20 => return error.Bar, | ||
| 10 | 21 ... 30 => return error.Baz, | ||
| 11 | else => {}, | ||
| 12 | } | ||
| 13 | } | ||
| 14 | |||
| 15 | // error | ||
| 16 | // backend=llvm | ||
| 17 | // target=native | ||
| 18 | // | ||
| 19 | // :2:26: error: switch must handle all possibilities | ||
| 20 | // :2:26: note: unhandled error value: 'error.Bar' | ||
| 21 | // :2:26: note: unhandled error value: 'error.Baz' | ||
test/cases/compile_errors/fieldParentPtr-comptime_field_ptr_not_based_on_struct.zig created+17| ... | @@ -0,0 +1,17 @@ | ||
| 1 | const Foo = struct { | ||
| 2 | a: i32, | ||
| 3 | b: i32, | ||
| 4 | }; | ||
| 5 | const foo = Foo { .a = 1, .b = 2, }; | ||
| 6 | |||
| 7 | comptime { | ||
| 8 | const field_ptr = @intToPtr(*i32, 0x1234); | ||
| 9 | const another_foo_ptr = @fieldParentPtr(Foo, "b", field_ptr); | ||
| 10 | _ = another_foo_ptr; | ||
| 11 | } | ||
| 12 | |||
| 13 | // error | ||
| 14 | // backend=stage2 | ||
| 15 | // target=native | ||
| 16 | // | ||
| 17 | // :9:55: error: pointer value not based on parent struct | ||
test/cases/compile_errors/fieldParentPtr-comptime_wrong_field_index.zig created+17| ... | @@ -0,0 +1,17 @@ | ||
| 1 | const Foo = struct { | ||
| 2 | a: i32, | ||
| 3 | b: i32, | ||
| 4 | }; | ||
| 5 | const foo = Foo { .a = 1, .b = 2, }; | ||
| 6 | |||
| 7 | comptime { | ||
| 8 | const another_foo_ptr = @fieldParentPtr(Foo, "b", &foo.a); | ||
| 9 | _ = another_foo_ptr; | ||
| 10 | } | ||
| 11 | |||
| 12 | // error | ||
| 13 | // backend=stage2 | ||
| 14 | // target=native | ||
| 15 | // | ||
| 16 | // :8:29: error: field 'b' has index '1' but pointer value is index '0' of struct 'tmp.Foo' | ||
| 17 | // :1:13: note: struct declared here | ||
test/cases/compile_errors/fieldParentPtr-field_pointer_is_not_pointer.zig created+12| ... | @@ -0,0 +1,12 @@ | ||
| 1 | const Foo = extern struct { | ||
| 2 | a: i32, | ||
| 3 | }; | ||
| 4 | export fn foo(a: i32) *Foo { | ||
| 5 | return @fieldParentPtr(Foo, "a", a); | ||
| 6 | } | ||
| 7 | |||
| 8 | // error | ||
| 9 | // backend=stage2 | ||
| 10 | // target=native | ||
| 11 | // | ||
| 12 | // :5:38: error: expected pointer type, found 'i32' | ||
test/cases/compile_errors/field_access_of_opaque_type.zig created+16| ... | @@ -0,0 +1,16 @@ | ||
| 1 | const MyType = opaque {}; | ||
| 2 | |||
| 3 | export fn entry() bool { | ||
| 4 | var x: i32 = 1; | ||
| 5 | return bar(@ptrCast(*MyType, &x)); | ||
| 6 | } | ||
| 7 | |||
| 8 | fn bar(x: *MyType) bool { | ||
| 9 | return x.blah; | ||
| 10 | } | ||
| 11 | |||
| 12 | // error | ||
| 13 | // backend=stage2 | ||
| 14 | // target=native | ||
| 15 | // | ||
| 16 | // :9:13: error: type '*tmp.MyType' does not support field access | ||
test/cases/compile_errors/field_access_of_slices.zig created+12| ... | @@ -0,0 +1,12 @@ | ||
| 1 | export fn entry() void { | ||
| 2 | var slice: []i32 = undefined; | ||
| 3 | const info = @TypeOf(slice).unknown; | ||
| 4 | _ = info; | ||
| 5 | } | ||
| 6 | |||
| 7 | // error | ||
| 8 | // backend=stage2 | ||
| 9 | // target=native | ||
| 10 | // | ||
| 11 | // :3:32: error: type '[]i32' has no members | ||
| 12 | // :3:32: note: slice values have 'len' and 'ptr' members | ||
test/cases/compile_errors/field_access_of_unknown_length_pointer.zig created+13| ... | @@ -0,0 +1,13 @@ | ||
| 1 | const Foo = extern struct { | ||
| 2 | a: i32, | ||
| 3 | }; | ||
| 4 | |||
| 5 | export fn entry(foo: [*]Foo) void { | ||
| 6 | foo.a += 1; | ||
| 7 | } | ||
| 8 | |||
| 9 | // error | ||
| 10 | // backend=stage2 | ||
| 11 | // target=native | ||
| 12 | // | ||
| 13 | // :6:8: error: type '[*]tmp.Foo' does not support field access | ||
test/cases/compile_errors/stage1/error_equality_but_sets_have_no_common_members.zig created+16| ... | @@ -0,0 +1,16 @@ | ||
| 1 | const Set1 = error{A, C}; | ||
| 2 | const Set2 = error{B, D}; | ||
| 3 | export fn entry() void { | ||
| 4 | foo(Set1.A); | ||
| 5 | } | ||
| 6 | fn foo(x: Set1) void { | ||
| 7 | if (x == Set2.B) { | ||
| 8 | |||
| 9 | } | ||
| 10 | } | ||
| 11 | |||
| 12 | // error | ||
| 13 | // backend=stage1 | ||
| 14 | // target=native | ||
| 15 | // | ||
| 16 | // tmp.zig:7:11: error: error sets 'Set1' and 'Set2' have no common errors | ||
test/cases/compile_errors/stage1/obj/division_by_zero.zig deleted-18| ... | @@ -1,18 +0,0 @@ | ||
| 1 | const lit_int_x = 1 / 0; | ||
| 2 | const lit_float_x = 1.0 / 0.0; | ||
| 3 | const int_x = @as(u32, 1) / @as(u32, 0); | ||
| 4 | const float_x = @as(f32, 1.0) / @as(f32, 0.0); | ||
| 5 | |||
| 6 | export fn entry1() usize { return @sizeOf(@TypeOf(lit_int_x)); } | ||
| 7 | export fn entry2() usize { return @sizeOf(@TypeOf(lit_float_x)); } | ||
| 8 | export fn entry3() usize { return @sizeOf(@TypeOf(int_x)); } | ||
| 9 | export fn entry4() usize { return @sizeOf(@TypeOf(float_x)); } | ||
| 10 | |||
| 11 | // error | ||
| 12 | // backend=stage1 | ||
| 13 | // target=native | ||
| 14 | // | ||
| 15 | // tmp.zig:1:21: error: division by zero | ||
| 16 | // tmp.zig:2:25: error: division by zero | ||
| 17 | // tmp.zig:3:27: error: division by zero | ||
| 18 | // tmp.zig:4:31: error: division by zero | ||
test/cases/compile_errors/stage1/obj/error_equality_but_sets_have_no_common_members.zig deleted-16| ... | @@ -1,16 +0,0 @@ | ||
| 1 | const Set1 = error{A, C}; | ||
| 2 | const Set2 = error{B, D}; | ||
| 3 | export fn entry() void { | ||
| 4 | foo(Set1.A); | ||
| 5 | } | ||
| 6 | fn foo(x: Set1) void { | ||
| 7 | if (x == Set2.B) { | ||
| 8 | |||
| 9 | } | ||
| 10 | } | ||
| 11 | |||
| 12 | // error | ||
| 13 | // backend=stage1 | ||
| 14 | // target=native | ||
| 15 | // | ||
| 16 | // tmp.zig:7:11: error: error sets 'Set1' and 'Set2' have no common errors | ||
test/cases/compile_errors/stage1/obj/error_not_handled_in_switch.zig deleted-20| ... | @@ -1,20 +0,0 @@ | ||
| 1 | export fn entry() void { | ||
| 2 | foo(452) catch |err| switch (err) { | ||
| 3 | error.Foo => {}, | ||
| 4 | }; | ||
| 5 | } | ||
| 6 | fn foo(x: i32) !void { | ||
| 7 | switch (x) { | ||
| 8 | 0 ... 10 => return error.Foo, | ||
| 9 | 11 ... 20 => return error.Bar, | ||
| 10 | 21 ... 30 => return error.Baz, | ||
| 11 | else => {}, | ||
| 12 | } | ||
| 13 | } | ||
| 14 | |||
| 15 | // error | ||
| 16 | // backend=stage1 | ||
| 17 | // target=native | ||
| 18 | // | ||
| 19 | // tmp.zig:2:26: error: error.Baz not handled in switch | ||
| 20 | // tmp.zig:2:26: error: error.Bar not handled in switch | ||
test/cases/compile_errors/stage1/obj/fieldParentPtr-comptime_field_ptr_not_based_on_struct.zig deleted-17| ... | @@ -1,17 +0,0 @@ | ||
| 1 | const Foo = struct { | ||
| 2 | a: i32, | ||
| 3 | b: i32, | ||
| 4 | }; | ||
| 5 | const foo = Foo { .a = 1, .b = 2, }; | ||
| 6 | |||
| 7 | comptime { | ||
| 8 | const field_ptr = @intToPtr(*i32, 0x1234); | ||
| 9 | const another_foo_ptr = @fieldParentPtr(Foo, "b", field_ptr); | ||
| 10 | _ = another_foo_ptr; | ||
| 11 | } | ||
| 12 | |||
| 13 | // error | ||
| 14 | // backend=stage1 | ||
| 15 | // target=native | ||
| 16 | // | ||
| 17 | // tmp.zig:9:55: error: pointer value not based on parent struct | ||
test/cases/compile_errors/stage1/obj/fieldParentPtr-comptime_wrong_field_index.zig deleted-16| ... | @@ -1,16 +0,0 @@ | ||
| 1 | const Foo = struct { | ||
| 2 | a: i32, | ||
| 3 | b: i32, | ||
| 4 | }; | ||
| 5 | const foo = Foo { .a = 1, .b = 2, }; | ||
| 6 | |||
| 7 | comptime { | ||
| 8 | const another_foo_ptr = @fieldParentPtr(Foo, "b", &foo.a); | ||
| 9 | _ = another_foo_ptr; | ||
| 10 | } | ||
| 11 | |||
| 12 | // error | ||
| 13 | // backend=stage1 | ||
| 14 | // target=native | ||
| 15 | // | ||
| 16 | // tmp.zig:8:29: error: field 'b' has index 1 but pointer value is index 0 of struct 'Foo' | ||
test/cases/compile_errors/stage1/obj/fieldParentPtr-field_pointer_is_not_pointer.zig deleted-12| ... | @@ -1,12 +0,0 @@ | ||
| 1 | const Foo = extern struct { | ||
| 2 | a: i32, | ||
| 3 | }; | ||
| 4 | export fn foo(a: i32) *Foo { | ||
| 5 | return @fieldParentPtr(Foo, "a", a); | ||
| 6 | } | ||
| 7 | |||
| 8 | // error | ||
| 9 | // backend=stage1 | ||
| 10 | // target=native | ||
| 11 | // | ||
| 12 | // tmp.zig:5:38: error: expected pointer, found 'i32' | ||
test/cases/compile_errors/stage1/obj/field_access_of_opaque_type.zig deleted-16| ... | @@ -1,16 +0,0 @@ | ||
| 1 | const MyType = opaque {}; | ||
| 2 | |||
| 3 | export fn entry() bool { | ||
| 4 | var x: i32 = 1; | ||
| 5 | return bar(@ptrCast(*MyType, &x)); | ||
| 6 | } | ||
| 7 | |||
| 8 | fn bar(x: *MyType) bool { | ||
| 9 | return x.blah; | ||
| 10 | } | ||
| 11 | |||
| 12 | // error | ||
| 13 | // backend=stage1 | ||
| 14 | // target=native | ||
| 15 | // | ||
| 16 | // tmp.zig:9:13: error: no member named 'blah' in opaque type 'MyType' | ||
test/cases/compile_errors/stage1/obj/field_access_of_slices.zig deleted-11| ... | @@ -1,11 +0,0 @@ | ||
| 1 | export fn entry() void { | ||
| 2 | var slice: []i32 = undefined; | ||
| 3 | const info = @TypeOf(slice).unknown; | ||
| 4 | _ = info; | ||
| 5 | } | ||
| 6 | |||
| 7 | // error | ||
| 8 | // backend=stage1 | ||
| 9 | // target=native | ||
| 10 | // | ||
| 11 | // tmp.zig:3:32: error: type 'type' does not support field access | ||
test/cases/compile_errors/stage1/obj/field_access_of_unknown_length_pointer.zig deleted-13| ... | @@ -1,13 +0,0 @@ | ||
| 1 | const Foo = extern struct { | ||
| 2 | a: i32, | ||
| 3 | }; | ||
| 4 | |||
| 5 | export fn entry(foo: [*]Foo) void { | ||
| 6 | foo.a += 1; | ||
| 7 | } | ||
| 8 | |||
| 9 | // error | ||
| 10 | // backend=stage1 | ||
| 11 | // target=native | ||
| 12 | // | ||
| 13 | // tmp.zig:6:8: error: type '[*]Foo' does not support field access | ||