checker: check fn return type mismatch (#14081)
							parent
							
								
									4400efeb9f
								
							
						
					
					
						commit
						6164654d11
					
				|  | @ -32,7 +32,8 @@ pub fn (mut c Checker) return_stmt(mut node ast.Return) { | |||
| 		} | ||||
| 	} | ||||
| 	mut got_types := []ast.Type{} | ||||
| 	for expr in node.exprs { | ||||
| 	mut expr_idxs := []int{} | ||||
| 	for i, expr in node.exprs { | ||||
| 		typ := c.expr(expr) | ||||
| 		if typ == ast.void_type { | ||||
| 			c.error('`$expr` used as value', node.pos) | ||||
|  | @ -42,9 +43,11 @@ pub fn (mut c Checker) return_stmt(mut node ast.Return) { | |||
| 		if sym.kind == .multi_return { | ||||
| 			for t in sym.mr_info().types { | ||||
| 				got_types << t | ||||
| 				expr_idxs << i | ||||
| 			} | ||||
| 		} else { | ||||
| 			got_types << typ | ||||
| 			expr_idxs << i | ||||
| 		} | ||||
| 	} | ||||
| 	node.types = got_types | ||||
|  | @ -82,7 +85,7 @@ pub fn (mut c Checker) return_stmt(mut node ast.Return) { | |||
| 		got_typ := c.unwrap_generic(got_types[i]) | ||||
| 		if got_typ.has_flag(.optional) && (!exp_type.has_flag(.optional) | ||||
| 			|| c.table.type_to_str(got_typ) != c.table.type_to_str(exp_type)) { | ||||
| 			pos := node.exprs[i].pos() | ||||
| 			pos := node.exprs[expr_idxs[i]].pos() | ||||
| 			c.error('cannot use `${c.table.type_to_str(got_typ)}` as type `${c.table.type_to_str(exp_type)}` in return argument', | ||||
| 				pos) | ||||
| 		} | ||||
|  | @ -93,19 +96,19 @@ pub fn (mut c Checker) return_stmt(mut node ast.Return) { | |||
| 				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 { | ||||
| 						c.mark_as_referenced(mut &node.exprs[i], true) | ||||
| 						c.mark_as_referenced(mut &node.exprs[expr_idxs[i]], true) | ||||
| 					} | ||||
| 				} | ||||
| 				continue | ||||
| 			} | ||||
| 			pos := node.exprs[i].pos() | ||||
| 			pos := node.exprs[expr_idxs[i]].pos() | ||||
| 			c.error('cannot use `$got_typ_sym.name` as type `${c.table.type_to_str(exp_type)}` in return argument', | ||||
| 				pos) | ||||
| 		} | ||||
| 		if (got_typ.is_ptr() || got_typ.is_pointer()) | ||||
| 			&& (!exp_type.is_ptr() && !exp_type.is_pointer()) { | ||||
| 			pos := node.exprs[i].pos() | ||||
| 			if node.exprs[i].is_auto_deref_var() { | ||||
| 			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 non reference type `${c.table.type_to_str(exp_type)}`, but you are returning `${c.table.type_to_str(got_typ)}` instead', | ||||
|  | @ -114,8 +117,8 @@ pub fn (mut c Checker) return_stmt(mut node ast.Return) { | |||
| 		if (exp_type.is_ptr() || exp_type.is_pointer()) | ||||
| 			&& (!got_typ.is_ptr() && !got_typ.is_pointer()) && got_typ != ast.int_literal_type | ||||
| 			&& !c.pref.translated && !c.file.is_translated { | ||||
| 			pos := node.exprs[i].pos() | ||||
| 			if node.exprs[i].is_auto_deref_var() { | ||||
| 			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', | ||||
|  |  | |||
|  | @ -0,0 +1,7 @@ | |||
| vlib/v/checker/tests/fn_return_type_mismatch.vv:6:9: error: cannot use `i64` as type `int` in return argument | ||||
|     4 | | ||||
|     5 | fn func2() (int, int) { | ||||
|     6 |     return func1() | ||||
|       |            ~~~~~~~ | ||||
|     7 | } | ||||
|     8 | | ||||
|  | @ -0,0 +1,9 @@ | |||
| fn func1() (i64, i64) { | ||||
| 	return i64(1), i64(2) | ||||
| } | ||||
| 
 | ||||
| fn func2() (int, int) { | ||||
| 	return func1() | ||||
| } | ||||
| 
 | ||||
| fn main() {} | ||||
		Loading…
	
		Reference in New Issue