From d1224ffb5adc371c5c7f5cfb36f8a3fea120ae7b Mon Sep 17 00:00:00 2001 From: joe-conigliaro Date: Fri, 11 Dec 2020 20:50:26 +1100 Subject: [PATCH] parser: error on non local array/map methods & add tests --- vlib/v/fmt/tests/anon_fn_as_param_keep.vv | 2 +- vlib/v/parser/fn.v | 9 ++++++++- vlib/v/parser/tests/method_decl_on_non_local_array.out | 5 +++++ vlib/v/parser/tests/method_decl_on_non_local_array.vv | 3 +++ vlib/v/parser/tests/method_decl_on_non_local_map.out | 5 +++++ vlib/v/parser/tests/method_decl_on_non_local_map.vv | 3 +++ vlib/v/parser/tests/method_decl_on_non_local_type.out | 5 +++++ vlib/v/parser/tests/method_decl_on_non_local_type.vv | 3 +++ 8 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 vlib/v/parser/tests/method_decl_on_non_local_array.out create mode 100644 vlib/v/parser/tests/method_decl_on_non_local_array.vv create mode 100644 vlib/v/parser/tests/method_decl_on_non_local_map.out create mode 100644 vlib/v/parser/tests/method_decl_on_non_local_map.vv create mode 100644 vlib/v/parser/tests/method_decl_on_non_local_type.out create mode 100644 vlib/v/parser/tests/method_decl_on_non_local_type.vv diff --git a/vlib/v/fmt/tests/anon_fn_as_param_keep.vv b/vlib/v/fmt/tests/anon_fn_as_param_keep.vv index dd5f3180ea..93a97e736c 100644 --- a/vlib/v/fmt/tests/anon_fn_as_param_keep.vv +++ b/vlib/v/fmt/tests/anon_fn_as_param_keep.vv @@ -1,4 +1,4 @@ -pub fn (a []int) reduce(iter fn (int, int) int, accum_start int) int { +pub fn reduce(a []int, iter fn (int, int) int, accum_start int) int { iter(accum_start) } diff --git a/vlib/v/parser/fn.v b/vlib/v/parser/fn.v index 3cb57d84fa..9cf036e8d1 100644 --- a/vlib/v/parser/fn.v +++ b/vlib/v/parser/fn.v @@ -281,7 +281,14 @@ fn (mut p Parser) fn_decl() ast.FnDecl { // Do not allow to modify / add methods to types from other modules // arrays/maps dont belong to a module only their element types do // we could also check if kind is .array, .array_fixed, .map instead of mod.len - if type_sym.mod.len > 0 && type_sym.mod != p.mod && type_sym.language == .v { + mut is_non_local := type_sym.mod.len > 0 && type_sym.mod != p.mod && type_sym.language == .v + // check maps & arrays, must be defined in same module as the elem type + if !is_non_local && type_sym.kind in [.array, .map] { + elem_type_sym := p.table.get_type_symbol(p.table.value_type(rec_type)) + is_non_local = elem_type_sym.mod.len > 0 && + elem_type_sym.mod != p.mod && elem_type_sym.language == .v + } + if is_non_local { p.error_with_pos('cannot define new methods on non-local type $type_sym.name', rec_type_pos) return ast.FnDecl{} diff --git a/vlib/v/parser/tests/method_decl_on_non_local_array.out b/vlib/v/parser/tests/method_decl_on_non_local_array.out new file mode 100644 index 0000000000..f01fc00045 --- /dev/null +++ b/vlib/v/parser/tests/method_decl_on_non_local_array.out @@ -0,0 +1,5 @@ +vlib/v/parser/tests/method_decl_on_non_local_array.vv:1:7: error: cannot define new methods on non-local type []int + 1 | fn (a []int) get_number() int { + | ~~~~~ + 2 | return 1 + 3 | } diff --git a/vlib/v/parser/tests/method_decl_on_non_local_array.vv b/vlib/v/parser/tests/method_decl_on_non_local_array.vv new file mode 100644 index 0000000000..9822ce51a8 --- /dev/null +++ b/vlib/v/parser/tests/method_decl_on_non_local_array.vv @@ -0,0 +1,3 @@ +fn (a []int) get_number() int { + return 1 +} diff --git a/vlib/v/parser/tests/method_decl_on_non_local_map.out b/vlib/v/parser/tests/method_decl_on_non_local_map.out new file mode 100644 index 0000000000..d8459da3a3 --- /dev/null +++ b/vlib/v/parser/tests/method_decl_on_non_local_map.out @@ -0,0 +1,5 @@ +vlib/v/parser/tests/method_decl_on_non_local_map.vv:1:7: error: cannot define new methods on non-local type map[string]string + 1 | fn (a map[string]string) get_number() int { + | ~~~~~~~~~~~~~~~~~ + 2 | return 1 + 3 | } diff --git a/vlib/v/parser/tests/method_decl_on_non_local_map.vv b/vlib/v/parser/tests/method_decl_on_non_local_map.vv new file mode 100644 index 0000000000..f95e719f2d --- /dev/null +++ b/vlib/v/parser/tests/method_decl_on_non_local_map.vv @@ -0,0 +1,3 @@ +fn (a map[string]string) get_number() int { + return 1 +} diff --git a/vlib/v/parser/tests/method_decl_on_non_local_type.out b/vlib/v/parser/tests/method_decl_on_non_local_type.out new file mode 100644 index 0000000000..1b57bbd2b0 --- /dev/null +++ b/vlib/v/parser/tests/method_decl_on_non_local_type.out @@ -0,0 +1,5 @@ +vlib/v/parser/tests/method_decl_on_non_local_type.vv:1:7: error: cannot define new methods on non-local type int + 1 | fn (a int) get_number() int { + | ~~~ + 2 | return 1 + 3 | } diff --git a/vlib/v/parser/tests/method_decl_on_non_local_type.vv b/vlib/v/parser/tests/method_decl_on_non_local_type.vv new file mode 100644 index 0000000000..f75565bc71 --- /dev/null +++ b/vlib/v/parser/tests/method_decl_on_non_local_type.vv @@ -0,0 +1,3 @@ +fn (a int) get_number() int { + return 1 +}