mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
ast, checker: check generic fn declaration error (#15079)
This commit is contained in:
parent
b4ed5d5f20
commit
57c4188d98
|
@ -1686,6 +1686,70 @@ pub fn (mut t Table) resolve_generic_to_concrete(generic_type Type, generic_name
|
||||||
return none
|
return none
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn generic_names_push_with_filter(mut to_names []string, from_names []string) {
|
||||||
|
for name in from_names {
|
||||||
|
if name !in to_names {
|
||||||
|
to_names << name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (mut t Table) generic_type_names(generic_type Type) []string {
|
||||||
|
mut names := []string{}
|
||||||
|
mut sym := t.sym(generic_type)
|
||||||
|
if sym.name.len == 1 && sym.name[0].is_capital() {
|
||||||
|
names << sym.name
|
||||||
|
return names
|
||||||
|
}
|
||||||
|
match mut sym.info {
|
||||||
|
Array {
|
||||||
|
mut elem_type := sym.info.elem_type
|
||||||
|
mut elem_sym := t.sym(elem_type)
|
||||||
|
mut dims := 1
|
||||||
|
for mut elem_sym.info is Array {
|
||||||
|
elem_type = elem_sym.info.elem_type
|
||||||
|
elem_sym = t.sym(elem_type)
|
||||||
|
dims++
|
||||||
|
}
|
||||||
|
names << t.generic_type_names(elem_type)
|
||||||
|
}
|
||||||
|
ArrayFixed {
|
||||||
|
names << t.generic_type_names(sym.info.elem_type)
|
||||||
|
}
|
||||||
|
Chan {
|
||||||
|
names << t.generic_type_names(sym.info.elem_type)
|
||||||
|
}
|
||||||
|
FnType {
|
||||||
|
mut func := sym.info.func
|
||||||
|
if func.return_type.has_flag(.generic) {
|
||||||
|
names << t.generic_type_names(func.return_type)
|
||||||
|
}
|
||||||
|
func.params = func.params.clone()
|
||||||
|
for mut param in func.params {
|
||||||
|
if param.typ.has_flag(.generic) {
|
||||||
|
generic_names_push_with_filter(mut names, t.generic_type_names(param.typ))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MultiReturn {
|
||||||
|
for ret_type in sym.info.types {
|
||||||
|
generic_names_push_with_filter(mut names, t.generic_type_names(ret_type))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Map {
|
||||||
|
names << t.generic_type_names(sym.info.key_type)
|
||||||
|
generic_names_push_with_filter(mut names, t.generic_type_names(sym.info.value_type))
|
||||||
|
}
|
||||||
|
Struct, Interface, SumType {
|
||||||
|
if sym.info.is_generic {
|
||||||
|
names << sym.info.generic_types.map(t.sym(it).name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {}
|
||||||
|
}
|
||||||
|
return names
|
||||||
|
}
|
||||||
|
|
||||||
pub fn (mut t Table) unwrap_generic_type(typ Type, generic_names []string, concrete_types []Type) Type {
|
pub fn (mut t Table) unwrap_generic_type(typ Type, generic_names []string, concrete_types []Type) Type {
|
||||||
mut final_concrete_types := []Type{}
|
mut final_concrete_types := []Type{}
|
||||||
mut fields := []StructField{}
|
mut fields := []StructField{}
|
||||||
|
|
|
@ -207,7 +207,16 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//&& node.params.len == 1 && param.typ.is_ptr() {
|
if param.typ.has_flag(.generic) {
|
||||||
|
generic_names := c.table.generic_type_names(param.typ)
|
||||||
|
for name in generic_names {
|
||||||
|
if name !in node.generic_names {
|
||||||
|
fn_generic_names := node.generic_names.join(', ')
|
||||||
|
c.error('generic type name `$name` is not mentioned in fn `$node.name<$fn_generic_names>`',
|
||||||
|
param.type_pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (c.pref.translated || c.file.is_translated) && node.is_variadic && param.typ.is_ptr() {
|
if (c.pref.translated || c.file.is_translated) && node.is_variadic && param.typ.is_ptr() {
|
||||||
// TODO c2v hack to fix `(const char *s, ...)`
|
// TODO c2v hack to fix `(const char *s, ...)`
|
||||||
param.typ = ast.int_type.ref()
|
param.typ = ast.int_type.ref()
|
||||||
|
|
7
vlib/v/checker/tests/generic_fn_decl_err_a.out
Normal file
7
vlib/v/checker/tests/generic_fn_decl_err_a.out
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
vlib/v/checker/tests/generic_fn_decl_err_a.vv:17:28: error: generic type name `P` is not mentioned in fn `create<U>`
|
||||||
|
15 | }
|
||||||
|
16 |
|
||||||
|
17 | fn (r Db) create<U>(u U, p P) {
|
||||||
|
| ^
|
||||||
|
18 | println('Yo')
|
||||||
|
19 | }
|
19
vlib/v/checker/tests/generic_fn_decl_err_a.vv
Normal file
19
vlib/v/checker/tests/generic_fn_decl_err_a.vv
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
module main
|
||||||
|
|
||||||
|
struct Db {}
|
||||||
|
|
||||||
|
struct User {}
|
||||||
|
|
||||||
|
struct Post {}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
r := Db{}
|
||||||
|
u := User{}
|
||||||
|
p := Post{}
|
||||||
|
|
||||||
|
r.create(u, p)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (r Db) create<U>(u U, p P) {
|
||||||
|
println('Yo')
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user