mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
ast: fix concrete fn type that returns pair type as generic type (#17780)
This commit is contained in:
parent
8759409a69
commit
34f5f05efa
@ -2105,7 +2105,7 @@ pub fn (mut t Table) generic_insts_to_concrete() {
|
||||
}
|
||||
mut fields := parent_info.fields.clone()
|
||||
if parent_info.generic_types.len == info.concrete_types.len {
|
||||
generic_names := parent_info.generic_types.map(t.sym(it).name)
|
||||
generic_names := t.get_generic_names(parent_info.generic_types)
|
||||
for i in 0 .. fields.len {
|
||||
if fields[i].typ.has_flag(.generic) {
|
||||
if fields[i].typ.idx() != info.parent_idx {
|
||||
@ -2151,7 +2151,7 @@ pub fn (mut t Table) generic_insts_to_concrete() {
|
||||
}
|
||||
if parent_info.generic_types.len == info.concrete_types.len {
|
||||
mut fields := parent_info.fields.clone()
|
||||
generic_names := parent_info.generic_types.map(t.sym(it).name)
|
||||
generic_names := t.get_generic_names(parent_info.generic_types)
|
||||
for i in 0 .. fields.len {
|
||||
if t_typ := t.resolve_generic_to_concrete(fields[i].typ, generic_names,
|
||||
info.concrete_types)
|
||||
@ -2209,7 +2209,7 @@ pub fn (mut t Table) generic_insts_to_concrete() {
|
||||
if parent_info.generic_types.len == info.concrete_types.len {
|
||||
mut fields := parent_info.fields.clone()
|
||||
mut variants := parent_info.variants.clone()
|
||||
generic_names := parent_info.generic_types.map(t.sym(it).name)
|
||||
generic_names := t.get_generic_names(parent_info.generic_types)
|
||||
for i in 0 .. fields.len {
|
||||
if t_typ := t.resolve_generic_to_concrete(fields[i].typ, generic_names,
|
||||
info.concrete_types)
|
||||
@ -2250,11 +2250,12 @@ pub fn (mut t Table) generic_insts_to_concrete() {
|
||||
// TODO: Cache function's generic types (parameters and return type) like Struct and Interface etc. do?
|
||||
mut parent_info := parent.info as FnType
|
||||
mut function := parent_info.func
|
||||
mut generic_names := []string{cap: function.params.len + 1}
|
||||
generic_names << function.params.filter(it.typ.has_flag(.generic)).map(t.sym(it.typ).name)
|
||||
mut generic_types := []Type{cap: function.params.len + 1}
|
||||
generic_types << function.params.filter(it.typ.has_flag(.generic)).map(it.typ)
|
||||
if function.return_type.has_flag(.generic) {
|
||||
generic_names << t.sym(function.return_type).name
|
||||
generic_types << function.return_type
|
||||
}
|
||||
generic_names := t.get_generic_names(generic_types)
|
||||
for mut param in function.params {
|
||||
if param.typ.has_flag(.generic) {
|
||||
if t_typ := t.resolve_generic_to_concrete(param.typ, generic_names,
|
||||
@ -2264,11 +2265,11 @@ pub fn (mut t Table) generic_insts_to_concrete() {
|
||||
}
|
||||
}
|
||||
}
|
||||
mut return_type := function.return_type
|
||||
if return_type.has_flag(.generic) {
|
||||
if return_type.idx() != info.parent_idx {
|
||||
return_type = t.unwrap_generic_type(return_type, generic_names,
|
||||
info.concrete_types)
|
||||
if function.return_type.has_flag(.generic) {
|
||||
if t_typ := t.resolve_generic_to_concrete(function.return_type,
|
||||
generic_names, info.concrete_types)
|
||||
{
|
||||
function.return_type = t_typ
|
||||
}
|
||||
}
|
||||
sym.info = FnType{
|
||||
@ -2284,6 +2285,30 @@ pub fn (mut t Table) generic_insts_to_concrete() {
|
||||
}
|
||||
}
|
||||
|
||||
// Extracts all type names from given types, notice that MultiReturn will be decompose
|
||||
// and will not included in returned string
|
||||
pub fn (t &Table) get_generic_names(generic_types []Type) []string {
|
||||
mut generic_names := []string{cap: generic_types.len}
|
||||
for typ in generic_types {
|
||||
if !typ.has_flag(.generic) {
|
||||
continue
|
||||
}
|
||||
|
||||
sym := t.sym(typ)
|
||||
info := sym.info
|
||||
|
||||
match info {
|
||||
MultiReturn {
|
||||
generic_names << t.get_generic_names(info.types)
|
||||
}
|
||||
else {
|
||||
generic_names << sym.name
|
||||
}
|
||||
}
|
||||
}
|
||||
return generic_names
|
||||
}
|
||||
|
||||
pub fn (t &Table) is_comptime_type(x Type, y ComptimeType) bool {
|
||||
x_kind := t.type_kind(x)
|
||||
match y.kind {
|
||||
|
@ -2,6 +2,8 @@ type Fn = fn (T)
|
||||
|
||||
type FnReturn = fn (T) R
|
||||
|
||||
type FnMultiReturn = fn (I) (O, R)
|
||||
|
||||
fn func_fn_concrete() Fn[string] {
|
||||
return fn (_s string) {}
|
||||
}
|
||||
@ -23,7 +25,13 @@ fn func_fn_return_dynamic[T, R]() FnReturn[T, R] {
|
||||
}
|
||||
}
|
||||
|
||||
// vfmt will erase explicit generic type (bug)
|
||||
fn func_fn_multi_return_concrete() FnMultiReturn[string, string, string] {
|
||||
return fn (s string) (string, string) {
|
||||
return s[..1], s[1..]
|
||||
}
|
||||
}
|
||||
|
||||
// vfmt will erase explicit generic type (bug reported in #17773)
|
||||
// vfmt off
|
||||
|
||||
fn test_concrete_function_type_as_generic_type() {
|
||||
@ -31,6 +39,11 @@ fn test_concrete_function_type_as_generic_type() {
|
||||
func_fn_dynamic[string]()('V')
|
||||
|
||||
assert func_fn_return_dynamic[string, int]()('100') == 100
|
||||
|
||||
s1, s2 := func_fn_multi_return_concrete()('VLang')
|
||||
|
||||
assert s1 == 'V'
|
||||
assert s2 == 'Lang'
|
||||
}
|
||||
|
||||
// vfmt on
|
||||
|
Loading…
Reference in New Issue
Block a user