@@ -5,6 +5,21 @@ module checker
55import v.ast
66import v.pref
77
8+ // error_type_name returns a proper type name reference for error messages
9+ // ? => Option type
10+ // ! => Result type
11+ // others => type `name`
12+ [inline ]
13+ fn (mut c Checker) error_type_name (exp_type ast.Type) string {
14+ return if exp_type == ast.void_type.set_flag (.result) {
15+ 'Result type'
16+ } else if exp_type == ast.void_type.set_flag (.option) {
17+ 'Option type'
18+ } else {
19+ 'type `${c.table.type_to_str(exp_type)} `'
20+ }
21+ }
22+
823// TODO: non deferred
924fn (mut c Checker) return_stmt (mut node ast.Return) {
1025 if c.table.cur_fn == unsafe { nil } {
@@ -22,6 +37,12 @@ fn (mut c Checker) return_stmt(mut node ast.Return) {
2237 if node.exprs.len > 0 && c.table.cur_fn.return_type == ast.void_type {
2338 c.error ('unexpected argument, current function does not return anything' , node.exprs[0 ].pos ())
2439 return
40+ } else if node.exprs.len > 1 && c.table.cur_fn.return_type == ast.void_type.set_flag (.option) {
41+ c.error ('can only return `none` from an Option-only return function' , node.exprs[0 ].pos ())
42+ return
43+ } else if node.exprs.len > 1 && c.table.cur_fn.return_type == ast.void_type.set_flag (.result) {
44+ c.error ('functions with Result-only return types can only return an error' , node.exprs[0 ].pos ())
45+ return
2546 } else if node.exprs.len == 0 && ! (c.expected_type == ast.void_type
2647 || expected_type_sym.kind == .void) {
2748 stype := c.table.type_to_str (expected_type)
@@ -100,7 +121,7 @@ fn (mut c Checker) return_stmt(mut node ast.Return) {
100121 c.warn ('Option and Result types have been split, use `!Foo` to return errors' ,
101122 node.pos)
102123 } else if exp_is_result && got_types_0_idx == ast.none_type_idx {
103- c.warn ('Option and Result types have been split, use `?Foo ` to return none' , node.pos)
124+ c.warn ('Option and Result types have been split, use `?` to return none' , node.pos)
104125 }
105126 if (exp_is_option
106127 && got_types_0_ idx in [ast.none_type_idx, ast.error_type_idx, option_type_idx])
@@ -143,13 +164,13 @@ fn (mut c Checker) return_stmt(mut node ast.Return) {
143164 got_typ := c.unwrap_generic (got_types[i])
144165 if got_typ.has_flag (.option) && got_typ.clear_flag (.option) != exp_type.clear_flag (.option) {
145166 pos := node.exprs[expr_idxs[i]].pos ()
146- c.error ('cannot use `${c.table.type_to_str(got_typ)} ` as type ` ${c.table.type_to_str (exp_type)} ` in return argument' ,
167+ c.error ('cannot use `${c.table.type_to_str(got_typ)} ` as ${c.error_type_name (exp_type)} in return argument' ,
147168 pos)
148169 }
149170 if got_typ.has_flag (.result) && (! exp_type.has_flag (.result)
150171 || c.table.type_to_str (got_typ) != c.table.type_to_str (exp_type)) {
151172 pos := node.exprs[expr_idxs[i]].pos ()
152- c.error ('cannot use `${c.table.type_to_str(got_typ)} ` as type ` ${c.table.type_to_str (exp_type)} ` in return argument' ,
173+ c.error ('cannot use `${c.table.type_to_str(got_typ)} ` as ${c.error_type_name (exp_type)} in return argument' ,
153174 pos)
154175 }
155176 if node.exprs[expr_idxs[i]] ! is ast.ComptimeCall {
@@ -161,7 +182,7 @@ fn (mut c Checker) return_stmt(mut node ast.Return) {
161182 if node.exprs[expr_idxs[i]] is ast.IntegerLiteral {
162183 var := (node.exprs[expr_idxs[i]] as ast.IntegerLiteral ).val
163184 if var[0 ] == `-` {
164- c.note ('cannot use a negative value as value of type ` ${c.table.type_to_str (exp_type)} ` in return argument' ,
185+ c.note ('cannot use a negative value as value of ${c.error_type_name (exp_type)} in return argument' ,
165186 pos)
166187 }
167188 }
@@ -194,7 +215,7 @@ fn (mut c Checker) return_stmt(mut node ast.Return) {
194215 } else {
195216 got_typ_sym.name
196217 }
197- c.error ('cannot use `${got_typ_name} ` as type ` ${c.table.type_to_str (exp_type)} ` in return argument' ,
218+ c.error ('cannot use `${got_typ_name} ` as ${c.error_type_name (exp_type)} in return argument' ,
198219 pos)
199220 }
200221 }
0 commit comments