diff --git a/vlib/v/checker/return.v b/vlib/v/checker/return.v index 43d9221b65..ac95dfd0fb 100644 --- a/vlib/v/checker/return.v +++ b/vlib/v/checker/return.v @@ -131,14 +131,15 @@ fn (mut c Checker) return_stmt(mut node ast.Return) { if expected_types.len > 0 && expected_types.len != got_types.len { // `fn foo() !(int, string) { return Err{} }` if (exp_is_option || 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) { + got_type := c.expr(node.exprs[0]) + got_type_sym := c.table.sym(got_type) + if got_type_sym.kind == .struct_ + && c.type_implements(got_type, ast.error_type, node.pos) { node.exprs[0] = ast.CastExpr{ expr: node.exprs[0] typname: 'IError' typ: ast.error_type - expr_type: got_typ + expr_type: got_type pos: node.pos } node.types[0] = ast.error_type @@ -161,24 +162,25 @@ fn (mut c Checker) return_stmt(mut node ast.Return) { c.error('should not unwrap option var on return, it could be none', node.pos) } } - got_typ := c.unwrap_generic(got_types[i]) - if got_typ.has_flag(.option) && got_typ.clear_flag(.option) != exp_type.clear_flag(.option) { + got_type := c.unwrap_generic(got_types[i]) + if got_type.has_flag(.option) + && got_type.clear_flag(.option) != exp_type.clear_flag(.option) { pos := node.exprs[expr_idxs[i]].pos() - c.error('cannot use `${c.table.type_to_str(got_typ)}` as ${c.error_type_name(exp_type)} in return argument', + c.error('cannot use `${c.table.type_to_str(got_type)}` as ${c.error_type_name(exp_type)} in return argument', pos) } - if got_typ.has_flag(.result) && (!exp_type.has_flag(.result) - || c.table.type_to_str(got_typ) != c.table.type_to_str(exp_type)) { + if got_type.has_flag(.result) && (!exp_type.has_flag(.result) + || c.table.type_to_str(got_type) != c.table.type_to_str(exp_type)) { pos := node.exprs[expr_idxs[i]].pos() - c.error('cannot use `${c.table.type_to_str(got_typ)}` as ${c.error_type_name(exp_type)} in return argument', + c.error('cannot use `${c.table.type_to_str(got_type)}` as ${c.error_type_name(exp_type)} in return argument', pos) } if node.exprs[expr_idxs[i]] !is ast.ComptimeCall { - got_typ_sym := c.table.sym(got_typ) - exp_typ_sym := c.table.sym(exp_type) + got_type_sym := c.table.sym(got_type) + exp_type_sym := c.table.sym(exp_type) pos := node.exprs[expr_idxs[i]].pos() - if c.check_types(got_typ, exp_type) { - if exp_type.is_unsigned() && got_typ.is_int_literal() { + if c.check_types(got_type, exp_type) { + if exp_type.is_unsigned() && got_type.is_int_literal() { if node.exprs[expr_idxs[i]] is ast.IntegerLiteral { var := (node.exprs[expr_idxs[i]] as ast.IntegerLiteral).val if var[0] == `-` { @@ -188,60 +190,58 @@ fn (mut c Checker) return_stmt(mut node ast.Return) { } } } else { - if exp_typ_sym.kind == .interface_ { - if c.type_implements(got_typ, exp_type, node.pos) { - if !got_typ.is_ptr() && !got_typ.is_pointer() - && got_typ_sym.kind != .interface_ && !c.inside_unsafe { + if exp_type_sym.kind == .interface_ { + if c.type_implements(got_type, exp_type, node.pos) { + if !got_type.is_ptr() && !got_type.is_pointer() + && got_type_sym.kind != .interface_ && !c.inside_unsafe { c.mark_as_referenced(mut &node.exprs[expr_idxs[i]], true) } } continue } // `fn foo() !int { return Err{} }` - if got_typ_sym.kind == .struct_ - && c.type_implements(got_typ, ast.error_type, node.pos) { + if got_type_sym.kind == .struct_ + && c.type_implements(got_type, ast.error_type, node.pos) { node.exprs[expr_idxs[i]] = ast.CastExpr{ expr: node.exprs[expr_idxs[i]] typname: 'IError' typ: ast.error_type - expr_type: got_typ + expr_type: got_type pos: node.pos } node.types[expr_idxs[i]] = ast.error_type continue } - got_typ_name := if got_typ_sym.kind == .function { - '${c.table.type_to_str(got_typ)}' + got_type_name := if got_type_sym.kind == .function { + '${c.table.type_to_str(got_type)}' } else { - got_typ_sym.name + got_type_sym.name } - c.error('cannot use `${got_typ_name}` as ${c.error_type_name(exp_type)} in return argument', + c.error('cannot use `${got_type_name}` as ${c.error_type_name(exp_type)} in return argument', pos) } } - unaliased_exp_typ := c.table.unaliased_type(exp_type) - if got_typ.is_real_pointer() && !exp_type.is_real_pointer() - && !unaliased_exp_typ.is_real_pointer() { + if got_type.is_real_pointer() && !exp_type.is_real_pointer() + && !c.table.unaliased_type(exp_type).is_real_pointer() { pos := node.exprs[expr_idxs[i]].pos() if node.exprs[expr_idxs[i]].is_auto_deref_var() { continue } c.add_error_detail('use `return *pointer` instead of `return pointer`, and just `return value` instead of `return &value`') - c.error('fn `${c.table.cur_fn.name}` expects you to return a non reference type `${c.table.type_to_str(exp_type)}`, but you are returning `${c.table.type_to_str(got_typ)}` instead', + c.error('fn `${c.table.cur_fn.name}` expects you to return a non reference type `${c.table.type_to_str(exp_type)}`, but you are returning `${c.table.type_to_str(got_type)}` instead', pos) } - unaliased_got_typ := c.table.unaliased_type(got_typ) - if exp_type.is_real_pointer() && !got_typ.is_real_pointer() - && !unaliased_got_typ.is_real_pointer() && got_typ != ast.int_literal_type - && !c.pref.translated && !c.file.is_translated { + if exp_type.is_real_pointer() && !got_type.is_real_pointer() + && !c.table.unaliased_type(got_type).is_real_pointer() + && got_type != ast.int_literal_type && !c.pref.translated && !c.file.is_translated { pos := node.exprs[expr_idxs[i]].pos() if node.exprs[expr_idxs[i]].is_auto_deref_var() { continue } - c.error('fn `${c.table.cur_fn.name}` expects you to return a reference type `${c.table.type_to_str(exp_type)}`, but you are returning `${c.table.type_to_str(got_typ)}` instead', + c.error('fn `${c.table.cur_fn.name}` expects you to return a reference type `${c.table.type_to_str(exp_type)}`, but you are returning `${c.table.type_to_str(got_type)}` instead', pos) } - if exp_type.is_ptr() && got_typ.is_ptr() { + if exp_type.is_ptr() && got_type.is_ptr() { mut r_expr := &node.exprs[expr_idxs[i]] if mut r_expr is ast.Ident { if mut r_expr.obj is ast.Var {