Skip to content

Commit c3b924c

Browse files
authored
v.generics: improve the new generics stage, by fixing unwrapping in nested generic struct, also fix suggestions from previous PR (#26430)
1 parent 97340a9 commit c3b924c

File tree

1 file changed

+31
-27
lines changed

1 file changed

+31
-27
lines changed

vlib/v/generics/generics.v

Lines changed: 31 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,14 @@ const option_name = ast.option_name
1414
pub struct Generics {
1515
pref &pref.Preferences
1616
pub mut:
17-
table &ast.Table = unsafe { nil }
18-
file &ast.File = unsafe { nil }
19-
styp_cache map[ast.Type]string
20-
cur_fn &ast.FnDecl = unsafe { nil }
21-
cur_concrete_types []ast.Type
22-
inside_struct_init bool
23-
cur_struct_init_typ ast.Type
24-
forin_types map[string]ast.Type // maps the name of the elem variable (`for elem in my_array`) to the solved type
17+
table &ast.Table = unsafe { nil }
18+
file &ast.File = unsafe { nil }
19+
styp_cache map[ast.Type]string
20+
cur_fn &ast.FnDecl = unsafe { nil }
21+
cur_concrete_types []ast.Type
22+
inside_struct_init bool
23+
cur_struct_init_node &ast.StructInit = unsafe { nil }
24+
forin_types map[string]ast.Type // maps the name of the elem variable (`for elem in my_array`) to the solved type
2525
}
2626

2727
pub fn new_generics(pref_ &pref.Preferences) &Generics {
@@ -377,10 +377,6 @@ fn (mut g Generics) register_result(t ast.Type) string {
377377
return styp
378378
}
379379

380-
// TODO: this really shouldn't be separate from typ
381-
// but I(emily) would rather have this generation
382-
// all unified in one place so that it doesn't break
383-
// if one location changes
384380
fn (mut g Generics) option_type_name(t ast.Type) (string, string) {
385381
mut base := g.base_type(t)
386382
mut styp := ''
@@ -452,12 +448,12 @@ fn (mut g Generics) cc_type(typ ast.Type, is_prefix_struct bool) string {
452448
return styp
453449
}
454450

455-
pub fn (mut g Generics) method_concrete_name(old_name string, concrete_types []ast.Type, _receiver_type ast.Type) string {
451+
pub fn (mut g Generics) method_concrete_name(old_name string, concrete_types []ast.Type, receiver_type ast.Type) string {
456452
mut name := old_name
457-
if _receiver_type != 0 {
458-
mut info := g.table.sym(g.unwrap_generic(_receiver_type)).info
453+
if receiver_type != 0 {
454+
mut info := g.table.sym(g.unwrap_generic(receiver_type)).info
459455
if mut info is ast.Alias {
460-
info = g.table.sym(g.table.unaliased_type(g.unwrap_generic(_receiver_type))).info
456+
info = g.table.sym(g.table.unaliased_type(g.unwrap_generic(receiver_type))).info
461457
}
462458
if mut info is ast.Struct {
463459
fn_conc_types := concrete_types#[info.generic_types.len..] // concrete types without the generic types of the struct
@@ -1171,33 +1167,40 @@ pub fn (mut g Generics) expr(mut node ast.Expr) ast.Expr {
11711167
}
11721168
ast.StructInit {
11731169
if g.cur_concrete_types.len > 0 {
1170+
old_inside_struct_init := g.inside_struct_init
11741171
g.inside_struct_init = true
1175-
g.cur_struct_init_typ = node.typ
1172+
old_cur_struct_init_node := g.cur_struct_init_node
1173+
g.cur_struct_init_node = unsafe { &node }
1174+
11761175
mut init_fields := node.init_fields.clone()
11771176
for mut init_field in init_fields {
11781177
init_field.expr = g.expr(mut init_field.expr)
1178+
init_field.typ = g.unwrap_generic(init_field.typ)
1179+
init_field.expected_type = g.unwrap_generic(init_field.expected_type)
1180+
init_field.parent_type = g.unwrap_generic(init_field.parent_type)
11791181
}
1182+
11801183
out := ast.Expr(ast.StructInit{
11811184
...node
11821185
typ: g.unwrap_generic(node.typ)
11831186
typ_str: g.table.type_str(g.unwrap_generic(node.typ))
1184-
generic_types: []
1187+
generic_types: node.generic_types.map(g.unwrap_generic(it))
11851188
update_expr: g.expr(mut node.update_expr)
11861189
update_expr_type: g.unwrap_generic(node.update_expr_type)
11871190
init_fields: init_fields
11881191
})
1189-
g.cur_struct_init_typ = 0
1190-
g.inside_struct_init = false
1192+
1193+
g.cur_struct_init_node = old_cur_struct_init_node
1194+
g.inside_struct_init = old_inside_struct_init
11911195
return out
11921196
}
1197+
old_inside_struct_init := g.inside_struct_init
11931198
g.inside_struct_init = true
1194-
g.cur_struct_init_typ = node.typ
11951199
node.update_expr = g.expr(mut node.update_expr)
11961200
for mut init_field in node.init_fields {
11971201
init_field.expr = g.expr(mut init_field.expr)
11981202
}
1199-
g.cur_struct_init_typ = 0
1200-
g.inside_struct_init = false
1203+
g.inside_struct_init = old_inside_struct_init
12011204
}
12021205
ast.TypeNode {
12031206
if g.cur_concrete_types.len > 0 {
@@ -1239,13 +1242,14 @@ fn (mut g Generics) unwrap_generic(typ ast.Type) ast.Type {
12391242
if t_typ := g.table.convert_generic_type(typ, g.cur_fn.generic_names, g.cur_concrete_types) {
12401243
return t_typ
12411244
}
1242-
} else if g.inside_struct_init {
1243-
if g.cur_struct_init_typ != 0 {
1244-
sym := g.table.sym(g.cur_struct_init_typ)
1245+
}
1246+
if g.inside_struct_init && g.cur_struct_init_node != unsafe { nil } {
1247+
if g.cur_struct_init_node.typ != 0 {
1248+
sym := g.table.sym(g.cur_struct_init_node.typ)
12451249
if sym.info is ast.Struct {
12461250
if sym.info.generic_types.len > 0 {
12471251
generic_names := sym.info.generic_types.map(g.table.sym(it).name)
1248-
if t_typ := g.table.convert_generic_type(typ, generic_names, sym.info.concrete_types) {
1252+
if t_typ := g.table.convert_generic_type(typ, generic_names, g.cur_struct_init_node.generic_types.map(g.unwrap_generic(it))) {
12491253
return t_typ
12501254
}
12511255
}

0 commit comments

Comments
 (0)