From ee782e9119af07cc24904148d7512caeab7e1690 Mon Sep 17 00:00:00 2001 From: yuyi Date: Sat, 29 Oct 2022 11:34:45 +0800 Subject: [PATCH] checker: fix return error with multi_return optional (#16250) --- vlib/v/checker/return.v | 16 ++++++++++++++++ vlib/v/tests/results_multi_return_test.v | 4 ++-- vlib/v/tests/string_optional_none_test.v | 2 +- vlib/vweb/parse.v | 6 +++--- 4 files changed, 22 insertions(+), 6 deletions(-) diff --git a/vlib/v/checker/return.v b/vlib/v/checker/return.v index 11c0f807eb..58117afefb 100644 --- a/vlib/v/checker/return.v +++ b/vlib/v/checker/return.v @@ -94,6 +94,21 @@ pub fn (mut c Checker) return_stmt(mut node ast.Return) { return } if expected_types.len > 0 && expected_types.len != got_types.len { + // `fn foo() !(int, string) { return Err{} }` + if (exp_is_optional || exp_is_result) && node.exprs.len == 1 { + got_typ := c.expr(node.exprs[0]) + got_typ_sym := c.table.sym(got_typ) + if got_typ_sym.kind == .struct_ && c.type_implements(got_typ, ast.error_type, node.pos) { + node.exprs[0] = ast.CastExpr{ + expr: node.exprs[0] + typname: 'IError' + typ: ast.error_type + expr_type: got_typ + } + node.types[0] = ast.error_type + return + } + } arg := if expected_types.len == 1 { 'argument' } else { 'arguments' } midx := imax(0, imin(expected_types.len, expr_idxs.len - 1)) mismatch_pos := node.exprs[expr_idxs[midx]].pos() @@ -138,6 +153,7 @@ pub fn (mut c Checker) return_stmt(mut node ast.Return) { } continue } + // `fn foo() !int { return Err{} }` if got_typ_sym.kind == .struct_ && c.type_implements(got_typ, ast.error_type, node.pos) { node.exprs[expr_idxs[i]] = ast.CastExpr{ diff --git a/vlib/v/tests/results_multi_return_test.v b/vlib/v/tests/results_multi_return_test.v index f8b5a2ed06..64096f5eb5 100644 --- a/vlib/v/tests/results_multi_return_test.v +++ b/vlib/v/tests/results_multi_return_test.v @@ -16,9 +16,9 @@ fn foo() ?string { } fn bar() !(string, int) { - a := foo() or { return IError(Err{ + a := foo() or { return Err{ msg: 'error test' - }) } + } } return a, 1 } diff --git a/vlib/v/tests/string_optional_none_test.v b/vlib/v/tests/string_optional_none_test.v index b381ff1254..e785fc42c1 100644 --- a/vlib/v/tests/string_optional_none_test.v +++ b/vlib/v/tests/string_optional_none_test.v @@ -12,7 +12,7 @@ fn (err MyError) code() int { } fn foo() int|none|IError { - return IError(MyError{}) + return MyError{} } fn test_string_optional_none() { diff --git a/vlib/vweb/parse.v b/vlib/vweb/parse.v index aa9662ab17..3e6e43ef75 100644 --- a/vlib/vweb/parse.v +++ b/vlib/vweb/parse.v @@ -24,7 +24,7 @@ fn parse_attrs(name string, attrs []string) !([]http.Method, string) { } if attr.starts_with('/') { if path != '' { - return IError(http.MultiplePathAttributesError{}) + return http.MultiplePathAttributesError{} } path = attr x.delete(i) @@ -33,9 +33,9 @@ fn parse_attrs(name string, attrs []string) !([]http.Method, string) { i++ } if x.len > 0 { - return IError(http.UnexpectedExtraAttributeError{ + return http.UnexpectedExtraAttributeError{ attributes: x - }) + } } if methods.len == 0 { methods = [http.Method.get]