mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
ast: fix concrete function type used as generic type (#17769)
This commit is contained in:
parent
3d2d330478
commit
f5f45d846e
@ -2246,6 +2246,38 @@ pub fn (mut t Table) generic_insts_to_concrete() {
|
|||||||
util.verror('generic error', 'the number of generic types of sumtype `${parent.name}` is inconsistent with the concrete types')
|
util.verror('generic error', 'the number of generic types of sumtype `${parent.name}` is inconsistent with the concrete types')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
FnType {
|
||||||
|
// TODO: Cache function's generic types (parameters and return type) like Struct and Interface etc. do?
|
||||||
|
mut parent_info := parent.info as FnType
|
||||||
|
mut function := parent_info.func
|
||||||
|
mut generic_names := []string{cap: function.params.len + 1}
|
||||||
|
generic_names << function.params.filter(it.typ.has_flag(.generic)).map(t.sym(it.typ).name)
|
||||||
|
if function.return_type.has_flag(.generic) {
|
||||||
|
generic_names << t.sym(function.return_type).name
|
||||||
|
}
|
||||||
|
for mut param in function.params {
|
||||||
|
if param.typ.has_flag(.generic) {
|
||||||
|
if t_typ := t.resolve_generic_to_concrete(param.typ, generic_names,
|
||||||
|
info.concrete_types)
|
||||||
|
{
|
||||||
|
param.typ = t_typ
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mut return_type := function.return_type
|
||||||
|
if return_type.has_flag(.generic) {
|
||||||
|
if return_type.idx() != info.parent_idx {
|
||||||
|
return_type = t.unwrap_generic_type(return_type, generic_names,
|
||||||
|
info.concrete_types)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sym.info = FnType{
|
||||||
|
...parent_info
|
||||||
|
func: function
|
||||||
|
}
|
||||||
|
sym.is_pub = true
|
||||||
|
sym.kind = parent.kind
|
||||||
|
}
|
||||||
else {}
|
else {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
36
vlib/v/tests/concrete_type_as_generic_type_test.v
Normal file
36
vlib/v/tests/concrete_type_as_generic_type_test.v
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
type Fn = fn (T)
|
||||||
|
|
||||||
|
type FnReturn = fn (T) R
|
||||||
|
|
||||||
|
fn func_fn_concrete() Fn[string] {
|
||||||
|
return fn (_s string) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn func_fn_dynamic[T]() Fn[T] {
|
||||||
|
return fn [T](_t T) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: FnReturn[string, string] fails to stencil
|
||||||
|
// fn func_fn_return_concrete() FnReturn[string, string] {
|
||||||
|
// return fn (s string) string {
|
||||||
|
// return s
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
fn func_fn_return_dynamic[T, R]() FnReturn[T, R] {
|
||||||
|
return fn [T, R](t T) R {
|
||||||
|
return t.int()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vfmt will erase explicit generic type (bug)
|
||||||
|
// vfmt off
|
||||||
|
|
||||||
|
fn test_concrete_function_type_as_generic_type() {
|
||||||
|
func_fn_concrete()('V')
|
||||||
|
func_fn_dynamic[string]()('V')
|
||||||
|
|
||||||
|
assert func_fn_return_dynamic[string, int]()('100') == 100
|
||||||
|
}
|
||||||
|
|
||||||
|
// vfmt on
|
Loading…
x
Reference in New Issue
Block a user