From e519bdf0eb4a732fd84da37d9ba70834e96f0582 Mon Sep 17 00:00:00 2001 From: yuyi Date: Thu, 22 Dec 2022 19:37:46 +0800 Subject: [PATCH] checker: check generic method receiver type mismatch (#16739) --- vlib/v/checker/fn.v | 46 +++++++++---------- .../generics_method_receiver_type_err.out | 7 --- .../generics_method_receiver_type_err_a.out | 7 +++ ...=> generics_method_receiver_type_err_a.vv} | 0 .../generics_method_receiver_type_err_b.out | 7 +++ .../generics_method_receiver_type_err_b.vv | 13 ++++++ 6 files changed, 49 insertions(+), 31 deletions(-) delete mode 100644 vlib/v/checker/tests/generics_method_receiver_type_err.out create mode 100644 vlib/v/checker/tests/generics_method_receiver_type_err_a.out rename vlib/v/checker/tests/{generics_method_receiver_type_err.vv => generics_method_receiver_type_err_a.vv} (100%) create mode 100644 vlib/v/checker/tests/generics_method_receiver_type_err_b.out create mode 100644 vlib/v/checker/tests/generics_method_receiver_type_err_b.vv diff --git a/vlib/v/checker/fn.v b/vlib/v/checker/fn.v index 84e4a3f7d5..f17743c085 100644 --- a/vlib/v/checker/fn.v +++ b/vlib/v/checker/fn.v @@ -215,30 +215,28 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) { c.error('optional or result type argument is not supported currently', param.type_pos) } - if !param.typ.is_ptr() { // value parameter, i.e. on stack - check for `[heap]` - arg_typ_sym := c.table.sym(param.typ) - if arg_typ_sym.info is ast.Struct { - if arg_typ_sym.info.is_heap { // set auto_heap to promote value parameter - mut v := node.scope.find_var(param.name) or { continue } - v.is_auto_heap = true - } - if arg_typ_sym.info.generic_types.len > 0 && !param.typ.has_flag(.generic) - && arg_typ_sym.info.concrete_types.len == 0 { - c.error('generic struct `${arg_typ_sym.name}` in fn declaration must specify the generic type names, e.g. ${arg_typ_sym.name}[T]', - param.type_pos) - } - } else if arg_typ_sym.info is ast.Interface { - if arg_typ_sym.info.generic_types.len > 0 && !param.typ.has_flag(.generic) - && arg_typ_sym.info.concrete_types.len == 0 { - c.error('generic interface `${arg_typ_sym.name}` in fn declaration must specify the generic type names, e.g. ${arg_typ_sym.name}[T]', - param.type_pos) - } - } else if arg_typ_sym.info is ast.SumType { - if arg_typ_sym.info.generic_types.len > 0 && !param.typ.has_flag(.generic) - && arg_typ_sym.info.concrete_types.len == 0 { - c.error('generic sumtype `${arg_typ_sym.name}` in fn declaration must specify the generic type names, e.g. ${arg_typ_sym.name}[T]', - param.type_pos) - } + arg_typ_sym := c.table.sym(param.typ) + if arg_typ_sym.info is ast.Struct { + if !param.typ.is_ptr() && arg_typ_sym.info.is_heap { // set auto_heap to promote value parameter + mut v := node.scope.find_var(param.name) or { continue } + v.is_auto_heap = true + } + if arg_typ_sym.info.generic_types.len > 0 && !param.typ.has_flag(.generic) + && arg_typ_sym.info.concrete_types.len == 0 { + c.error('generic struct `${arg_typ_sym.name}` in fn declaration must specify the generic type names, e.g. ${arg_typ_sym.name}[T]', + param.type_pos) + } + } else if arg_typ_sym.info is ast.Interface { + if arg_typ_sym.info.generic_types.len > 0 && !param.typ.has_flag(.generic) + && arg_typ_sym.info.concrete_types.len == 0 { + c.error('generic interface `${arg_typ_sym.name}` in fn declaration must specify the generic type names, e.g. ${arg_typ_sym.name}[T]', + param.type_pos) + } + } else if arg_typ_sym.info is ast.SumType { + if arg_typ_sym.info.generic_types.len > 0 && !param.typ.has_flag(.generic) + && arg_typ_sym.info.concrete_types.len == 0 { + c.error('generic sumtype `${arg_typ_sym.name}` in fn declaration must specify the generic type names, e.g. ${arg_typ_sym.name}[T]', + param.type_pos) } } // Ensure each generic type of the parameter was declared in the function's definition diff --git a/vlib/v/checker/tests/generics_method_receiver_type_err.out b/vlib/v/checker/tests/generics_method_receiver_type_err.out deleted file mode 100644 index 9f038bc29f..0000000000 --- a/vlib/v/checker/tests/generics_method_receiver_type_err.out +++ /dev/null @@ -1,7 +0,0 @@ -vlib/v/checker/tests/generics_method_receiver_type_err.vv:6:11: error: generic struct `Node` in fn declaration must specify the generic type names, e.g. Node[T] - 4 | } - 5 | - 6 | pub fn (x Node) str() string { - | ~~~~ - 7 | return 'Value is : ${u16(x.val)}\nName is : $x.name' - 8 | } diff --git a/vlib/v/checker/tests/generics_method_receiver_type_err_a.out b/vlib/v/checker/tests/generics_method_receiver_type_err_a.out new file mode 100644 index 0000000000..decceef9c0 --- /dev/null +++ b/vlib/v/checker/tests/generics_method_receiver_type_err_a.out @@ -0,0 +1,7 @@ +vlib/v/checker/tests/generics_method_receiver_type_err_a.vv:6:11: error: generic struct `Node` in fn declaration must specify the generic type names, e.g. Node[T] + 4 | } + 5 | + 6 | pub fn (x Node) str() string { + | ~~~~ + 7 | return 'Value is : ${u16(x.val)}\nName is : $x.name' + 8 | } diff --git a/vlib/v/checker/tests/generics_method_receiver_type_err.vv b/vlib/v/checker/tests/generics_method_receiver_type_err_a.vv similarity index 100% rename from vlib/v/checker/tests/generics_method_receiver_type_err.vv rename to vlib/v/checker/tests/generics_method_receiver_type_err_a.vv diff --git a/vlib/v/checker/tests/generics_method_receiver_type_err_b.out b/vlib/v/checker/tests/generics_method_receiver_type_err_b.out new file mode 100644 index 0000000000..546ff70c47 --- /dev/null +++ b/vlib/v/checker/tests/generics_method_receiver_type_err_b.out @@ -0,0 +1,7 @@ +vlib/v/checker/tests/generics_method_receiver_type_err_b.vv:8:12: error: generic struct `ConsumableResources` in fn declaration must specify the generic type names, e.g. ConsumableResources[T] + 6 | used_resources map[T]Resources + 7 | } + 8 | pub fn (cr &ConsumableResources) get_total_resources() Resources { + | ~~~~~~~~~~~~~~~~~~~~ + 9 | return cr.total_resources + 10 | } diff --git a/vlib/v/checker/tests/generics_method_receiver_type_err_b.vv b/vlib/v/checker/tests/generics_method_receiver_type_err_b.vv new file mode 100644 index 0000000000..844c597283 --- /dev/null +++ b/vlib/v/checker/tests/generics_method_receiver_type_err_b.vv @@ -0,0 +1,13 @@ +pub struct Resources{} + +pub struct ConsumableResources[T] { +mut: + total_resources Resources + used_resources map[T]Resources +} +pub fn (cr &ConsumableResources) get_total_resources() Resources { + return cr.total_resources +} + +fn main() { +}