From f5471299d81e809c706e147d2ea79c83aeb8b650 Mon Sep 17 00:00:00 2001 From: Sebsatian Keller Date: Thu, 10 Feb 2022 02:35:53 +0100 Subject: [PATCH] stage 1: improve error message if error union is cast to payload (#10770) Also: Added special error message for for `?T` to `T` casting --- src/stage1/ir.cpp | 28 ++++++++++++++++++++++++++++ test/compile_errors.zig | 14 +++++++------- 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/src/stage1/ir.cpp b/src/stage1/ir.cpp index be6226313f..0b6332f480 100644 --- a/src/stage1/ir.cpp +++ b/src/stage1/ir.cpp @@ -8242,6 +8242,34 @@ static Stage1AirInst *ir_analyze_cast(IrAnalyze *ira, Scope *scope, AstNode *sou return ir_implicit_cast2(ira, scope, source_node, cast1, wanted_type); } + // E!T to T + if (actual_type->id == ZigTypeIdErrorUnion) { + if (types_match_const_cast_only(ira, actual_type->data.error_union.payload_type, wanted_type, + source_node, false).id == ConstCastResultIdOk) + { + ErrorMsg *parent_msg = ir_add_error_node(ira, source_node, + buf_sprintf("cannot convert error union to payload type. consider using `try`, `catch`, or `if`. expected type '%s', found '%s'", + buf_ptr(&wanted_type->name), + buf_ptr(&actual_type->name))); + report_recursive_error(ira, source_node, &const_cast_result, parent_msg); + return ira->codegen->invalid_inst_gen; + } + } + + //?T to T + if (actual_type->id == ZigTypeIdOptional) { + if (types_match_const_cast_only(ira, actual_type->data.maybe.child_type, wanted_type, + source_node, false).id == ConstCastResultIdOk) + { + ErrorMsg *parent_msg = ir_add_error_node(ira, source_node, + buf_sprintf("cannot convert optional to payload type. consider using `.?`, `orelse`, or `if`. expected type '%s', found '%s'", + buf_ptr(&wanted_type->name), + buf_ptr(&actual_type->name))); + report_recursive_error(ira, source_node, &const_cast_result, parent_msg); + return ira->codegen->invalid_inst_gen; + } + } + ErrorMsg *parent_msg = ir_add_error_node(ira, source_node, buf_sprintf("expected type '%s', found '%s'", buf_ptr(&wanted_type->name), diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 252ec1496b..3c224013c9 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -790,9 +790,9 @@ pub fn addCases(ctx: *TestContext) !void { "tmp.zig:1:17: note: function cannot return an error", "tmp.zig:8:5: error: expected type 'void', found '@typeInfo(@typeInfo(@TypeOf(bar)).Fn.return_type.?).ErrorUnion.error_set'", "tmp.zig:7:17: note: function cannot return an error", - "tmp.zig:11:15: error: expected type 'u32', found '@typeInfo(@typeInfo(@TypeOf(bar)).Fn.return_type.?).ErrorUnion.error_set!u32'", + "tmp.zig:11:15: error: cannot convert error union to payload type. consider using `try`, `catch`, or `if`. expected type 'u32', found '@typeInfo(@typeInfo(@TypeOf(bar)).Fn.return_type.?).ErrorUnion.error_set!u32'", "tmp.zig:10:17: note: function cannot return an error", - "tmp.zig:15:14: error: expected type 'u32', found '@typeInfo(@typeInfo(@TypeOf(bar)).Fn.return_type.?).ErrorUnion.error_set!u32'", + "tmp.zig:15:14: error: cannot convert error union to payload type. consider using `try`, `catch`, or `if`. expected type 'u32', found '@typeInfo(@typeInfo(@TypeOf(bar)).Fn.return_type.?).ErrorUnion.error_set!u32'", "tmp.zig:14:5: note: cannot store an error in type 'u32'", }); @@ -1879,7 +1879,7 @@ pub fn addCases(ctx: *TestContext) !void { \\ _ = afoo; \\} , &[_][]const u8{ - "tmp.zig:12:25: error: expected type 'u32', found '@typeInfo(@typeInfo(@TypeOf(get_uval)).Fn.return_type.?).ErrorUnion.error_set!u32'", + "tmp.zig:12:25: error: cannot convert error union to payload type. consider using `try`, `catch`, or `if`. expected type 'u32', found '@typeInfo(@typeInfo(@TypeOf(get_uval)).Fn.return_type.?).ErrorUnion.error_set!u32'", }); ctx.objErrStage1("assigning to struct or union fields that are not optionals with a function that returns an optional", @@ -1899,7 +1899,7 @@ pub fn addCases(ctx: *TestContext) !void { \\ _ = s; \\} , &[_][]const u8{ - "tmp.zig:11:27: error: expected type 'u8', found '?u8'", + "tmp.zig:11:27: error: cannot convert optional to payload type. consider using `.?`, `orelse`, or `if`. expected type 'u8', found '?u8'", }); ctx.objErrStage1("missing result type for phi node", @@ -2308,7 +2308,7 @@ pub fn addCases(ctx: *TestContext) !void { \\ not_optional: i32, \\}; , &[_][]const u8{ - "tmp.zig:3:36: error: expected type 'i32', found '?i32'", + "tmp.zig:3:36: error: cannot convert optional to payload type. consider using `.?`, `orelse`, or `if`. expected type 'i32', found '?i32'", }); ctx.objErrStage1("result location incompatibility mismatching handle_is_ptr", @@ -2325,7 +2325,7 @@ pub fn addCases(ctx: *TestContext) !void { \\ not_optional: i32, \\}; , &[_][]const u8{ - "tmp.zig:3:36: error: expected type 'i32', found '?i32'", + "tmp.zig:3:36: error: cannot convert optional to payload type. consider using `.?`, `orelse`, or `if`. expected type 'i32', found '?i32'", }); ctx.objErrStage1("const frame cast to anyframe", @@ -8828,7 +8828,7 @@ pub fn addCases(ctx: *TestContext) !void { \\ v = u; \\} , &[_][]const u8{ - "tmp.zig:4:9: error: expected type '*anyopaque', found '?*anyopaque'", + "tmp.zig:4:9: error: cannot convert optional to payload type. consider using `.?`, `orelse`, or `if`. expected type '*anyopaque', found '?*anyopaque'", }); ctx.objErrStage1("Issue #6823: don't allow .* to be followed by **",