Skip to content

Commit

Permalink
all: cleanup resolve_generic_to_concrete() and related methods (#22433)
Browse files Browse the repository at this point in the history
  • Loading branch information
yuyi98 authored Oct 7, 2024
1 parent f4c0484 commit 184a863
Show file tree
Hide file tree
Showing 18 changed files with 192 additions and 220 deletions.
106 changes: 44 additions & 62 deletions vlib/v/ast/table.v
Original file line number Diff line number Diff line change
Expand Up @@ -1570,15 +1570,15 @@ pub fn (t Table) does_type_implement_interface(typ Type, inter_typ Type) bool {
return false
}

pub fn (mut t Table) resolve_generic_static_type_name(fn_name string, generic_names []string, concrete_types []Type) string {
pub fn (mut t Table) convert_generic_static_type_name(fn_name string, generic_names []string, concrete_types []Type) string {
if index := fn_name.index('__static__') {
if index > 0 {
generic_name := fn_name[0..index]
valid_generic := util.is_generic_type_name(generic_name)
&& generic_name in generic_names
if valid_generic {
name_type := idx_to_type(t.find_type_idx(generic_name)).set_flag(.generic)
if typ := t.resolve_generic_to_concrete(name_type, generic_names, concrete_types) {
if typ := t.convert_generic_type(name_type, generic_names, concrete_types) {
return '${t.type_to_str(typ)}${fn_name[index..]}'
}
}
Expand All @@ -1587,20 +1587,18 @@ pub fn (mut t Table) resolve_generic_static_type_name(fn_name string, generic_na
return fn_name
}

// resolve_generic_to_concrete resolves generics to real types T => int.
// Even map[string]map[string]T can be resolved.
// This is used for resolving the generic return type of CallExpr white `unwrap_generic` is used to resolve generic usage in FnDecl.
pub fn (mut t Table) resolve_generic_to_concrete(generic_type Type, generic_names []string, concrete_types []Type) ?Type {
if generic_names.len != concrete_types.len {
// convert_generic_type convert generics to real types (T => int) or other generics type.
pub fn (mut t Table) convert_generic_type(generic_type Type, generic_names []string, to_types []Type) ?Type {
if generic_names.len != to_types.len {
return none
}
mut sym := t.sym(generic_type)
if sym.name in generic_names {
index := generic_names.index(sym.name)
if index >= concrete_types.len {
if index >= to_types.len {
return none
}
typ := concrete_types[index]
typ := to_types[index]
if typ == 0 {
return none
}
Expand All @@ -1613,7 +1611,7 @@ pub fn (mut t Table) resolve_generic_to_concrete(generic_type Type, generic_name
match mut sym.info {
Array {
dims, elem_type := t.get_array_dims(sym.info)
if typ := t.resolve_generic_to_concrete(elem_type, generic_names, concrete_types) {
if typ := t.convert_generic_type(elem_type, generic_names, to_types) {
idx := t.find_or_register_array_with_dims(typ, dims)
if typ.has_flag(.generic) {
return new_type(idx).derive_add_muls(generic_type).set_flag(.generic)
Expand All @@ -1623,9 +1621,7 @@ pub fn (mut t Table) resolve_generic_to_concrete(generic_type Type, generic_name
}
}
ArrayFixed {
if typ := t.resolve_generic_to_concrete(sym.info.elem_type, generic_names,
concrete_types)
{
if typ := t.convert_generic_type(sym.info.elem_type, generic_names, to_types) {
idx := t.find_or_register_array_fixed(typ, sym.info.size, None{}, false)
if typ.has_flag(.generic) {
return new_type(idx).derive_add_muls(generic_type).set_flag(.generic)
Expand All @@ -1635,9 +1631,7 @@ pub fn (mut t Table) resolve_generic_to_concrete(generic_type Type, generic_name
}
}
Chan {
if typ := t.resolve_generic_to_concrete(sym.info.elem_type, generic_names,
concrete_types)
{
if typ := t.convert_generic_type(sym.info.elem_type, generic_names, to_types) {
idx := t.find_or_register_chan(typ, typ.nr_muls() > 0)
if typ.has_flag(.generic) {
return new_type(idx).derive_add_muls(generic_type).set_flag(.generic)
Expand All @@ -1647,9 +1641,7 @@ pub fn (mut t Table) resolve_generic_to_concrete(generic_type Type, generic_name
}
}
Thread {
if typ := t.resolve_generic_to_concrete(sym.info.return_type, generic_names,
concrete_types)
{
if typ := t.convert_generic_type(sym.info.return_type, generic_names, to_types) {
idx := t.find_or_register_thread(typ)
if typ.has_flag(.generic) {
return new_type(idx).derive_add_muls(generic_type).set_flag(.generic)
Expand All @@ -1662,9 +1654,7 @@ pub fn (mut t Table) resolve_generic_to_concrete(generic_type Type, generic_name
mut func := sym.info.func
mut has_generic := false
if func.return_type.has_flag(.generic) {
if typ := t.resolve_generic_to_concrete(func.return_type, generic_names,
concrete_types)
{
if typ := t.convert_generic_type(func.return_type, generic_names, to_types) {
func.return_type = typ
if typ.has_flag(.generic) {
has_generic = true
Expand All @@ -1674,9 +1664,7 @@ pub fn (mut t Table) resolve_generic_to_concrete(generic_type Type, generic_name
func.params = func.params.clone()
for mut param in func.params {
if param.typ.has_flag(.generic) {
if typ := t.resolve_generic_to_concrete(param.typ, generic_names,
concrete_types)
{
if typ := t.convert_generic_type(param.typ, generic_names, to_types) {
param.typ = typ
if typ.has_flag(.generic) {
has_generic = true
Expand All @@ -1697,7 +1685,7 @@ pub fn (mut t Table) resolve_generic_to_concrete(generic_type Type, generic_name
mut types := []Type{}
mut type_changed := false
for ret_type in sym.info.types {
if typ := t.resolve_generic_to_concrete(ret_type, generic_names, concrete_types) {
if typ := t.convert_generic_type(ret_type, generic_names, to_types) {
types << typ
type_changed = true
} else {
Expand All @@ -1717,15 +1705,11 @@ pub fn (mut t Table) resolve_generic_to_concrete(generic_type Type, generic_name
mut type_changed := false
mut unwrapped_key_type := sym.info.key_type
mut unwrapped_value_type := sym.info.value_type
if typ := t.resolve_generic_to_concrete(sym.info.key_type, generic_names,
concrete_types)
{
if typ := t.convert_generic_type(sym.info.key_type, generic_names, to_types) {
unwrapped_key_type = typ
type_changed = true
}
if typ := t.resolve_generic_to_concrete(sym.info.value_type, generic_names,
concrete_types)
{
if typ := t.convert_generic_type(sym.info.value_type, generic_names, to_types) {
unwrapped_value_type = typ
type_changed = true
}
Expand All @@ -1743,32 +1727,30 @@ pub fn (mut t Table) resolve_generic_to_concrete(generic_type Type, generic_name
mut nrt := '${sym.name}['
mut rnrt := '${sym.rname}['
mut t_generic_names := generic_names.clone()
mut t_concrete_types := concrete_types.clone()
mut t_to_types := to_types.clone()
if sym.generic_types.len > 0 && sym.generic_types.len == sym.info.generic_types.len
&& sym.generic_types != sym.info.generic_types {
t_generic_names = sym.info.generic_types.map(t.sym(it).name)
t_concrete_types = []
t_to_types = []
for t_typ in sym.generic_types {
if !t_typ.has_flag(.generic) {
t_concrete_types << t_typ
t_to_types << t_typ
} else if t.sym(t_typ).kind == .any {
tname := t.sym(t_typ).name
index := generic_names.index(tname)
if index >= 0 && index < concrete_types.len {
t_concrete_types << concrete_types[index]
if index >= 0 && index < to_types.len {
t_to_types << to_types[index]
}
} else {
if tt := t.resolve_generic_to_concrete(t_typ, generic_names,
concrete_types)
{
t_concrete_types << tt
if tt := t.convert_generic_type(t_typ, generic_names, to_types) {
t_to_types << tt
}
}
}
}
for i in 0 .. sym.info.generic_types.len {
if ct := t.resolve_generic_to_concrete(sym.info.generic_types[i],
t_generic_names, t_concrete_types)
if ct := t.convert_generic_type(sym.info.generic_types[i], t_generic_names,
t_to_types)
{
gts := t.sym(ct)
if ct.is_ptr() {
Expand Down Expand Up @@ -1923,7 +1905,7 @@ pub fn (mut t Table) unwrap_generic_type(typ Type, generic_names []string, concr
nrt = '${ts.name}['
c_nrt = '${ts.cname}_T_'
for i in 0 .. ts.info.generic_types.len {
if ct := t.resolve_generic_to_concrete(ts.info.generic_types[i], t_generic_names,
if ct := t.convert_generic_type(ts.info.generic_types[i], t_generic_names,
t_concrete_types)
{
gts := t.sym(ct)
Expand Down Expand Up @@ -1955,7 +1937,7 @@ pub fn (mut t Table) unwrap_generic_type(typ Type, generic_names []string, concr
fields[i].typ = t.unwrap_generic_type(fields[i].typ, t_generic_names,
t_concrete_types)
} else {
if t_typ := t.resolve_generic_to_concrete(fields[i].typ, t_generic_names,
if t_typ := t.convert_generic_type(fields[i].typ, t_generic_names,
t_concrete_types)
{
fields[i].typ = t_typ
Expand Down Expand Up @@ -1984,8 +1966,8 @@ pub fn (mut t Table) unwrap_generic_type(typ Type, generic_names []string, concr
}
// update concrete types
for i in 0 .. ts.info.generic_types.len {
if t_typ := t.resolve_generic_to_concrete(ts.info.generic_types[i],
t_generic_names, t_concrete_types)
if t_typ := t.convert_generic_type(ts.info.generic_types[i], t_generic_names,
t_concrete_types)
{
final_concrete_types << t_typ
}
Expand Down Expand Up @@ -2044,7 +2026,7 @@ pub fn (mut t Table) unwrap_generic_type(typ Type, generic_names []string, concr
variants[i] = t.unwrap_generic_type(variants[i], generic_names,
concrete_types)
} else {
if t_typ := t.resolve_generic_to_concrete(variants[i], generic_names,
if t_typ := t.convert_generic_type(variants[i], generic_names,
concrete_types)
{
variants[i] = t_typ
Expand Down Expand Up @@ -2075,13 +2057,13 @@ pub fn (mut t Table) unwrap_generic_type(typ Type, generic_names []string, concr
// resolve generic types inside methods
mut imethods := ts.info.methods.clone()
for mut method in imethods {
if unwrap_typ := t.resolve_generic_to_concrete(method.return_type, generic_names,
if unwrap_typ := t.convert_generic_type(method.return_type, generic_names,
concrete_types)
{
method.return_type = unwrap_typ
}
for mut param in method.params {
if unwrap_typ := t.resolve_generic_to_concrete(param.typ, generic_names,
if unwrap_typ := t.convert_generic_type(param.typ, generic_names,
concrete_types)
{
param.typ = unwrap_typ
Expand Down Expand Up @@ -2148,8 +2130,8 @@ pub fn (mut t Table) generic_insts_to_concrete() {
fields[i].typ = t.unwrap_generic_type(fields[i].typ,
generic_names, info.concrete_types)
}
if t_typ := t.resolve_generic_to_concrete(fields[i].typ,
generic_names, info.concrete_types)
if t_typ := t.convert_generic_type(fields[i].typ, generic_names,
info.concrete_types)
{
fields[i].typ = t_typ
}
Expand Down Expand Up @@ -2196,7 +2178,7 @@ pub fn (mut t Table) generic_insts_to_concrete() {
mut fields := parent_info.fields.clone()
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,
if t_typ := t.convert_generic_type(fields[i].typ, generic_names,
info.concrete_types)
{
fields[i].typ = t_typ
Expand All @@ -2205,14 +2187,14 @@ pub fn (mut t Table) generic_insts_to_concrete() {
mut imethods := parent_info.methods.clone()
for mut method in imethods {
method.generic_names.clear()
if pt := t.resolve_generic_to_concrete(method.return_type,
generic_names, info.concrete_types)
if pt := t.convert_generic_type(method.return_type, generic_names,
info.concrete_types)
{
method.return_type = pt
}
method.params = method.params.clone()
for mut param in method.params {
if pt := t.resolve_generic_to_concrete(param.typ, generic_names,
if pt := t.convert_generic_type(param.typ, generic_names,
info.concrete_types)
{
param.typ = pt
Expand Down Expand Up @@ -2254,7 +2236,7 @@ pub fn (mut t Table) generic_insts_to_concrete() {
mut variants := parent_info.variants.clone()
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,
if t_typ := t.convert_generic_type(fields[i].typ, generic_names,
info.concrete_types)
{
fields[i].typ = t_typ
Expand All @@ -2267,8 +2249,8 @@ pub fn (mut t Table) generic_insts_to_concrete() {
variants[i] = t.unwrap_generic_type(variants[i], generic_names,
info.concrete_types)
} else {
if t_typ := t.resolve_generic_to_concrete(variants[i],
generic_names, info.concrete_types)
if t_typ := t.convert_generic_type(variants[i], generic_names,
info.concrete_types)
{
variants[i] = t_typ
}
Expand All @@ -2295,16 +2277,16 @@ pub fn (mut t Table) generic_insts_to_concrete() {
function.params = function.params.clone()
for mut param in function.params {
if param.typ.has_flag(.generic) {
if t_typ := t.resolve_generic_to_concrete(param.typ, function.generic_names,
if t_typ := t.convert_generic_type(param.typ, function.generic_names,
info.concrete_types)
{
param.typ = t_typ
}
}
}
if function.return_type.has_flag(.generic) {
if t_typ := t.resolve_generic_to_concrete(function.return_type,
function.generic_names, info.concrete_types)
if t_typ := t.convert_generic_type(function.return_type, function.generic_names,
info.concrete_types)
{
function.return_type = t_typ
}
Expand Down
6 changes: 3 additions & 3 deletions vlib/v/ast/types.v
Original file line number Diff line number Diff line change
Expand Up @@ -1708,16 +1708,16 @@ pub fn (t &TypeSymbol) find_method_with_generic_parent(name string) ?Fn {
method.return_type = table.unwrap_generic_type(method.return_type,
generic_names, t.info.concrete_types)
} else {
if rt := table.resolve_generic_to_concrete(method.return_type,
if rt := table.convert_generic_type(method.return_type,
generic_names, t.info.concrete_types)
{
method.return_type = rt
}
}
method.params = method.params.clone()
for mut param in method.params {
if pt := table.resolve_generic_to_concrete(param.typ,
generic_names, t.info.concrete_types)
if pt := table.convert_generic_type(param.typ, generic_names,
t.info.concrete_types)
{
param.typ = pt
}
Expand Down
2 changes: 1 addition & 1 deletion vlib/v/checker/check_types.v
Original file line number Diff line number Diff line change
Expand Up @@ -1092,7 +1092,7 @@ fn (mut c Checker) infer_fn_generic_types(func ast.Fn, mut node ast.CallExpr) {
}
// resolve lambda with generic return type
if arg.expr is ast.LambdaExpr && typ.has_flag(.generic) {
typ = c.comptime.resolve_generic_expr(arg.expr.expr, typ)
typ = c.comptime.unwrap_generic_expr(arg.expr.expr, typ)
if typ.has_flag(.generic) {
lambda_ret_gt_name := c.table.type_to_str(typ)
idx := func.generic_names.index(lambda_ret_gt_name)
Expand Down
12 changes: 6 additions & 6 deletions vlib/v/checker/checker.v
Original file line number Diff line number Diff line change
Expand Up @@ -1051,7 +1051,7 @@ fn (mut c Checker) type_implements(typ ast.Type, interface_type ast.Type, pos to
}
mut inferred_type := interface_type
if generic_info.is_generic {
inferred_type = c.resolve_generic_interface(typ, generic_type, pos)
inferred_type = c.unwrap_generic_interface(typ, generic_type, pos)
if inferred_type == 0 {
return false
}
Expand Down Expand Up @@ -2739,18 +2739,18 @@ fn (mut c Checker) unwrap_generic(typ ast.Type) ast.Type {
if typ.has_flag(.generic) {
if c.inside_generic_struct_init {
generic_names := c.cur_struct_generic_types.map(c.table.sym(it).name)
if t_typ := c.table.resolve_generic_to_concrete(typ, generic_names, c.cur_struct_concrete_types) {
if t_typ := c.table.convert_generic_type(typ, generic_names, c.cur_struct_concrete_types) {
return t_typ
}
}
if c.table.cur_fn != unsafe { nil } {
if t_typ := c.table.resolve_generic_to_concrete(typ, c.table.cur_fn.generic_names,
if t_typ := c.table.convert_generic_type(typ, c.table.cur_fn.generic_names,
c.table.cur_concrete_types)
{
return t_typ
}
if c.inside_lambda && c.table.cur_lambda.call_ctx != unsafe { nil } {
if t_typ := c.table.resolve_generic_to_concrete(typ, c.table.cur_lambda.func.decl.generic_names,
if t_typ := c.table.convert_generic_type(typ, c.table.cur_lambda.func.decl.generic_names,
c.table.cur_lambda.call_ctx.concrete_types)
{
return t_typ
Expand Down Expand Up @@ -3326,7 +3326,7 @@ fn (mut c Checker) cast_expr(mut node ast.CastExpr) ast.Type {
c.mark_as_referenced(mut &node.expr, true)
}
if to_sym.info.is_generic {
inferred_type := c.resolve_generic_interface(from_type, to_type, node.pos)
inferred_type := c.unwrap_generic_interface(from_type, to_type, node.pos)
if inferred_type != 0 {
to_type = inferred_type
to_sym = c.table.sym(to_type)
Expand Down Expand Up @@ -3717,7 +3717,7 @@ fn (mut c Checker) resolve_var_fn(func ast.Fn, mut node ast.Ident, name string)
mut fn_type := ast.new_type(c.table.find_or_register_fn_type(func, false, true))
if func.generic_names.len > 0 {
concrete_types := node.concrete_types.map(c.unwrap_generic(it))
if typ_ := c.table.resolve_generic_to_concrete(fn_type, func.generic_names, concrete_types) {
if typ_ := c.table.convert_generic_type(fn_type, func.generic_names, concrete_types) {
fn_type = typ_
if concrete_types.all(!it.has_flag(.generic)) {
c.table.register_fn_concrete_types(func.fkey(), concrete_types)
Expand Down
Loading

0 comments on commit 184a863

Please sign in to comment.