1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

checker: minor cleanup in return_stmt() (#17995)

This commit is contained in:
yuyi 2023-04-22 00:32:59 +08:00 committed by GitHub
parent adcd16b198
commit eb410bf283
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -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 { if expected_types.len > 0 && expected_types.len != got_types.len {
// `fn foo() !(int, string) { return Err{} }` // `fn foo() !(int, string) { return Err{} }`
if (exp_is_option || exp_is_result) && node.exprs.len == 1 { if (exp_is_option || exp_is_result) && node.exprs.len == 1 {
got_typ := c.expr(node.exprs[0]) got_type := c.expr(node.exprs[0])
got_typ_sym := c.table.sym(got_typ) got_type_sym := c.table.sym(got_type)
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[0] = ast.CastExpr{ node.exprs[0] = ast.CastExpr{
expr: node.exprs[0] expr: node.exprs[0]
typname: 'IError' typname: 'IError'
typ: ast.error_type typ: ast.error_type
expr_type: got_typ expr_type: got_type
pos: node.pos pos: node.pos
} }
node.types[0] = ast.error_type 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) c.error('should not unwrap option var on return, it could be none', node.pos)
} }
} }
got_typ := c.unwrap_generic(got_types[i]) got_type := c.unwrap_generic(got_types[i])
if got_typ.has_flag(.option) && got_typ.clear_flag(.option) != exp_type.clear_flag(.option) { if got_type.has_flag(.option)
&& got_type.clear_flag(.option) != exp_type.clear_flag(.option) {
pos := node.exprs[expr_idxs[i]].pos() 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) pos)
} }
if got_typ.has_flag(.result) && (!exp_type.has_flag(.result) if got_type.has_flag(.result) && (!exp_type.has_flag(.result)
|| c.table.type_to_str(got_typ) != c.table.type_to_str(exp_type)) { || c.table.type_to_str(got_type) != c.table.type_to_str(exp_type)) {
pos := node.exprs[expr_idxs[i]].pos() 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) pos)
} }
if node.exprs[expr_idxs[i]] !is ast.ComptimeCall { if node.exprs[expr_idxs[i]] !is ast.ComptimeCall {
got_typ_sym := c.table.sym(got_typ) got_type_sym := c.table.sym(got_type)
exp_typ_sym := c.table.sym(exp_type) exp_type_sym := c.table.sym(exp_type)
pos := node.exprs[expr_idxs[i]].pos() pos := node.exprs[expr_idxs[i]].pos()
if c.check_types(got_typ, exp_type) { if c.check_types(got_type, exp_type) {
if exp_type.is_unsigned() && got_typ.is_int_literal() { if exp_type.is_unsigned() && got_type.is_int_literal() {
if node.exprs[expr_idxs[i]] is ast.IntegerLiteral { if node.exprs[expr_idxs[i]] is ast.IntegerLiteral {
var := (node.exprs[expr_idxs[i]] as ast.IntegerLiteral).val var := (node.exprs[expr_idxs[i]] as ast.IntegerLiteral).val
if var[0] == `-` { if var[0] == `-` {
@ -188,60 +190,58 @@ fn (mut c Checker) return_stmt(mut node ast.Return) {
} }
} }
} else { } else {
if exp_typ_sym.kind == .interface_ { if exp_type_sym.kind == .interface_ {
if c.type_implements(got_typ, exp_type, node.pos) { if c.type_implements(got_type, exp_type, node.pos) {
if !got_typ.is_ptr() && !got_typ.is_pointer() if !got_type.is_ptr() && !got_type.is_pointer()
&& got_typ_sym.kind != .interface_ && !c.inside_unsafe { && got_type_sym.kind != .interface_ && !c.inside_unsafe {
c.mark_as_referenced(mut &node.exprs[expr_idxs[i]], true) c.mark_as_referenced(mut &node.exprs[expr_idxs[i]], true)
} }
} }
continue continue
} }
// `fn foo() !int { return Err{} }` // `fn foo() !int { return Err{} }`
if got_typ_sym.kind == .struct_ if got_type_sym.kind == .struct_
&& c.type_implements(got_typ, ast.error_type, node.pos) { && c.type_implements(got_type, ast.error_type, node.pos) {
node.exprs[expr_idxs[i]] = ast.CastExpr{ node.exprs[expr_idxs[i]] = ast.CastExpr{
expr: node.exprs[expr_idxs[i]] expr: node.exprs[expr_idxs[i]]
typname: 'IError' typname: 'IError'
typ: ast.error_type typ: ast.error_type
expr_type: got_typ expr_type: got_type
pos: node.pos pos: node.pos
} }
node.types[expr_idxs[i]] = ast.error_type node.types[expr_idxs[i]] = ast.error_type
continue continue
} }
got_typ_name := if got_typ_sym.kind == .function { got_type_name := if got_type_sym.kind == .function {
'${c.table.type_to_str(got_typ)}' '${c.table.type_to_str(got_type)}'
} else { } 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) pos)
} }
} }
unaliased_exp_typ := c.table.unaliased_type(exp_type) if got_type.is_real_pointer() && !exp_type.is_real_pointer()
if got_typ.is_real_pointer() && !exp_type.is_real_pointer() && !c.table.unaliased_type(exp_type).is_real_pointer() {
&& !unaliased_exp_typ.is_real_pointer() {
pos := node.exprs[expr_idxs[i]].pos() pos := node.exprs[expr_idxs[i]].pos()
if node.exprs[expr_idxs[i]].is_auto_deref_var() { if node.exprs[expr_idxs[i]].is_auto_deref_var() {
continue continue
} }
c.add_error_detail('use `return *pointer` instead of `return pointer`, and just `return value` instead of `return &value`') 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) pos)
} }
unaliased_got_typ := c.table.unaliased_type(got_typ) if exp_type.is_real_pointer() && !got_type.is_real_pointer()
if exp_type.is_real_pointer() && !got_typ.is_real_pointer() && !c.table.unaliased_type(got_type).is_real_pointer()
&& !unaliased_got_typ.is_real_pointer() && got_typ != ast.int_literal_type && got_type != ast.int_literal_type && !c.pref.translated && !c.file.is_translated {
&& !c.pref.translated && !c.file.is_translated {
pos := node.exprs[expr_idxs[i]].pos() pos := node.exprs[expr_idxs[i]].pos()
if node.exprs[expr_idxs[i]].is_auto_deref_var() { if node.exprs[expr_idxs[i]].is_auto_deref_var() {
continue 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) 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]] mut r_expr := &node.exprs[expr_idxs[i]]
if mut r_expr is ast.Ident { if mut r_expr is ast.Ident {
if mut r_expr.obj is ast.Var { if mut r_expr.obj is ast.Var {