Skip to content

Commit 7b7400c

Browse files
committed
cgen: resolve generic map types in concrete contexts
1 parent 17571b6 commit 7b7400c

8 files changed

Lines changed: 320 additions & 24 deletions

File tree

vlib/v/gen/c/cgen.v

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8393,8 +8393,9 @@ fn (mut g Gen) lock_expr_mtx(expr ast.Expr) {
83938393
}
83948394

83958395
fn (mut g Gen) map_init(node ast.MapInit) {
8396-
unwrap_key_typ := g.unwrap_generic(node.key_type)
8397-
unwrap_val_typ := g.unwrap_generic(node.value_type).clear_flag(.result)
8396+
unwrap_key_typ, unwrap_val_typ_ := g.resolved_map_key_value_types(node.typ, node.key_type,
8397+
node.value_type)
8398+
unwrap_val_typ := unwrap_val_typ_.clear_flag(.result)
83988399
key_typ_str := g.styp(unwrap_key_typ)
83998400
value_typ_str := g.styp(unwrap_val_typ)
84008401
value_sym := g.table.sym(unwrap_val_typ)
@@ -8416,8 +8417,8 @@ fn (mut g Gen) map_init(node ast.MapInit) {
84168417
styp = g.styp(node.typ)
84178418
g.write('(${styp}*)builtin__memdup(ADDR(${styp}, ')
84188419
}
8419-
noscan_key := g.check_noscan(node.key_type)
8420-
noscan_value := g.check_noscan(node.value_type)
8420+
noscan_key := g.check_noscan(unwrap_key_typ)
8421+
noscan_value := g.check_noscan(unwrap_val_typ)
84218422
mut noscan := if noscan_key.len != 0 || noscan_value.len != 0 { '_noscan' } else { '' }
84228423
if noscan.len != 0 {
84238424
if noscan_key.len != 0 {

vlib/v/gen/c/if.v

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,25 @@ module c
55

66
import v.ast
77

8+
fn (mut g Gen) resolved_if_guard_expr_type(expr ast.Expr, default_type ast.Type) ast.Type {
9+
if expr is ast.IndexExpr {
10+
left_type := g.resolved_map_type_from_expr(expr.left, expr.left_type)
11+
left_sym := g.table.final_sym(g.unwrap_generic(left_type))
12+
if left_sym.kind == .map {
13+
map_info := left_sym.map_info()
14+
_, mut value_type := g.resolved_map_key_value_types(left_type, map_info.key_type,
15+
map_info.value_type)
16+
if default_type.has_flag(.option) && !value_type.has_flag(.option) {
17+
value_type = value_type.set_flag(.option)
18+
} else if default_type.has_flag(.result) && !value_type.has_flag(.result) {
19+
value_type = value_type.set_flag(.result)
20+
}
21+
return value_type
22+
}
23+
}
24+
return g.unwrap_generic(g.recheck_concrete_type(default_type))
25+
}
26+
827
fn (mut g Gen) if_guard_var_needs_gc_pin(scope &ast.Scope, name string) bool {
928
if g.pref.gc_mode !in [.boehm_full, .boehm_incr, .boehm_full_opt, .boehm_incr_opt] {
1029
return false
@@ -509,7 +528,7 @@ fn (mut g Gen) if_expr(node ast.IfExpr) {
509528
}
510529
}
511530
} else {
512-
resolved := g.unwrap_generic(g.recheck_concrete_type(guard_expr_type))
531+
resolved := g.resolved_if_guard_expr_type(branch.cond.expr, guard_expr_type)
513532
if resolved != ast.void_type {
514533
guard_expr_type = resolved
515534
}

vlib/v/gen/c/index.v

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -689,14 +689,7 @@ fn (mut g Gen) index_of_fixed_array(node ast.IndexExpr, sym ast.TypeSymbol) {
689689

690690
fn (mut g Gen) index_of_map(node ast.IndexExpr, sym ast.TypeSymbol) {
691691
gen_or := node.or_expr.kind != .absent || node.is_option
692-
mut map_left_type := g.recheck_concrete_type(node.left_type)
693-
resolved_left_type := g.recheck_concrete_type(g.resolved_expr_type(node.left, node.left_type))
694-
if resolved_left_type != 0
695-
&& (g.cur_concrete_types.len > 0 || map_left_type == 0 || map_left_type.has_flag(.generic)
696-
|| g.type_has_unresolved_generic_parts(map_left_type)
697-
|| g.unwrap_generic(resolved_left_type) != g.unwrap_generic(map_left_type)) {
698-
map_left_type = resolved_left_type
699-
}
692+
map_left_type := g.resolved_map_type_from_expr(node.left, node.left_type)
700693
mut left_is_ptr := map_left_type.is_ptr()
701694
if !left_is_ptr && g.is_assign_lhs && node.left is ast.Ident
702695
&& g.resolved_ident_is_auto_heap(node.left) {
@@ -712,14 +705,10 @@ fn (mut g Gen) index_of_map(node ast.IndexExpr, sym ast.TypeSymbol) {
712705
} else {
713706
sym.info as ast.Map
714707
}
715-
mut key_type := g.unwrap_generic(g.recheck_concrete_type(info.key_type))
716-
mut val_type := g.unwrap_generic(g.recheck_concrete_type(info.value_type))
717-
if key_type == 0 {
718-
key_type = info.key_type
719-
}
720-
if val_type == 0 {
721-
val_type = info.value_type
722-
}
708+
key_type_, val_type_ := g.resolved_map_key_value_types(map_left_type, info.key_type,
709+
info.value_type)
710+
mut key_type := key_type_
711+
mut val_type := val_type_
723712
if node.left is ast.Ident {
724713
ident_key_type := g.resolved_ident_map_key_type(node.left)
725714
if ident_key_type != 0 {

vlib/v/gen/c/struct.v

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1087,7 +1087,18 @@ fn (mut g Gen) struct_init_field_value(sfield ast.StructInitField) {
10871087
expected_unwrap_typ := g.unwrap_generic(sfield.expected_type)
10881088
expected_unwrap_sym := g.table.final_sym(expected_unwrap_typ)
10891089
is_auto_deref_var := sfield.expr.is_auto_deref_var()
1090-
if expected_unwrap_sym.info is ast.ArrayFixed && sfield.expr is ast.ArrayInit
1090+
if expected_unwrap_sym.kind == .map && sfield.expr is ast.MapInit
1091+
&& !sfield.expected_type.has_option_or_result()
1092+
&& !sfield.expected_type.has_flag(.shared_f)
1093+
&& !sfield.expected_type.has_flag(.atomic_f) {
1094+
expected_map_info := expected_unwrap_sym.map_info()
1095+
g.map_init(ast.MapInit{
1096+
...sfield.expr
1097+
typ: expected_unwrap_typ
1098+
key_type: expected_map_info.key_type
1099+
value_type: expected_map_info.value_type
1100+
})
1101+
} else if expected_unwrap_sym.info is ast.ArrayFixed && sfield.expr is ast.ArrayInit
10911102
&& !sfield.expr.is_fixed && !sfield.expr.has_len && !sfield.expr.has_init
10921103
&& sfield.expr.exprs.len > 0 && !sfield.expected_type.has_flag(.option) {
10931104
fixed_array_expr := ast.ArrayInit{

vlib/v/gen/c/utils.v

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -924,6 +924,52 @@ fn (mut g Gen) resolved_ident_map_value_type(expr ast.Ident) ast.Type {
924924
return 0
925925
}
926926

927+
fn (mut g Gen) resolved_map_key_value_types(map_type ast.Type, fallback_key_type ast.Type, fallback_value_type ast.Type) (ast.Type, ast.Type) {
928+
mut key_type := g.unwrap_generic(g.recheck_concrete_type(fallback_key_type))
929+
mut value_type := g.unwrap_generic(g.recheck_concrete_type(fallback_value_type))
930+
resolved_map_type := g.unwrap_generic(g.recheck_concrete_type(map_type))
931+
map_sym := g.table.final_sym(resolved_map_type)
932+
if map_sym.kind == .map {
933+
map_info := map_sym.map_info()
934+
resolved_key := g.unwrap_generic(g.recheck_concrete_type(map_info.key_type))
935+
resolved_value := g.unwrap_generic(g.recheck_concrete_type(map_info.value_type))
936+
if resolved_key != 0 {
937+
key_type = resolved_key
938+
}
939+
if resolved_value != 0 {
940+
value_type = resolved_value
941+
}
942+
if key_type == ast.usize_type || value_type == ast.usize_type {
943+
name_key_type, name_value_type := g.resolved_map_types_from_name(map_sym.name)
944+
if key_type == ast.usize_type && name_key_type != 0 {
945+
key_type = name_key_type
946+
}
947+
if value_type == ast.usize_type && name_value_type != 0 {
948+
value_type = name_value_type
949+
}
950+
}
951+
}
952+
if key_type == 0 {
953+
key_type = fallback_key_type
954+
}
955+
if value_type == 0 {
956+
value_type = fallback_value_type
957+
}
958+
return key_type, value_type
959+
}
960+
961+
fn (mut g Gen) resolved_map_type_from_expr(expr ast.Expr, default_type ast.Type) ast.Type {
962+
mut map_type := g.recheck_concrete_type(default_type)
963+
resolved_type := g.recheck_concrete_type(g.resolved_expr_type(expr, default_type))
964+
if resolved_type != 0
965+
&& (g.cur_concrete_types.len > 0 || map_type == 0 || map_type.has_flag(.generic)
966+
|| g.type_has_unresolved_generic_parts(map_type)
967+
|| g.unwrap_generic(resolved_type) != g.unwrap_generic(map_type)) {
968+
map_type = resolved_type
969+
}
970+
return map_type
971+
}
972+
927973
fn (mut g Gen) resolved_array_elem_type_from_name(name string) ast.Type {
928974
if !name.starts_with('[]') {
929975
return 0

vlib/v/generics/new_generics_regression_test.v

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,9 +117,9 @@ fn run_new_generic_solver_tests(root_label string, test_cmd string, expected_sum
117117
println('')
118118
}
119119

120-
const expected_summsvc_generics = 'Summary for all V _test.v files: 114 failed, 180 passed, 294 total.'
120+
const expected_summsvc_generics = 'Summary for all V _test.v files: 115 failed, 180 passed, 295 total.'
121121
// The exact failure count varies slightly across compilers.
122-
const expected_summary_generics = 'Summary for all V _test.v files: 110 failed, 183 passed, 293 total.'
122+
const expected_summary_generics = 'Summary for all V _test.v files: 111 failed, 184 passed, 295 total.'
123123
const expected_summsvc_vec = 'Summary for all V _test.v files: 3 failed, 3 total.'
124124
const expected_summary_vec = 'Summary for all V _test.v files: 3 failed, 3 total.'
125125
const expected_summsvc_flag = 'Summary for all V _test.v files: 21 passed, 21 total.'
@@ -155,6 +155,7 @@ const failing_tests = [
155155
'vlib/v/tests/generics/generic_lambda_expr_test.v',
156156
'vlib/v/tests/generics/generic_linked_list_ref_push_test.v',
157157
'vlib/v/tests/generics/generic_map_alias_test.v',
158+
'vlib/v/tests/generics/generic_map_value_in_generic_struct_method_test.v',
158159
'vlib/v/tests/generics/generic_match_expr_test.v',
159160
'vlib/v/tests/generics/generic_match_generic_interface_type_test.v',
160161
'vlib/v/tests/generics/generic_method_fn_field_result_recheck_test.v',

0 commit comments

Comments
 (0)