@@ -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
2324pub 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