1
0
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:
ChAoS_UnItY
2023-03-26 16:29:52 +08:00
committed by GitHub
parent 8759409a69
commit 34f5f05efa
2 changed files with 50 additions and 12 deletions

View File

@ -2105,7 +2105,7 @@ pub fn (mut t Table) generic_insts_to_concrete() {
} }
mut fields := parent_info.fields.clone() mut fields := parent_info.fields.clone()
if parent_info.generic_types.len == info.concrete_types.len { 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 { for i in 0 .. fields.len {
if fields[i].typ.has_flag(.generic) { if fields[i].typ.has_flag(.generic) {
if fields[i].typ.idx() != info.parent_idx { 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 { if parent_info.generic_types.len == info.concrete_types.len {
mut fields := parent_info.fields.clone() 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 { for i in 0 .. fields.len {
if t_typ := t.resolve_generic_to_concrete(fields[i].typ, generic_names, if t_typ := t.resolve_generic_to_concrete(fields[i].typ, generic_names,
info.concrete_types) 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 { if parent_info.generic_types.len == info.concrete_types.len {
mut fields := parent_info.fields.clone() mut fields := parent_info.fields.clone()
mut variants := parent_info.variants.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 { for i in 0 .. fields.len {
if t_typ := t.resolve_generic_to_concrete(fields[i].typ, generic_names, if t_typ := t.resolve_generic_to_concrete(fields[i].typ, generic_names,
info.concrete_types) 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? // TODO: Cache function's generic types (parameters and return type) like Struct and Interface etc. do?
mut parent_info := parent.info as FnType mut parent_info := parent.info as FnType
mut function := parent_info.func mut function := parent_info.func
mut generic_names := []string{cap: function.params.len + 1} mut generic_types := []Type{cap: function.params.len + 1}
generic_names << function.params.filter(it.typ.has_flag(.generic)).map(t.sym(it.typ).name) generic_types << function.params.filter(it.typ.has_flag(.generic)).map(it.typ)
if function.return_type.has_flag(.generic) { 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 { for mut param in function.params {
if param.typ.has_flag(.generic) { if param.typ.has_flag(.generic) {
if t_typ := t.resolve_generic_to_concrete(param.typ, generic_names, 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 function.return_type.has_flag(.generic) {
if return_type.has_flag(.generic) { if t_typ := t.resolve_generic_to_concrete(function.return_type,
if return_type.idx() != info.parent_idx { generic_names, info.concrete_types)
return_type = t.unwrap_generic_type(return_type, generic_names, {
info.concrete_types) function.return_type = t_typ
} }
} }
sym.info = FnType{ 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 { pub fn (t &Table) is_comptime_type(x Type, y ComptimeType) bool {
x_kind := t.type_kind(x) x_kind := t.type_kind(x)
match y.kind { match y.kind {

View File

@ -2,6 +2,8 @@ type Fn = fn (T)
type FnReturn = fn (T) R type FnReturn = fn (T) R
type FnMultiReturn = fn (I) (O, R)
fn func_fn_concrete() Fn[string] { fn func_fn_concrete() Fn[string] {
return fn (_s 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 // vfmt off
fn test_concrete_function_type_as_generic_type() { 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') func_fn_dynamic[string]()('V')
assert func_fn_return_dynamic[string, int]()('100') == 100 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 // vfmt on