1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

checker: check generic method receiver type mismatch (#16739)

This commit is contained in:
yuyi
2022-12-22 19:37:46 +08:00
committed by GitHub
parent 82a3551313
commit e519bdf0eb
6 changed files with 49 additions and 31 deletions

View File

@@ -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

View File

@@ -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 | }

View File

@@ -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 | }

View File

@@ -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 | }

View File

@@ -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() {
}