checker: error on redefining any of the public builtin functions, not just ['print', 'println', 'eprint', 'eprintln', 'isnil', 'panic', 'exit'] (#13419)
							parent
							
								
									43d6b97c21
								
							
						
					
					
						commit
						9ed18efa53
					
				|  | @ -449,8 +449,9 @@ pub mut: | |||
| // function or method declaration
 | ||||
| pub struct FnDecl { | ||||
| pub: | ||||
| 	name            string | ||||
| 	mod             string | ||||
| 	name            string // 'math.bits.normalize'
 | ||||
| 	short_name      string // 'normalize'
 | ||||
| 	mod             string // 'math.bits'
 | ||||
| 	is_deprecated   bool | ||||
| 	is_pub          bool | ||||
| 	is_variadic     bool | ||||
|  |  | |||
|  | @ -41,6 +41,7 @@ pub mut: | |||
| 	enum_decls        map[string]EnumDecl | ||||
| 	mdeprecated_msg   map[string]string    // module deprecation message
 | ||||
| 	mdeprecated_after map[string]time.Time // module deprecation date
 | ||||
| 	builtin_pub_fns   map[string]bool | ||||
| } | ||||
| 
 | ||||
| // used by vls to avoid leaks
 | ||||
|  | @ -315,6 +316,9 @@ pub fn (mut t Table) mark_module_as_deprecated_after(mname string, after_date st | |||
| 
 | ||||
| pub fn (mut t Table) register_fn(new_fn Fn) { | ||||
| 	t.fns[new_fn.name] = new_fn | ||||
| 	if new_fn.is_pub && new_fn.mod == 'builtin' { | ||||
| 		t.builtin_pub_fns[new_fn.name] = true | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| pub fn (mut t Table) register_interface(idecl InterfaceDecl) { | ||||
|  |  | |||
|  | @ -70,6 +70,9 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) { | |||
| 	} | ||||
| 	if node.language == .v && !c.is_builtin_mod && !node.is_anon { | ||||
| 		c.check_valid_snake_case(node.name, 'function name', node.pos) | ||||
| 		if !node.is_method && node.mod == 'main' && node.short_name in c.table.builtin_pub_fns { | ||||
| 			c.error('cannot redefine builtin public function `$node.short_name`', node.pos) | ||||
| 		} | ||||
| 	} | ||||
| 	if node.name == 'main.main' { | ||||
| 		c.main_fn_decl_node = *node | ||||
|  |  | |||
|  | @ -0,0 +1,12 @@ | |||
| vlib/v/checker/tests/redefining_builtin_pub_functions.vv:1:1: error: cannot redefine builtin public function `exit` | ||||
|     1 | fn exit(x string) { | ||||
|       | ~~~~~~~~~~~~~~~~~ | ||||
|     2 |     println('my exit: $x') | ||||
|     3 | } | ||||
| vlib/v/checker/tests/redefining_builtin_pub_functions.vv:5:1: error: cannot redefine builtin public function `print_backtrace` | ||||
|     3 | } | ||||
|     4 |  | ||||
|     5 | fn print_backtrace() { | ||||
|       | ~~~~~~~~~~~~~~~~~~~~ | ||||
|     6 |     println('hello') | ||||
|     7 | } | ||||
|  | @ -0,0 +1,11 @@ | |||
| fn exit(x string) { | ||||
| 	println('my exit: $x') | ||||
| } | ||||
| 
 | ||||
| fn print_backtrace() { | ||||
| 	println('hello') | ||||
| } | ||||
| 
 | ||||
| fn main() { | ||||
| 	print_backtrace() | ||||
| } | ||||
|  | @ -2,9 +2,10 @@ module js | |||
| 
 | ||||
| import v.ast | ||||
| import v.util | ||||
| import v.parser | ||||
| import strings | ||||
| 
 | ||||
| pub const builtin_functions = ['print', 'println', 'eprint', 'eprintln', 'isnil', 'panic', 'exit'] | ||||
| 
 | ||||
| fn (mut g JsGen) js_mname(name_ string) string { | ||||
| 	mut is_js := false | ||||
| 	is_overload := ['+', '-', '*', '/', '==', '<', '>'] | ||||
|  | @ -406,7 +407,7 @@ fn (mut g JsGen) gen_call_expr(it ast.CallExpr) { | |||
| 	mut name := g.js_name(it.name) | ||||
| 
 | ||||
| 	is_print := name in ['print', 'println', 'eprint', 'eprintln', 'panic'] | ||||
| 	if name in parser.builtin_functions { | ||||
| 	if name in js.builtin_functions { | ||||
| 		name = 'builtin__$name' | ||||
| 	} | ||||
| 	print_method := name | ||||
|  | @ -623,7 +624,7 @@ fn (mut g JsGen) gen_method_decl(it ast.FnDecl, typ FnGenType) { | |||
| 	name = g.js_name(name) | ||||
| 
 | ||||
| 	name = g.generic_fn_name(g.cur_concrete_types, name, true) | ||||
| 	if name in parser.builtin_functions { | ||||
| 	if name in js.builtin_functions { | ||||
| 		name = 'builtin__$name' | ||||
| 	} | ||||
| 	if it.is_pub && !it.is_method { | ||||
|  | @ -797,7 +798,7 @@ fn (mut g JsGen) gen_anon_fn(mut fun ast.AnonFn) { | |||
| 	name = g.js_name(name) | ||||
| 
 | ||||
| 	name = g.generic_fn_name(g.table.cur_concrete_types, name, true) | ||||
| 	if name in parser.builtin_functions { | ||||
| 	if name in js.builtin_functions { | ||||
| 		name = 'builtin__$name' | ||||
| 	} | ||||
| 	if it.is_pub && !it.is_method { | ||||
|  |  | |||
|  | @ -281,12 +281,6 @@ fn (mut p Parser) fn_decl() ast.FnDecl { | |||
| 			} | ||||
| 		} | ||||
| 		if !p.pref.is_fmt { | ||||
| 			if !is_method && !p.builtin_mod && name in builtin_functions { | ||||
| 				p.error_with_pos('cannot redefine builtin function `$name`', name_pos) | ||||
| 				return ast.FnDecl{ | ||||
| 					scope: 0 | ||||
| 				} | ||||
| 			} | ||||
| 			if name in p.imported_symbols { | ||||
| 				p.error_with_pos('cannot redefine imported function `$name`', name_pos) | ||||
| 				return ast.FnDecl{ | ||||
|  | @ -493,6 +487,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl { | |||
| 	// }
 | ||||
| 	fn_decl := ast.FnDecl{ | ||||
| 		name: name | ||||
| 		short_name: short_fn_name | ||||
| 		mod: p.mod | ||||
| 		stmts: stmts | ||||
| 		return_type: return_type | ||||
|  | @ -704,6 +699,7 @@ fn (mut p Parser) anon_fn() ast.AnonFn { | |||
| 	return ast.AnonFn{ | ||||
| 		decl: ast.FnDecl{ | ||||
| 			name: name | ||||
| 			short_name: '' | ||||
| 			mod: p.mod | ||||
| 			stmts: stmts | ||||
| 			return_type: return_type | ||||
|  | @ -1011,7 +1007,7 @@ fn (mut p Parser) check_fn_atomic_arguments(typ ast.Type, pos token.Pos) { | |||
| fn have_fn_main(stmts []ast.Stmt) bool { | ||||
| 	for stmt in stmts { | ||||
| 		if stmt is ast.FnDecl { | ||||
| 			if stmt.name == 'main.main' && stmt.mod == 'main' { | ||||
| 			if stmt.name == 'main.main' { | ||||
| 				return true | ||||
| 			} | ||||
| 		} | ||||
|  |  | |||
|  | @ -14,8 +14,6 @@ import v.errors | |||
| import os | ||||
| import hash.fnv1a | ||||
| 
 | ||||
| pub const builtin_functions = ['print', 'println', 'eprint', 'eprintln', 'isnil', 'panic', 'exit'] | ||||
| 
 | ||||
| pub struct Parser { | ||||
| 	pref &pref.Preferences | ||||
| mut: | ||||
|  | @ -654,6 +652,7 @@ pub fn (mut p Parser) top_stmt() ast.Stmt { | |||
| 					p.close_scope() | ||||
| 					return ast.FnDecl{ | ||||
| 						name: 'main.main' | ||||
| 						short_name: 'main' | ||||
| 						mod: 'main' | ||||
| 						is_main: true | ||||
| 						stmts: stmts | ||||
|  |  | |||
|  | @ -584,6 +584,7 @@ fn (mut p Parser) interface_decl() ast.InterfaceDecl { | |||
| 			args << args2 | ||||
| 			mut method := ast.FnDecl{ | ||||
| 				name: name | ||||
| 				short_name: name | ||||
| 				mod: p.mod | ||||
| 				params: args | ||||
| 				file: p.file_name | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| vlib/v/parser/tests/fn_use_builtin_err.vv:1:4: error: cannot redefine builtin function `print` | ||||
| vlib/v/parser/tests/fn_use_builtin_err.vv:1:1: error: cannot redefine builtin public function `print` | ||||
|     1 | fn print(strings ...string) { | ||||
|       |    ~~~~~ | ||||
|       | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
|     2 |     for s in strings { | ||||
|     3 |         println(s) | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue