Skip to content

Commit 5fbe692

Browse files
authored
v: improve the new generic stage (solve elem type in for elem in my_array when my_array is T and other fixes) (#26323)
1 parent 92aba98 commit 5fbe692

3 files changed

Lines changed: 75 additions & 11 deletions

File tree

‎vlib/v/comptime/comptime.v‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,12 +148,28 @@ pub fn (mut c Comptime) is_true(expr ast.Expr) !bool {
148148
return c.table.sym(expr.left.typ).info is ast.Map
149149
} else if expr.right.kind == .struct {
150150
return c.table.sym(expr.left.typ).info is ast.Struct
151+
} else if expr.right.kind == .int {
152+
return expr.left.typ.is_int()
151153
}
152154
// TODO do the other types
155+
} else if expr.right is ast.TypeNode {
156+
return expr.left.typ == expr.right.typ
157+
}
158+
} else if expr.left is ast.SelectorExpr {
159+
if expr.left.field_name == 'typ' && expr.left.expr is ast.Ident {
160+
if expr.left.expr.info is ast.IdentFn {
161+
if expr.right is ast.TypeNode {
162+
return expr.left.expr.info.typ == expr.right.typ
163+
}
164+
}
153165
}
154166
}
155167
}
156168
}
169+
ast.NodeError {
170+
// else
171+
return true
172+
}
157173
else {}
158174
}
159175
return error('Cannot solve')

‎vlib/v/gen/c/cgen.v‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4303,6 +4303,9 @@ fn (mut g Gen) selector_expr(node ast.SelectorExpr) {
43034303
mut name_type := node.name_type
43044304
if node.expr is ast.TypeOf {
43054305
name_type = g.type_resolver.typeof_type(node.expr.expr, name_type)
4306+
if name_type == ast.void_type_idx {
4307+
name_type = node.name_type
4308+
}
43064309
}
43074310
g.type_name(name_type)
43084311
return

‎vlib/v/generics/generics.v‎

Lines changed: 56 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ pub mut:
1818
cur_concrete_types []ast.Type
1919
inside_struct_init bool
2020
cur_struct_init_typ ast.Type
21+
forin_types map[string]ast.Type // maps the name of the elem variable (`for elem in my_array`) to the solved type
2122
}
2223

2324
pub fn new_generics(pref_ &pref.Preferences) &Generics {
@@ -217,7 +218,19 @@ pub fn (mut g Generics) stmt(mut node ast.Stmt) ast.Stmt {
217218
ast.ForInStmt {
218219
if g.cur_concrete_types.len > 0 {
219220
mut stmts := node.stmts.clone()
220-
return ast.Stmt(ast.ForInStmt{
221+
if mut node.cond is ast.Ident && node.cond.ct_expr {
222+
// Solve the type for elem in `for elem in my_array` when my_array is T
223+
unwrapped_typ := g.unwrap_generic(node.cond_type)
224+
node.val_type = g.table.value_type(unwrapped_typ)
225+
if node.val_is_mut {
226+
node.val_type = node.val_type.ref()
227+
}
228+
g.forin_types[node.val_var] = node.val_type
229+
defer(fn) {
230+
g.forin_types.delete(node.val_var)
231+
}
232+
}
233+
mut new_node := ast.ForInStmt{
221234
...node
222235
cond: g.expr(mut node.cond)
223236
high: g.expr(mut node.high)
@@ -226,7 +239,8 @@ pub fn (mut g Generics) stmt(mut node ast.Stmt) ast.Stmt {
226239
cond_type: g.unwrap_generic(node.cond_type)
227240
high_type: g.unwrap_generic(node.high_type)
228241
stmts: g.stmts(mut stmts)
229-
})
242+
}
243+
return ast.Stmt(new_node)
230244
}
231245
node.stmts = g.stmts(mut node.stmts)
232246
}
@@ -473,17 +487,30 @@ pub fn (mut g Generics) expr(mut node ast.Expr) ast.Expr {
473487
ast.CallExpr {
474488
if g.cur_concrete_types.len > 0 {
475489
mut args := node.args.clone()
476-
for mut arg in args {
477-
arg.typ = g.unwrap_generic(arg.typ)
478-
arg.expr = g.expr(mut arg.expr)
479-
}
480490
mut all_concrete_types := node.concrete_types.clone()
481491
for mut ct in all_concrete_types {
482492
idx := g.cur_fn.generic_names.index(g.table.type_str(ct))
483493
if idx != -1 {
484494
ct = g.cur_concrete_types[idx]
485495
}
486496
}
497+
for i, mut arg in args {
498+
arg.typ = g.unwrap_generic(arg.typ)
499+
arg.expr = g.expr(mut arg.expr)
500+
if mut arg.expr is ast.Ident {
501+
// Solve concrete_types when the type of one argument was elem in `for elem in my_array` when my_array is T
502+
forin_type := g.forin_types[arg.expr.name]
503+
if forin_type != 0 {
504+
if func := g.table.find_fn(node.name) {
505+
solved_type_generic_name := g.table.type_str(func.params[i].typ)
506+
idx := func.generic_names.index(solved_type_generic_name)
507+
if idx != -1 {
508+
all_concrete_types[idx] = forin_type
509+
}
510+
}
511+
}
512+
}
513+
}
487514
return ast.Expr(ast.CallExpr{
488515
...node
489516
name: g.concrete_name(node.name, all_concrete_types)
@@ -619,24 +646,31 @@ pub fn (mut g Generics) expr(mut node ast.Expr) ast.Expr {
619646
if g.cur_concrete_types.len > 0 {
620647
is_ct_type_generic := node.obj.ct_type_var == .generic_param
621648
|| node.obj.ct_type_var == .generic_var
622-
unwrapped_typ := g.unwrap_generic(node.obj.typ)
649+
is_ct_type_forin_val := node.obj.ct_type_var == .value_var // elem in `for elem in my_array` when my_array is T
650+
unwrapped_typ := if is_ct_type_forin_val {
651+
g.forin_types[node.name]
652+
} else {
653+
g.unwrap_generic(node.obj.typ)
654+
}
623655
return ast.Expr(ast.Ident{
624656
...node
625-
obj: ast.Var{
657+
obj: ast.Var{
626658
...node.obj
627659
typ: unwrapped_typ
628660
smartcasts: node.obj.smartcasts.map(g.unwrap_generic(it))
629661
is_auto_deref: node.obj.is_auto_deref
630662
|| (node.obj.typ.has_flag(.generic)
631663
&& g.table.sym(unwrapped_typ).kind in [.sum_type, .interface])
632664
// node.obj.orig_type = g.unwrap_generic(node.obj.orig_type)
633-
ct_type_unwrapped: is_ct_type_generic || node.obj.ct_type_unwrapped
634-
ct_type_var: if is_ct_type_generic {
665+
ct_type_unwrapped: is_ct_type_generic || is_ct_type_forin_val
666+
|| node.obj.ct_type_unwrapped
667+
ct_type_var: if is_ct_type_generic || is_ct_type_forin_val {
635668
.no_comptime
636669
} else {
637670
node.obj.ct_type_var
638671
}
639672
}
673+
ct_expr: !is_ct_type_forin_val && node.ct_expr
640674
})
641675
}
642676
}
@@ -857,6 +891,7 @@ pub fn (mut g Generics) expr(mut node ast.Expr) ast.Expr {
857891
typ: g.unwrap_generic(node.typ)
858892
name_type: g.unwrap_generic(node.name_type)
859893
from_embed_types: node.from_embed_types.map(g.unwrap_generic(it))
894+
gkind_field: .unknown
860895
})
861896
}
862897
node.expr = g.expr(mut node.expr)
@@ -936,7 +971,7 @@ pub fn (mut g Generics) expr(mut node ast.Expr) ast.Expr {
936971
...node
937972
typ: g.unwrap_generic(node.typ)
938973
typ_str: g.table.type_str(g.unwrap_generic(node.typ))
939-
generic_types: node.generic_types.map(g.unwrap_generic(it))
974+
generic_types: []
940975
update_expr: g.expr(mut node.update_expr)
941976
update_expr_type: g.unwrap_generic(node.update_expr_type)
942977
init_fields: init_fields
@@ -964,6 +999,16 @@ pub fn (mut g Generics) expr(mut node ast.Expr) ast.Expr {
964999
}
9651000
node.stmt = g.stmt(mut node.stmt)
9661001
}
1002+
ast.TypeOf {
1003+
if g.cur_concrete_types.len > 0 {
1004+
return ast.Expr(ast.TypeOf{
1005+
...node
1006+
typ: g.unwrap_generic(node.typ)
1007+
expr: g.expr(mut node.expr)
1008+
})
1009+
}
1010+
node.expr = g.expr(mut node.expr)
1011+
}
9671012
ast.UnsafeExpr {
9681013
if g.cur_concrete_types.len > 0 {
9691014
return ast.Expr(ast.UnsafeExpr{

0 commit comments

Comments
 (0)