Skip to content

Commit b2a0f68

Browse files
authored
cgen: fix comptime for types not being recognized with maps correctly (fix #25742) (#25743)
1 parent 1963632 commit b2a0f68

File tree

3 files changed

+93
-9
lines changed

3 files changed

+93
-9
lines changed

vlib/v/gen/c/assign.v

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1132,17 +1132,51 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
11321132
fn (mut g Gen) gen_multi_return_assign(node &ast.AssignStmt, return_type ast.Type, return_sym ast.TypeSymbol) {
11331133
// multi return
11341134
// TODO: Handle in if_expr
1135-
mr_var_name := 'mr_${node.pos.pos}'
1136-
mut is_option := return_type.has_flag(.option)
1137-
mut mr_styp := g.styp(return_type.clear_flag(.result))
1135+
mut ret_type := return_type
1136+
mut ret_sym := return_sym
1137+
mut suffix := ''
1138+
if g.comptime.inside_comptime_for && node.right[0] is ast.CallExpr {
1139+
call_expr := node.right[0] as ast.CallExpr
1140+
if call_expr.concrete_types.len > 0 && return_sym.info is ast.MultiReturn
1141+
&& g.comptime.comptime_for_field_var != '' {
1142+
field_type := g.comptime.comptime_for_field_type
1143+
field_sym := g.table.sym(field_type)
1144+
if field_sym.info is ast.Map {
1145+
map_info := field_sym.info as ast.Map
1146+
ret_type = g.table.find_or_register_multi_return([map_info.key_type, map_info.value_type])
1147+
ret_sym = *g.table.sym(ret_type)
1148+
}
1149+
}
1150+
if g.comptime.comptime_for_field_var != '' {
1151+
suffix = '_${g.comptime.comptime_for_field_value.name}'
1152+
}
1153+
}
1154+
mr_var_name := 'mr_${node.pos.pos}${suffix}'
1155+
mut is_option := ret_type.has_flag(.option)
1156+
mut mr_styp := g.styp(ret_type.clear_flag(.result))
11381157
if node.right[0] is ast.CallExpr && node.right[0].or_block.kind != .absent {
11391158
is_option = false
1140-
mr_styp = g.styp(return_type.clear_option_and_result())
1159+
mr_styp = g.styp(ret_type.clear_option_and_result())
11411160
}
11421161
g.write('${mr_styp} ${mr_var_name} = ')
11431162
g.expr(node.right[0])
11441163
g.writeln(';')
1145-
mr_types := (return_sym.info as ast.MultiReturn).types
1164+
mr_types := (ret_sym.info as ast.MultiReturn).types
1165+
mut recompute_types := false
1166+
if g.comptime.inside_comptime_for && node.right[0] is ast.CallExpr {
1167+
call_expr := node.right[0] as ast.CallExpr
1168+
if call_expr.concrete_types.len > 0 && g.comptime.comptime_for_field_var != ''
1169+
&& return_sym.info is ast.MultiReturn {
1170+
recompute_types = true
1171+
for i, mut lx in &node.left {
1172+
if mut lx is ast.Ident && lx.kind != .blank_ident {
1173+
if mut lx.obj is ast.Var {
1174+
lx.obj.typ = mr_types[i]
1175+
}
1176+
}
1177+
}
1178+
}
1179+
}
11461180
for i, lx in node.left {
11471181
mut cur_indexexpr := -1
11481182
mut is_auto_heap := false
@@ -1161,7 +1195,8 @@ fn (mut g Gen) gen_multi_return_assign(node &ast.AssignStmt, return_type ast.Typ
11611195
if lx is ast.IndexExpr && g.cur_indexexpr.len > 0 {
11621196
cur_indexexpr = g.cur_indexexpr.index(lx.pos.pos)
11631197
}
1164-
styp := if ident.name in g.defer_vars { '' } else { g.styp(node.left_types[i]) }
1198+
left_type := if recompute_types { mr_types[i] } else { node.left_types[i] }
1199+
styp := if ident.name in g.defer_vars { '' } else { g.styp(left_type) }
11651200
if node.op == .decl_assign {
11661201
g.write('${styp} ')
11671202
}
@@ -1170,14 +1205,14 @@ fn (mut g Gen) gen_multi_return_assign(node &ast.AssignStmt, return_type ast.Typ
11701205
}
11711206
noscan := if is_auto_heap { g.check_noscan(return_type) } else { '' }
11721207
mut aligned := 0
1173-
sym := g.table.final_sym(node.left_types[i])
1208+
sym := g.table.final_sym(left_type)
11741209
if sym.info is ast.Struct {
11751210
if attr := sym.info.attrs.find_first('aligned') {
11761211
aligned = if attr.arg == '' { 0 } else { attr.arg.int() }
11771212
}
11781213
}
1179-
if node.left_types[i].has_flag(.option) {
1180-
base_typ := g.base_type(node.left_types[i])
1214+
if left_type.has_flag(.option) {
1215+
base_typ := g.base_type(left_type)
11811216
tmp_var := if is_auto_heap {
11821217
if aligned != 0 {
11831218
'HEAP_align(${styp}, ${mr_var_name}.arg${i}, ${aligned})'

vlib/v/gen/c/str_intp.v

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,11 @@ fn (mut g Gen) str_val(node ast.StringInterLiteral, i int, fmts []u8) {
191191
fmt := fmts[i]
192192
typ := g.unwrap_generic(node.expr_types[i])
193193
typ_sym := g.table.sym(typ)
194+
if g.comptime.inside_comptime_for && expr is ast.SelectorExpr && expr.field_name == 'name'
195+
&& expr.expr is ast.TypeOf {
196+
g.expr(expr)
197+
return
198+
}
194199
if typ == ast.string_type && g.comptime.comptime_for_method == unsafe { nil } {
195200
if g.inside_vweb_tmpl {
196201
g.write('${g.vweb_filter_fn_name}(')
@@ -278,6 +283,24 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) {
278283
mut node_ := unsafe { node }
279284
mut fmts := node_.fmts.clone()
280285
for i, mut expr in node_.exprs {
286+
mut type_to_use := node_.expr_types[i]
287+
if g.comptime.inside_comptime_for && mut expr is ast.SelectorExpr {
288+
if expr.expr is ast.TypeOf && expr.field_name == 'name' {
289+
// This is typeof(var).name
290+
typeof_expr := expr.expr as ast.TypeOf
291+
if typeof_expr.expr is ast.Ident {
292+
ident_name := (typeof_expr.expr as ast.Ident).name
293+
// Check if this ident might be from a multi-return in the current scope
294+
// For now, force re-evaluation by looking it up in the comptime context
295+
if obj := typeof_expr.expr.scope.find(ident_name) {
296+
if obj is ast.Var {
297+
// Use the var's actual type, which might be correct in codegen context
298+
type_to_use = obj.typ
299+
}
300+
}
301+
}
302+
}
303+
}
281304
if g.comptime.is_comptime(expr) {
282305
ctyp := g.type_resolver.get_type_or_default(expr, node_.expr_types[i])
283306
if ctyp != ast.void_type {
@@ -292,6 +315,8 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) {
292315
fmts[i] = g.get_default_fmt(ctyp, typ)
293316
}
294317
}
318+
} else {
319+
node_.expr_types[i] = type_to_use
295320
}
296321
}
297322
g.write2('builtin__str_intp(', node.vals.len.str())
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
struct Maps {
2+
a map[string]int
3+
b map[string]bool
4+
c map[string]f64
5+
}
6+
7+
fn decode_struct[T](t T) []string {
8+
mut decoded := []string{}
9+
$for f in T.fields {
10+
$if f is $map {
11+
k, v := map_key_value(t.$(f.name))
12+
decoded << '${typeof(k).name} ${typeof(v).name}'
13+
}
14+
}
15+
return decoded
16+
}
17+
18+
fn map_key_value[K, V](m map[K]V) (K, V) {
19+
return K{}, V{}
20+
}
21+
22+
fn test_main() {
23+
assert decode_struct(Maps{}) == ['string int', 'string bool', 'string f64']
24+
}

0 commit comments

Comments
 (0)