1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

ast, parser: fix generic fntype to concrete types with later generic fn definition (fix #18156) (#18157)

This commit is contained in:
yuyi 2023-05-12 20:52:41 +08:00 committed by GitHub
parent 2351856fc3
commit 8482bc4626
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 47 additions and 16 deletions

View File

@ -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 { 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 // start_parsing_type open the scope during the parsing of a type

View File

@ -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 { pub fn (mut p Parser) ident(language ast.Language) ast.Ident {
is_option := p.tok.kind == .question && p.peek_tok.kind == .lsbr is_option := p.tok.kind == .question && p.peek_tok.kind == .lsbr
if is_option { if is_option {
@ -2172,12 +2195,7 @@ pub fn (mut p Parser) ident(language ast.Language) ast.Ident {
scope: p.scope scope: p.scope
} }
} }
mut is_known_generic_fn := false is_following_concrete_types := p.is_following_concrete_types()
if func := p.table.find_fn(p.prepend_mod(name)) {
if func.generic_names.len > 0 {
is_known_generic_fn = true
}
}
mut concrete_types := []ast.Type{} mut concrete_types := []ast.Type{}
if p.expr_mod.len > 0 { if p.expr_mod.len > 0 {
name = '${p.expr_mod}.${name}' 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 { } else if allowed_cases && p.tok.kind == .key_orelse {
or_kind = ast.OrKind.block or_kind = ast.OrKind.block
or_stmts, or_pos = p.or_block(.no_err_var) 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]` // `generic_fn[int]`
concrete_types = p.parse_concrete_types() concrete_types = p.parse_concrete_types()
} }

View File

@ -4,17 +4,30 @@ fn func[T](x T, i int, f_ Fn[T]) T {
return f_(x, i) return f_(x, i)
} }
fn f[T](x T, i int) T { fn f1[T](x T, i int) T {
return x return x
} }
fn test_generic_fn_variable() { fn test_generic_fn_variable() {
ff := f[int] ff1 := f1[int]
ret := ff(1, 11) ret1 := ff1(1, 11)
println(ret) println(ret1)
assert ret == 1 assert ret1 == 1
x := func[f64](2.0, 3, f[f64]) ff2 := f2[int]
println(x) ret2 := ff2(1, 11)
assert x == 2.0 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
} }