mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 12:59:04 +00:00
Merge pull request #19961 from wooster0/errorstuff
Sema: improvements to error messages related to the handling of (error) values
This commit is contained in:
commit
eb0f871cb9
35
src/Sema.zig
35
src/Sema.zig
@ -2228,8 +2228,20 @@ fn failWithModRemNegative(sema: *Sema, block: *Block, src: LazySrcLoc, lhs_ty: T
|
||||
});
|
||||
}
|
||||
|
||||
fn failWithExpectedOptionalType(sema: *Sema, block: *Block, src: LazySrcLoc, optional_ty: Type) CompileError {
|
||||
return sema.fail(block, src, "expected optional type, found '{}'", .{optional_ty.fmt(sema.mod)});
|
||||
fn failWithExpectedOptionalType(sema: *Sema, block: *Block, src: LazySrcLoc, non_optional_ty: Type) CompileError {
|
||||
const mod = sema.mod;
|
||||
const msg = msg: {
|
||||
const msg = try sema.errMsg(block, src, "expected optional type, found '{}'", .{
|
||||
non_optional_ty.fmt(mod),
|
||||
});
|
||||
errdefer msg.destroy(sema.gpa);
|
||||
if (non_optional_ty.zigTypeTag(mod) == .ErrorUnion) {
|
||||
try sema.errNote(block, src, msg, "consider using 'try', 'catch', or 'if'", .{});
|
||||
}
|
||||
try addDeclaredHereNote(sema, msg, non_optional_ty);
|
||||
break :msg msg;
|
||||
};
|
||||
return sema.failWithOwnedErrorMsg(block, msg);
|
||||
}
|
||||
|
||||
fn failWithArrayInitNotSupported(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError {
|
||||
@ -3557,9 +3569,10 @@ fn ensureResultUsed(
|
||||
const mod = sema.mod;
|
||||
switch (ty.zigTypeTag(mod)) {
|
||||
.Void, .NoReturn => return,
|
||||
.ErrorSet, .ErrorUnion => {
|
||||
.ErrorSet => return sema.fail(block, src, "error set is ignored", .{}),
|
||||
.ErrorUnion => {
|
||||
const msg = msg: {
|
||||
const msg = try sema.errMsg(block, src, "error is ignored", .{});
|
||||
const msg = try sema.errMsg(block, src, "error union is ignored", .{});
|
||||
errdefer msg.destroy(sema.gpa);
|
||||
try sema.errNote(block, src, msg, "consider using 'try', 'catch', or 'if'", .{});
|
||||
break :msg msg;
|
||||
@ -3571,7 +3584,7 @@ fn ensureResultUsed(
|
||||
const msg = try sema.errMsg(block, src, "value of type '{}' ignored", .{ty.fmt(sema.mod)});
|
||||
errdefer msg.destroy(sema.gpa);
|
||||
try sema.errNote(block, src, msg, "all non-void values must be used", .{});
|
||||
try sema.errNote(block, src, msg, "this error can be suppressed by assigning the value to '_'", .{});
|
||||
try sema.errNote(block, src, msg, "to discard the value, assign it to '_'", .{});
|
||||
break :msg msg;
|
||||
};
|
||||
return sema.failWithOwnedErrorMsg(block, msg);
|
||||
@ -3589,9 +3602,10 @@ fn zirEnsureResultNonError(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
|
||||
const src = inst_data.src();
|
||||
const operand_ty = sema.typeOf(operand);
|
||||
switch (operand_ty.zigTypeTag(mod)) {
|
||||
.ErrorSet, .ErrorUnion => {
|
||||
.ErrorSet => return sema.fail(block, src, "error set is discarded", .{}),
|
||||
.ErrorUnion => {
|
||||
const msg = msg: {
|
||||
const msg = try sema.errMsg(block, src, "error is discarded", .{});
|
||||
const msg = try sema.errMsg(block, src, "error union is discarded", .{});
|
||||
errdefer msg.destroy(sema.gpa);
|
||||
try sema.errNote(block, src, msg, "consider using 'try', 'catch', or 'if'", .{});
|
||||
break :msg msg;
|
||||
@ -9038,7 +9052,7 @@ fn analyzeOptionalPayloadPtr(
|
||||
|
||||
const opt_type = optional_ptr_ty.childType(zcu);
|
||||
if (opt_type.zigTypeTag(zcu) != .Optional) {
|
||||
return sema.fail(block, src, "expected optional type, found '{}'", .{opt_type.fmt(zcu)});
|
||||
return sema.failWithExpectedOptionalType(block, src, opt_type);
|
||||
}
|
||||
|
||||
const child_type = opt_type.optionalChild(zcu);
|
||||
@ -9531,7 +9545,7 @@ fn handleExternLibName(
|
||||
return sema.fail(
|
||||
block,
|
||||
src_loc,
|
||||
"dependency on dynamic library '{s}' requires enabling Position Independent Code. Fixed by '-l{s}' or '-fPIC'.",
|
||||
"dependency on dynamic library '{s}' requires enabling Position Independent Code; fixed by '-l{s}' or '-fPIC'",
|
||||
.{ lib_name, lib_name },
|
||||
);
|
||||
}
|
||||
@ -27875,6 +27889,9 @@ fn fieldCallBind(
|
||||
const decl = mod.declPtr(decl_idx);
|
||||
try mod.errNoteNonLazy(decl.srcLoc(mod), msg, "'{}' is not a member function", .{field_name.fmt(ip)});
|
||||
}
|
||||
if (concrete_ty.zigTypeTag(mod) == .ErrorUnion) {
|
||||
try sema.errNote(block, src, msg, "consider using 'try', 'catch', or 'if'", .{});
|
||||
}
|
||||
break :msg msg;
|
||||
};
|
||||
return sema.failWithOwnedErrorMsg(block, msg);
|
||||
|
||||
@ -1,13 +1,18 @@
|
||||
export fn entry() void {
|
||||
export fn entry1() void {
|
||||
_ = foo();
|
||||
}
|
||||
fn foo() !void {
|
||||
return error.OutOfMemory;
|
||||
}
|
||||
export fn entry2() void {
|
||||
const x: error{a} = undefined;
|
||||
_ = x;
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :2:12: error: error is discarded
|
||||
// :2:12: error: error union is discarded
|
||||
// :2:12: note: consider using 'try', 'catch', or 'if'
|
||||
// :9:9: error: error set is discarded
|
||||
|
||||
@ -0,0 +1,16 @@
|
||||
export fn foo() void {
|
||||
while (bar()) |x| {
|
||||
_ = x;
|
||||
}
|
||||
}
|
||||
const X = enum { a };
|
||||
fn bar() X {
|
||||
return .a;
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :2:15: error: expected optional type, found 'tmp.X'
|
||||
// :6:11: note: enum declared here
|
||||
@ -23,13 +23,13 @@ export fn f4() void {
|
||||
//
|
||||
// :5:30: error: value of type 'usize' ignored
|
||||
// :5:30: note: all non-void values must be used
|
||||
// :5:30: note: this error can be suppressed by assigning the value to '_'
|
||||
// :5:30: note: to discard the value, assign it to '_'
|
||||
// :9:30: error: value of type 'usize' ignored
|
||||
// :9:30: note: all non-void values must be used
|
||||
// :9:30: note: this error can be suppressed by assigning the value to '_'
|
||||
// :9:30: note: to discard the value, assign it to '_'
|
||||
// :13:31: error: value of type 'bool' ignored
|
||||
// :13:31: note: all non-void values must be used
|
||||
// :13:31: note: this error can be suppressed by assigning the value to '_'
|
||||
// :13:31: note: to discard the value, assign it to '_'
|
||||
// :16:42: error: value of type 'usize' ignored
|
||||
// :16:42: note: all non-void values must be used
|
||||
// :16:42: note: this error can be suppressed by assigning the value to '_'
|
||||
// :16:42: note: to discard the value, assign it to '_'
|
||||
|
||||
@ -24,4 +24,4 @@ pub export fn entry() void {
|
||||
//
|
||||
// :18:43: error: value of type 'type' ignored
|
||||
// :18:43: note: all non-void values must be used
|
||||
// :18:43: note: this error can be suppressed by assigning the value to '_'
|
||||
// :18:43: note: to discard the value, assign it to '_'
|
||||
|
||||
@ -11,4 +11,4 @@ fn bar() anyerror!i32 {
|
||||
//
|
||||
// :2:11: error: value of type 'i32' ignored
|
||||
// :2:11: note: all non-void values must be used
|
||||
// :2:11: note: this error can be suppressed by assigning the value to '_'
|
||||
// :2:11: note: to discard the value, assign it to '_'
|
||||
|
||||
@ -10,4 +10,4 @@ export fn foo() void {
|
||||
//
|
||||
// :3:9: error: value of type 'comptime_int' ignored
|
||||
// :3:9: note: all non-void values must be used
|
||||
// :3:9: note: this error can be suppressed by assigning the value to '_'
|
||||
// :3:9: note: to discard the value, assign it to '_'
|
||||
|
||||
@ -14,7 +14,7 @@ fn bar() u8 {
|
||||
//
|
||||
// :2:5: error: value of type 'comptime_int' ignored
|
||||
// :2:5: note: all non-void values must be used
|
||||
// :2:5: note: this error can be suppressed by assigning the value to '_'
|
||||
// :2:5: note: to discard the value, assign it to '_'
|
||||
// :5:5: error: value of type 'u8' ignored
|
||||
// :5:5: note: all non-void values must be used
|
||||
// :5:5: note: this error can be suppressed by assigning the value to '_'
|
||||
// :5:5: note: to discard the value, assign it to '_'
|
||||
|
||||
@ -5,9 +5,17 @@ fn bar() anyerror!i32 {
|
||||
return 0;
|
||||
}
|
||||
|
||||
export fn foo2() void {
|
||||
defer bar2();
|
||||
}
|
||||
fn bar2() anyerror {
|
||||
return error.a;
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :2:14: error: error is ignored
|
||||
// :2:14: error: error union is ignored
|
||||
// :2:14: note: consider using 'try', 'catch', or 'if'
|
||||
// :9:15: error: error set is ignored
|
||||
|
||||
@ -10,4 +10,4 @@ export fn foo() void {
|
||||
//
|
||||
// :3:9: error: value of type 'comptime_int' ignored
|
||||
// :3:9: note: all non-void values must be used
|
||||
// :3:9: note: this error can be suppressed by assigning the value to '_'
|
||||
// :3:9: note: to discard the value, assign it to '_'
|
||||
|
||||
@ -15,13 +15,21 @@ fn bad() anyerror!void {
|
||||
return error.Bad;
|
||||
}
|
||||
|
||||
export fn d() void {
|
||||
while (true) : (bad2()) {}
|
||||
}
|
||||
fn bad2() anyerror {
|
||||
return error.Bad;
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :2:24: error: error is ignored
|
||||
// :2:24: error: error union is ignored
|
||||
// :2:24: note: consider using 'try', 'catch', or 'if'
|
||||
// :7:25: error: error is ignored
|
||||
// :7:25: error: error union is ignored
|
||||
// :7:25: note: consider using 'try', 'catch', or 'if'
|
||||
// :12:25: error: error is ignored
|
||||
// :12:25: error: error union is ignored
|
||||
// :12:25: note: consider using 'try', 'catch', or 'if'
|
||||
// :19:25: error: error set is ignored
|
||||
|
||||
@ -11,4 +11,4 @@ fn bar() i32 {
|
||||
//
|
||||
// :2:8: error: value of type 'i32' ignored
|
||||
// :2:8: note: all non-void values must be used
|
||||
// :2:8: note: this error can be suppressed by assigning the value to '_'
|
||||
// :2:8: note: to discard the value, assign it to '_'
|
||||
|
||||
@ -8,4 +8,4 @@ export fn foo() void {
|
||||
//
|
||||
// :2:5: error: value of type 'comptime_int' ignored
|
||||
// :2:5: note: all non-void values must be used
|
||||
// :2:5: note: this error can be suppressed by assigning the value to '_'
|
||||
// :2:5: note: to discard the value, assign it to '_'
|
||||
|
||||
21
test/cases/compile_errors/method_call_on_error_union.zig
Normal file
21
test/cases/compile_errors/method_call_on_error_union.zig
Normal file
@ -0,0 +1,21 @@
|
||||
const X = struct {
|
||||
fn init() !X {
|
||||
return error.a;
|
||||
}
|
||||
|
||||
fn a(x: X) void {
|
||||
_ = x;
|
||||
}
|
||||
};
|
||||
|
||||
export fn entry() void {
|
||||
const x = X.init();
|
||||
x.a();
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :13:6: error: no field or member function named 'a' in '@typeInfo(@typeInfo(@TypeOf(tmp.X.init)).Fn.return_type.?).ErrorUnion.error_set!tmp.X'
|
||||
// :13:6: note: consider using 'try', 'catch', or 'if'
|
||||
@ -12,3 +12,4 @@ fn bar() anyerror!i32 {
|
||||
// target=native
|
||||
//
|
||||
// :2:15: error: expected optional type, found 'anyerror!i32'
|
||||
// :2:15: note: consider using 'try', 'catch', or 'if'
|
||||
|
||||
@ -32,16 +32,16 @@ export fn f5() void {
|
||||
//
|
||||
// :5:25: error: value of type 'usize' ignored
|
||||
// :5:25: note: all non-void values must be used
|
||||
// :5:25: note: this error can be suppressed by assigning the value to '_'
|
||||
// :5:25: note: to discard the value, assign it to '_'
|
||||
// :10:26: error: value of type 'usize' ignored
|
||||
// :10:26: note: all non-void values must be used
|
||||
// :10:26: note: this error can be suppressed by assigning the value to '_'
|
||||
// :10:26: note: to discard the value, assign it to '_'
|
||||
// :15:26: error: value of type 'usize' ignored
|
||||
// :15:26: note: all non-void values must be used
|
||||
// :15:26: note: this error can be suppressed by assigning the value to '_'
|
||||
// :15:26: note: to discard the value, assign it to '_'
|
||||
// :20:23: error: value of type 'bool' ignored
|
||||
// :20:23: note: all non-void values must be used
|
||||
// :20:23: note: this error can be suppressed by assigning the value to '_'
|
||||
// :20:23: note: to discard the value, assign it to '_'
|
||||
// :25:34: error: value of type 'usize' ignored
|
||||
// :25:34: note: all non-void values must be used
|
||||
// :25:34: note: this error can be suppressed by assigning the value to '_'
|
||||
// :25:34: note: to discard the value, assign it to '_'
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user