Sema: better error when coercing error sets

This commit is contained in:
Veikka Tuominen 2022-07-26 15:39:47 +03:00
parent 7862ab9f41
commit d6e3988fe8
10 changed files with 53 additions and 45 deletions

View file

@ -5496,7 +5496,7 @@ fn analyzeCall(
// TODO add error note: declared here // TODO add error note: declared here
return sema.fail( return sema.fail(
block, block,
func_src, call_src,
"expected {d} argument(s), found {d}", "expected {d} argument(s), found {d}",
.{ fn_params_len, uncasted_args.len }, .{ fn_params_len, uncasted_args.len },
); );
@ -21275,7 +21275,7 @@ fn coerceExtra(
else => {}, else => {},
}, },
.ErrorUnion => switch (inst_ty.zigTypeTag()) { .ErrorUnion => switch (inst_ty.zigTypeTag()) {
.ErrorUnion => { .ErrorUnion => eu: {
if (maybe_inst_val) |inst_val| { if (maybe_inst_val) |inst_val| {
switch (inst_val.tag()) { switch (inst_val.tag()) {
.undef => return sema.addConstUndef(dest_ty), .undef => return sema.addConstUndef(dest_ty),
@ -21284,7 +21284,10 @@ fn coerceExtra(
inst_ty.errorUnionPayload(), inst_ty.errorUnionPayload(),
inst_val.castTag(.eu_payload).?.data, inst_val.castTag(.eu_payload).?.data,
); );
return sema.wrapErrorUnionPayload(block, dest_ty, payload, inst_src); return sema.wrapErrorUnionPayload(block, dest_ty, payload, inst_src) catch |err| switch (err) {
error.NotCoercible => break :eu,
else => |e| return e,
};
}, },
else => { else => {
const error_set = try sema.addConstant( const error_set = try sema.addConstant(
@ -21303,9 +21306,12 @@ fn coerceExtra(
.Undefined => { .Undefined => {
return sema.addConstUndef(dest_ty); return sema.addConstUndef(dest_ty);
}, },
else => { else => eu: {
// T to E!T // T to E!T
return sema.wrapErrorUnionPayload(block, dest_ty, inst, inst_src); return sema.wrapErrorUnionPayload(block, dest_ty, inst, inst_src) catch |err| switch (err) {
error.NotCoercible => break :eu,
else => |e| return e,
};
}, },
}, },
.Union => switch (inst_ty.zigTypeTag()) { .Union => switch (inst_ty.zigTypeTag()) {
@ -24795,7 +24801,7 @@ fn wrapErrorUnionPayload(
inst_src: LazySrcLoc, inst_src: LazySrcLoc,
) !Air.Inst.Ref { ) !Air.Inst.Ref {
const dest_payload_ty = dest_ty.errorUnionPayload(); const dest_payload_ty = dest_ty.errorUnionPayload();
const coerced = try sema.coerce(block, dest_payload_ty, inst, inst_src); const coerced = try sema.coerceExtra(block, dest_payload_ty, inst, inst_src, false, false);
if (try sema.resolveMaybeUndefVal(block, inst_src, coerced)) |val| { if (try sema.resolveMaybeUndefVal(block, inst_src, coerced)) |val| {
return sema.addConstant(dest_ty, try Value.Tag.eu_payload.create(sema.arena, val)); return sema.addConstant(dest_ty, try Value.Tag.eu_payload.create(sema.arena, val));
} }

View file

@ -0,0 +1,11 @@
export fn entry() void {
var foo: u32 = @This(){};
_ = foo;
}
// error
// backend=stage2
// target=native
//
// :2:27: error: expected type 'u32', found 'tmp.tmp'
// :1:1: note: struct declared here

View file

@ -0,0 +1,19 @@
const NextError = error{NextError};
const OtherError = error{OutOfMemory};
export fn entry() void {
const a: ?NextError!i32 = foo();
_ = a;
}
fn foo() ?OtherError!i32 {
return null;
}
// error
// backend=llvm
// target=native
//
// :4:1: error: expected type '?error{NextError}!i32', found '?error{OutOfMemory}!i32'
// :4:1: note: optional type child 'error{OutOfMemory}!i32' cannot cast into optional type child 'error{NextError}!i32'
// :4:1: note: 'error.OutOfMemory' not a member of destination error set

View file

@ -5,4 +5,4 @@ test "example" { return 1; }
// target=native // target=native
// is_test=1 // is_test=1
// //
// :1:25: error: expected type 'void', found 'comptime_int' // :1:25: error: expected type '@typeInfo(@typeInfo(@TypeOf(tmp.test.example)).Fn.return_type.?).ErrorUnion.error_set!void', found 'comptime_int'

View file

@ -1,10 +0,0 @@
export fn entry() void {
var foo: u32 = @This(){};
_ = foo;
}
// error
// backend=stage1
// target=native
//
// tmp.zig:2:27: error: type 'u32' does not support array initialization

View file

@ -1,20 +0,0 @@
const NextError = error{NextError};
const OtherError = error{OutOfMemory};
export fn entry() void {
const a: ?NextError!i32 = foo();
_ = a;
}
fn foo() ?OtherError!i32 {
return null;
}
// error
// backend=stage1
// target=native
//
// tmp.zig:5:34: error: expected type '?NextError!i32', found '?OtherError!i32'
// tmp.zig:5:34: note: optional type child 'OtherError!i32' cannot cast into optional type child 'NextError!i32'
// tmp.zig:5:34: note: error set 'OtherError' cannot cast into error set 'NextError'
// tmp.zig:2:26: note: 'error.OutOfMemory' not a member of destination error set

View file

@ -3,7 +3,7 @@ export fn entry() void {
} }
// error // error
// backend=stage1 // backend=llvm
// target=native // target=native
// //
// ?:?:?: error: 10 unused arguments in '{d} {d} {d} {d} {d}' // :?:?: error: 10 unused arguments in '{d} {d} {d} {d} {d}'

View file

@ -4,7 +4,7 @@ export fn a() void {
fn c(d: i32, e: i32, f: i32) void { _ = d; _ = e; _ = f; } fn c(d: i32, e: i32, f: i32) void { _ = d; _ = e; _ = f; }
// error // error
// backend=stage1 // backend=stage2
// target=native // target=native
// //
// tmp.zig:2:6: error: expected 3 argument(s), found 1 // :2:6: error: expected 3 argument(s), found 1

View file

@ -4,7 +4,8 @@ export fn entry() void {
} }
// error // error
// backend=stage1 // backend=stage2
// target=native // target=native
// //
// tmp.zig:3:47: error: expected type 'std.builtin.AtomicOrder', found 'u32' // :3:47: error: expected type 'builtin.AtomicOrder', found 'u32'
// :?:?: note: enum declared here

View file

@ -4,7 +4,8 @@ comptime {
} }
// error // error
// backend=stage1 // backend=stage2
// target=native // target=native
// //
// tmp.zig:3:59: error: expected type 'std.builtin.GlobalLinkage', found 'comptime_int' // :3:50: error: expected type 'builtin.GlobalLinkage', found 'u32'
// :?:?: note: enum declared here