checker: check the fn decl for anon fns too (#7529)
							parent
							
								
									b8d93df55e
								
							
						
					
					
						commit
						e03ece2a4b
					
				|  | @ -18,12 +18,6 @@ mut: | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub fn dial_udp(laddr string, raddr string) ?&UdpConn { | pub fn dial_udp(laddr string, raddr string) ?&UdpConn { | ||||||
| 	// Dont have to do this when its fixed
 |  | ||||||
| 	// this just allows us to store this `none` optional in a struct
 |  | ||||||
| 	resolve_wrapper := fn (raddr string) ?Addr { |  | ||||||
| 		x := resolve_addr(raddr, .inet, .udp) or { return none } |  | ||||||
| 		return x |  | ||||||
| 	} |  | ||||||
| 	local := resolve_addr(laddr, .inet, .udp) ? | 	local := resolve_addr(laddr, .inet, .udp) ? | ||||||
| 	sbase := new_udp_socket(local.port) ? | 	sbase := new_udp_socket(local.port) ? | ||||||
| 	sock := UdpSocket{ | 	sock := UdpSocket{ | ||||||
|  | @ -38,6 +32,13 @@ pub fn dial_udp(laddr string, raddr string) ?&UdpConn { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | fn resolve_wrapper(raddr string) ?Addr { | ||||||
|  | 	// Dont have to do this when its fixed
 | ||||||
|  | 	// this just allows us to store this `none` optional in a struct
 | ||||||
|  | 	x := resolve_addr(raddr, .inet, .udp) or { return none } | ||||||
|  | 	return x | ||||||
|  | } | ||||||
|  | 
 | ||||||
| pub fn (mut c UdpConn) write_ptr(b byteptr, len int) ? { | pub fn (mut c UdpConn) write_ptr(b byteptr, len int) ? { | ||||||
| 	remote := c.sock.remote() or { return err_no_udp_remote } | 	remote := c.sock.remote() or { return err_no_udp_remote } | ||||||
| 	return c.write_to_ptr(remote, b, len) | 	return c.write_to_ptr(remote, b, len) | ||||||
|  |  | ||||||
|  | @ -295,9 +295,8 @@ pub: | ||||||
| 
 | 
 | ||||||
| // anonymous function
 | // anonymous function
 | ||||||
| pub struct AnonFn { | pub struct AnonFn { | ||||||
| pub: |  | ||||||
| 	decl FnDecl |  | ||||||
| pub mut: | pub mut: | ||||||
|  | 	decl FnDecl | ||||||
| 	typ  table.Type // the type of anonymous fn. Both .typ and .decl.name are auto generated
 | 	typ  table.Type // the type of anonymous fn. Both .typ and .decl.name are auto generated
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -59,6 +59,7 @@ pub mut: | ||||||
| 	is_builtin_mod    bool   // are we in `builtin`?
 | 	is_builtin_mod    bool   // are we in `builtin`?
 | ||||||
| 	inside_unsafe     bool | 	inside_unsafe     bool | ||||||
| 	inside_const      bool | 	inside_const      bool | ||||||
|  | 	inside_anon_fn    bool | ||||||
| 	skip_flags        bool // should `#flag` and `#include` be skipped
 | 	skip_flags        bool // should `#flag` and `#include` be skipped
 | ||||||
| 	cur_generic_types []table.Type | 	cur_generic_types []table.Type | ||||||
| mut: | mut: | ||||||
|  | @ -3283,10 +3284,13 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type { | ||||||
| 			return node.typ | 			return node.typ | ||||||
| 		} | 		} | ||||||
| 		ast.AnonFn { | 		ast.AnonFn { | ||||||
|  | 			c.inside_anon_fn = true | ||||||
| 			keep_fn := c.cur_fn | 			keep_fn := c.cur_fn | ||||||
| 			c.cur_fn = &node.decl | 			c.cur_fn = &node.decl | ||||||
| 			c.stmts(node.decl.stmts) | 			c.stmts(node.decl.stmts) | ||||||
|  | 			c.fn_decl(mut node.decl) | ||||||
| 			c.cur_fn = keep_fn | 			c.cur_fn = keep_fn | ||||||
|  | 			c.inside_anon_fn = false | ||||||
| 			return node.typ | 			return node.typ | ||||||
| 		} | 		} | ||||||
| 		ast.ArrayDecompose { | 		ast.ArrayDecompose { | ||||||
|  | @ -5400,8 +5404,12 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) { | ||||||
| 	returns := c.returns || has_top_return(node.stmts) | 	returns := c.returns || has_top_return(node.stmts) | ||||||
| 	if node.language == .v && !node.no_body && node.return_type != table.void_type && !returns | 	if node.language == .v && !node.no_body && node.return_type != table.void_type && !returns | ||||||
| 		&& node.name !in ['panic', 'exit'] { | 		&& node.name !in ['panic', 'exit'] { | ||||||
|  | 		if c.inside_anon_fn { | ||||||
|  | 			c.error('missing return at the end of an anonymous function', node.pos) | ||||||
|  | 		} else { | ||||||
| 			c.error('missing return at end of function `$node.name`', node.pos) | 			c.error('missing return at end of function `$node.name`', node.pos) | ||||||
| 		} | 		} | ||||||
|  | 	} | ||||||
| 	c.returns = false | 	c.returns = false | ||||||
| 	node.source_file = c.file | 	node.source_file = c.file | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,3 +1,8 @@ | ||||||
|  | vlib/v/checker/tests/fn_var.vv:1:10: error: missing return at the end of an anonymous function | ||||||
|  |     1 | mut f := fn(i int) byte {} | ||||||
|  |       |          ~~~~~~~~~~~~~~~~~ | ||||||
|  |     2 | f = 4 | ||||||
|  |     3 | mut p := &f | ||||||
| vlib/v/checker/tests/fn_var.vv:2:5: error: cannot assign to `f`: expected `fn (int) byte`, not `int literal` | vlib/v/checker/tests/fn_var.vv:2:5: error: cannot assign to `f`: expected `fn (int) byte`, not `int literal` | ||||||
|     1 | mut f := fn(i int) byte {} |     1 | mut f := fn(i int) byte {} | ||||||
|     2 | f = 4 |     2 | f = 4 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue