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
|
// function or method declaration
|
||||||
pub struct FnDecl {
|
pub struct FnDecl {
|
||||||
pub:
|
pub:
|
||||||
name string
|
name string // 'math.bits.normalize'
|
||||||
mod string
|
short_name string // 'normalize'
|
||||||
|
mod string // 'math.bits'
|
||||||
is_deprecated bool
|
is_deprecated bool
|
||||||
is_pub bool
|
is_pub bool
|
||||||
is_variadic bool
|
is_variadic bool
|
||||||
|
|
|
@ -41,6 +41,7 @@ pub mut:
|
||||||
enum_decls map[string]EnumDecl
|
enum_decls map[string]EnumDecl
|
||||||
mdeprecated_msg map[string]string // module deprecation message
|
mdeprecated_msg map[string]string // module deprecation message
|
||||||
mdeprecated_after map[string]time.Time // module deprecation date
|
mdeprecated_after map[string]time.Time // module deprecation date
|
||||||
|
builtin_pub_fns map[string]bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// used by vls to avoid leaks
|
// 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) {
|
pub fn (mut t Table) register_fn(new_fn Fn) {
|
||||||
t.fns[new_fn.name] = new_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) {
|
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 {
|
if node.language == .v && !c.is_builtin_mod && !node.is_anon {
|
||||||
c.check_valid_snake_case(node.name, 'function name', node.pos)
|
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' {
|
if node.name == 'main.main' {
|
||||||
c.main_fn_decl_node = *node
|
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.ast
|
||||||
import v.util
|
import v.util
|
||||||
import v.parser
|
|
||||||
import strings
|
import strings
|
||||||
|
|
||||||
|
pub const builtin_functions = ['print', 'println', 'eprint', 'eprintln', 'isnil', 'panic', 'exit']
|
||||||
|
|
||||||
fn (mut g JsGen) js_mname(name_ string) string {
|
fn (mut g JsGen) js_mname(name_ string) string {
|
||||||
mut is_js := false
|
mut is_js := false
|
||||||
is_overload := ['+', '-', '*', '/', '==', '<', '>']
|
is_overload := ['+', '-', '*', '/', '==', '<', '>']
|
||||||
|
@ -406,7 +407,7 @@ fn (mut g JsGen) gen_call_expr(it ast.CallExpr) {
|
||||||
mut name := g.js_name(it.name)
|
mut name := g.js_name(it.name)
|
||||||
|
|
||||||
is_print := name in ['print', 'println', 'eprint', 'eprintln', 'panic']
|
is_print := name in ['print', 'println', 'eprint', 'eprintln', 'panic']
|
||||||
if name in parser.builtin_functions {
|
if name in js.builtin_functions {
|
||||||
name = 'builtin__$name'
|
name = 'builtin__$name'
|
||||||
}
|
}
|
||||||
print_method := 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.js_name(name)
|
||||||
|
|
||||||
name = g.generic_fn_name(g.cur_concrete_types, name, true)
|
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'
|
name = 'builtin__$name'
|
||||||
}
|
}
|
||||||
if it.is_pub && !it.is_method {
|
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.js_name(name)
|
||||||
|
|
||||||
name = g.generic_fn_name(g.table.cur_concrete_types, name, true)
|
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'
|
name = 'builtin__$name'
|
||||||
}
|
}
|
||||||
if it.is_pub && !it.is_method {
|
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 !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 {
|
if name in p.imported_symbols {
|
||||||
p.error_with_pos('cannot redefine imported function `$name`', name_pos)
|
p.error_with_pos('cannot redefine imported function `$name`', name_pos)
|
||||||
return ast.FnDecl{
|
return ast.FnDecl{
|
||||||
|
@ -493,6 +487,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
|
||||||
// }
|
// }
|
||||||
fn_decl := ast.FnDecl{
|
fn_decl := ast.FnDecl{
|
||||||
name: name
|
name: name
|
||||||
|
short_name: short_fn_name
|
||||||
mod: p.mod
|
mod: p.mod
|
||||||
stmts: stmts
|
stmts: stmts
|
||||||
return_type: return_type
|
return_type: return_type
|
||||||
|
@ -704,6 +699,7 @@ fn (mut p Parser) anon_fn() ast.AnonFn {
|
||||||
return ast.AnonFn{
|
return ast.AnonFn{
|
||||||
decl: ast.FnDecl{
|
decl: ast.FnDecl{
|
||||||
name: name
|
name: name
|
||||||
|
short_name: ''
|
||||||
mod: p.mod
|
mod: p.mod
|
||||||
stmts: stmts
|
stmts: stmts
|
||||||
return_type: return_type
|
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 {
|
fn have_fn_main(stmts []ast.Stmt) bool {
|
||||||
for stmt in stmts {
|
for stmt in stmts {
|
||||||
if stmt is ast.FnDecl {
|
if stmt is ast.FnDecl {
|
||||||
if stmt.name == 'main.main' && stmt.mod == 'main' {
|
if stmt.name == 'main.main' {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,8 +14,6 @@ import v.errors
|
||||||
import os
|
import os
|
||||||
import hash.fnv1a
|
import hash.fnv1a
|
||||||
|
|
||||||
pub const builtin_functions = ['print', 'println', 'eprint', 'eprintln', 'isnil', 'panic', 'exit']
|
|
||||||
|
|
||||||
pub struct Parser {
|
pub struct Parser {
|
||||||
pref &pref.Preferences
|
pref &pref.Preferences
|
||||||
mut:
|
mut:
|
||||||
|
@ -654,6 +652,7 @@ pub fn (mut p Parser) top_stmt() ast.Stmt {
|
||||||
p.close_scope()
|
p.close_scope()
|
||||||
return ast.FnDecl{
|
return ast.FnDecl{
|
||||||
name: 'main.main'
|
name: 'main.main'
|
||||||
|
short_name: 'main'
|
||||||
mod: 'main'
|
mod: 'main'
|
||||||
is_main: true
|
is_main: true
|
||||||
stmts: stmts
|
stmts: stmts
|
||||||
|
|
|
@ -584,6 +584,7 @@ fn (mut p Parser) interface_decl() ast.InterfaceDecl {
|
||||||
args << args2
|
args << args2
|
||||||
mut method := ast.FnDecl{
|
mut method := ast.FnDecl{
|
||||||
name: name
|
name: name
|
||||||
|
short_name: name
|
||||||
mod: p.mod
|
mod: p.mod
|
||||||
params: args
|
params: args
|
||||||
file: p.file_name
|
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) {
|
1 | fn print(strings ...string) {
|
||||||
| ~~~~~
|
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
2 | for s in strings {
|
2 | for s in strings {
|
||||||
3 | println(s)
|
3 | println(s)
|
||||||
|
|
Loading…
Reference in New Issue