diff --git a/vlib/v/ast/table.v b/vlib/v/ast/table.v index 219a3a00ba..b670defedd 100644 --- a/vlib/v/ast/table.v +++ b/vlib/v/ast/table.v @@ -744,7 +744,7 @@ pub fn (mut t Table) register_anon_struct(name string, sym_idx int) { } pub fn (t &Table) known_type(name string) bool { - return t.find_type_idx(name) != 0 || t.parsing_type == name || name in ['i32', 'byte'] + return t.type_idxs[name] != 0 || t.parsing_type == name || name in ['i32', 'byte'] } // start_parsing_type open the scope during the parsing of a type diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index 7d06ba1860..03615f9aad 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -2119,6 +2119,29 @@ fn (mut p Parser) parse_multi_expr(is_top_level bool) ast.Stmt { } } +fn (mut p Parser) is_following_concrete_types() bool { + if !(p.tok.kind == .lsbr && p.tok.pos - p.prev_tok.pos == p.prev_tok.len) { + return false + } + mut i := 1 + for { + cur_tok := p.peek_token(i) + if cur_tok.kind == .eof { + return false + } else if cur_tok.kind == .rsbr { + break + } else if cur_tok.kind == .name { + if !(cur_tok.lit.len > 1 && p.is_typename(cur_tok)) { + return false + } + } else if cur_tok.kind != .comma { + return false + } + i++ + } + return true +} + pub fn (mut p Parser) ident(language ast.Language) ast.Ident { is_option := p.tok.kind == .question && p.peek_tok.kind == .lsbr if is_option { @@ -2172,12 +2195,7 @@ pub fn (mut p Parser) ident(language ast.Language) ast.Ident { scope: p.scope } } - mut is_known_generic_fn := false - if func := p.table.find_fn(p.prepend_mod(name)) { - if func.generic_names.len > 0 { - is_known_generic_fn = true - } - } + is_following_concrete_types := p.is_following_concrete_types() mut concrete_types := []ast.Type{} if p.expr_mod.len > 0 { name = '${p.expr_mod}.${name}' @@ -2195,7 +2213,7 @@ pub fn (mut p Parser) ident(language ast.Language) ast.Ident { } else if allowed_cases && p.tok.kind == .key_orelse { or_kind = ast.OrKind.block or_stmts, or_pos = p.or_block(.no_err_var) - } else if is_known_generic_fn && p.tok.kind == .lsbr { + } else if is_following_concrete_types { // `generic_fn[int]` concrete_types = p.parse_concrete_types() } diff --git a/vlib/v/tests/generics_fn_variable_test.v b/vlib/v/tests/generics_fn_variable_test.v index a61ee3bff9..a6f6a928f4 100644 --- a/vlib/v/tests/generics_fn_variable_test.v +++ b/vlib/v/tests/generics_fn_variable_test.v @@ -4,17 +4,30 @@ fn func[T](x T, i int, f_ Fn[T]) T { return f_(x, i) } -fn f[T](x T, i int) T { +fn f1[T](x T, i int) T { return x } fn test_generic_fn_variable() { - ff := f[int] - ret := ff(1, 11) - println(ret) - assert ret == 1 + ff1 := f1[int] + ret1 := ff1(1, 11) + println(ret1) + assert ret1 == 1 - x := func[f64](2.0, 3, f[f64]) - println(x) - assert x == 2.0 + ff2 := f2[int] + ret2 := ff2(1, 11) + println(ret2) + assert ret2 == 1 + + x1 := func[f64](2.0, 3, f1[f64]) + println(x1) + assert x1 == 2.0 + + x2 := func[f64](2.0, 3, f2[f64]) + println(x2) + assert x2 == 2.0 +} + +fn f2[T](x T, i int) T { + return x }