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:
parent
2351856fc3
commit
8482bc4626
@ -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
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user