Skip to content

Commit

Permalink
ast, parser: fix generic fn type with defferent generic type call (#2…
Browse files Browse the repository at this point in the history
  • Loading branch information
yuyi98 authored Oct 7, 2024
1 parent 309c8d3 commit 3736e51
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 10 deletions.
11 changes: 1 addition & 10 deletions vlib/v/ast/table.v
Original file line number Diff line number Diff line change
Expand Up @@ -1828,16 +1828,7 @@ pub fn (mut t Table) generic_type_names(generic_type Type) []string {
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))
}
}
names << sym.info.func.generic_names
}
MultiReturn {
for ret_type in sym.info.types {
Expand Down
42 changes: 42 additions & 0 deletions vlib/v/parser/parse_type.v
Original file line number Diff line number Diff line change
Expand Up @@ -841,6 +841,48 @@ fn (mut p Parser) find_type_or_add_placeholder(name string, language ast.Languag
typ = ast.new_type(idx)
}
}
ast.FnType {
if p.struct_init_generic_types.len > 0 && sym.info.func.generic_names.len > 0 {
generic_names := p.types_to_names(p.struct_init_generic_types, p.tok.pos(),
'struct_init_generic_types') or { return ast.no_type }
if generic_names != sym.info.func.generic_names {
mut sym_name := sym.name + '<'
for i, gt in generic_names {
sym_name += gt
if i != generic_names.len - 1 {
sym_name += ','
}
}
sym_name += '>'
existing_idx := p.table.type_idxs[sym_name]
if existing_idx > 0 {
idx = existing_idx
} else {
mut func := sym.info.func
func.name = sym_name
func.generic_names = generic_names.clone()
if func.return_type.has_flag(.generic) {
if to_generic_typ := p.table.resolve_generic_to_concrete(func.return_type,
sym.info.func.generic_names, p.struct_init_generic_types)
{
func.return_type = to_generic_typ
}
}
for i in 0 .. func.params.len {
if func.params[i].typ.has_flag(.generic) {
if to_generic_typ := p.table.resolve_generic_to_concrete(func.params[i].typ,
sym.info.func.generic_names, p.struct_init_generic_types)
{
func.params[i].typ = to_generic_typ
}
}
}
idx = p.table.find_or_register_fn_type(func, false, false)
}
typ = ast.new_type(idx)
}
}
}
else {}
}
return typ
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
type Fn[T] = fn () T

fn problem[X](f Fn[X]) X {
return f[X]()
}

fn foo() int {
return 1
}

fn test_generic_fn_type_with_different_generic_type() {
t := problem[int](foo)
println(t)
assert t == 1
}

0 comments on commit 3736e51

Please sign in to comment.