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