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
return sema.fail(
block,
func_src,
call_src,
"expected {d} argument(s), found {d}",
.{ fn_params_len, uncasted_args.len },
);
@ -21275,7 +21275,7 @@ fn coerceExtra(
else => {},
},
.ErrorUnion => switch (inst_ty.zigTypeTag()) {
.ErrorUnion => {
.ErrorUnion => eu: {
if (maybe_inst_val) |inst_val| {
switch (inst_val.tag()) {
.undef => return sema.addConstUndef(dest_ty),
@ -21284,7 +21284,10 @@ fn coerceExtra(
inst_ty.errorUnionPayload(),
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 => {
const error_set = try sema.addConstant(
@ -21303,9 +21306,12 @@ fn coerceExtra(
.Undefined => {
return sema.addConstUndef(dest_ty);
},
else => {
else => eu: {
// 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()) {
@ -24795,7 +24801,7 @@ fn wrapErrorUnionPayload(
inst_src: LazySrcLoc,
) !Air.Inst.Ref {
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| {
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
// 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
// backend=stage1
// backend=llvm
// 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; }
// error
// backend=stage1
// backend=stage2
// 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
// backend=stage1
// backend=stage2
// 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
// backend=stage1
// backend=stage2
// 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