Skip to content

Commit 14b7ce0

Browse files
authored
checker: fix generics fn return generics fn type (fix #10085) (#10088)
1 parent 143c3d4 commit 14b7ce0

File tree

3 files changed

+70
-1
lines changed

3 files changed

+70
-1
lines changed

vlib/v/ast/types.v

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,7 @@ pub mut:
426426
}
427427

428428
pub struct FnType {
429-
pub:
429+
pub mut:
430430
is_anon bool
431431
has_decl bool
432432
func Fn

vlib/v/checker/check_types.v

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,15 @@ pub fn (mut c Checker) infer_fn_generic_types(f ast.Fn, mut call_expr ast.CallEx
508508

509509
if param.typ.has_flag(.generic) && param_type_sym.name == gt_name {
510510
to_set = c.table.mktyp(arg.typ)
511+
mut sym := c.table.get_type_symbol(arg.typ)
512+
if mut sym.info is ast.FnType {
513+
if !sym.info.is_anon {
514+
sym.info.func.name = ''
515+
idx := c.table.find_or_register_fn_type(c.mod, sym.info.func,
516+
true, false)
517+
to_set = ast.new_type(idx).derive(arg.typ)
518+
}
519+
}
511520
if arg.expr.is_auto_deref_var() {
512521
to_set = to_set.deref()
513522
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
fn neg(a int) int {
2+
return -a
3+
}
4+
5+
fn normal_v1(func fn (int) int) fn (int) int {
6+
assert typeof(func).name == typeof(neg).name
7+
return func
8+
}
9+
10+
fn normal_v2(func fn (int) int) fn (int) int {
11+
f := func
12+
assert typeof(f).name == typeof(neg).name
13+
return f
14+
}
15+
16+
fn generic_v1<T>(func T) T {
17+
assert T.name == typeof(neg).name
18+
assert typeof(func).name == typeof(neg).name
19+
return func
20+
}
21+
22+
fn generic_v2<T>(func T) T {
23+
assert T.name == typeof(neg).name
24+
f := func
25+
assert typeof(f).name == typeof(neg).name
26+
return f
27+
}
28+
29+
fn mixed_v1<T>(func T) fn (int) int {
30+
assert T.name == typeof(neg).name
31+
assert typeof(func).name == typeof(neg).name
32+
return func
33+
}
34+
35+
fn mixed_v2<T>(func T) fn (int) int {
36+
assert T.name == typeof(neg).name
37+
f := func
38+
assert typeof(f).name == typeof(neg).name
39+
return f
40+
}
41+
42+
fn test_generics_with_generics_fn_return_type() {
43+
mut f := neg
44+
assert f(1) == -1
45+
46+
f = normal_v1(neg)
47+
assert f(2) == -2
48+
f = normal_v2(neg)
49+
assert f(3) == -3
50+
51+
f = generic_v1(neg)
52+
assert f(4) == -4
53+
f = generic_v2(neg)
54+
assert f(5) == -5
55+
56+
f = mixed_v1(neg)
57+
assert f(6) == -6
58+
f = mixed_v2(neg)
59+
assert f(7) == -7
60+
}

0 commit comments

Comments
 (0)