Skip to content

Commit

Permalink
checker: error on redefining any of the public builtin functions, not…
Browse files Browse the repository at this point in the history
… just ['print', 'println', 'eprint', 'eprintln', 'isnil', 'panic', 'exit'] (#13419)
  • Loading branch information
spytheman committed Feb 10, 2022
1 parent 43d6b97 commit 9ed18ef
Show file tree
Hide file tree
Showing 10 changed files with 45 additions and 17 deletions.
5 changes: 3 additions & 2 deletions vlib/v/ast/ast.v
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions vlib/v/ast/table.v
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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) {
Expand Down
3 changes: 3 additions & 0 deletions vlib/v/checker/fn.v
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
12 changes: 12 additions & 0 deletions vlib/v/checker/tests/redefining_builtin_pub_functions.out
Original file line number Diff line number Diff line change
@@ -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 | }
11 changes: 11 additions & 0 deletions vlib/v/checker/tests/redefining_builtin_pub_functions.vv
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
fn exit(x string) {
println('my exit: $x')
}

fn print_backtrace() {
println('hello')
}

fn main() {
print_backtrace()
}
9 changes: 5 additions & 4 deletions vlib/v/gen/js/fn.v
Original file line number Diff line number Diff line change
Expand Up @@ -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 := ['+', '-', '*', '/', '==', '<', '>']
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down
10 changes: 3 additions & 7 deletions vlib/v/parser/fn.v
Original file line number Diff line number Diff line change
Expand Up @@ -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{
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
}
}
Expand Down
3 changes: 1 addition & 2 deletions vlib/v/parser/parser.v
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions vlib/v/parser/struct.v
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions vlib/v/parser/tests/fn_use_builtin_err.out
Original file line number Diff line number Diff line change
@@ -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)

0 comments on commit 9ed18ef

Please sign in to comment.