Skip to content

Commit 89d1aac

Browse files
authored
checker, cgen: fix aggregate var handling on match branch (fix #23768) (#23787)
1 parent 5376a55 commit 89d1aac

9 files changed

Lines changed: 44 additions & 10 deletions

File tree

‎vlib/v/ast/ast.v‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -884,6 +884,7 @@ pub enum ComptimeVarKind {
884884
generic_param // generic fn parameter
885885
generic_var // generic var
886886
smartcast // smart cast when used in `is v` (when `v` is from $for .variants)
887+
aggregate // aggregate var
887888
}
888889

889890
@[minify]

‎vlib/v/checker/checker.v‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4331,6 +4331,8 @@ fn (mut c Checker) smartcast(mut expr ast.Expr, cur_type ast.Type, to_type_ ast.
43314331
is_inherited = expr.obj.is_inherited
43324332
ct_type_var = if is_comptime {
43334333
.smartcast
4334+
} else if c.table.type_kind(to_type_) == .aggregate {
4335+
.aggregate
43344336
} else {
43354337
.no_comptime
43364338
}

‎vlib/v/checker/str.v‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ fn (mut c Checker) get_default_fmt(ftyp ast.Type, typ ast.Type) u8 {
3232
return `s`
3333
}
3434
if ftyp in [ast.string_type, ast.bool_type]
35-
|| sym.kind in [.enum, .array, .array_fixed, .struct, .map, .multi_return, .sum_type, .interface, .none]
35+
|| sym.kind in [.enum, .array, .array_fixed, .struct, .map, .multi_return, .sum_type, .interface, .aggregate, .none]
3636
|| ftyp.has_option_or_result() || sym.has_method('str') {
3737
return `s`
3838
} else {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5022,7 +5022,7 @@ fn (mut g Gen) ident(node ast.Ident) {
50225022
if node.info is ast.IdentVar {
50235023
if node.obj is ast.Var {
50245024
if !g.is_assign_lhs
5025-
&& node.obj.ct_type_var !in [.smartcast, .generic_param, .no_comptime] {
5025+
&& node.obj.ct_type_var !in [.smartcast, .generic_param, .no_comptime, .aggregate] {
50265026
comptime_type := g.type_resolver.get_type(node)
50275027
if comptime_type.has_flag(.option) {
50285028
if (g.inside_opt_or_res || g.left_is_opt) && node.or_expr.kind == .absent {

‎vlib/v/gen/c/infix.v‎

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -836,11 +836,7 @@ fn (mut g Gen) infix_expr_in_optimization(left ast.Expr, left_type ast.Type, rig
836836
fn (mut g Gen) infix_expr_is_op(node ast.InfixExpr) {
837837
mut left_sym := g.table.sym(g.unwrap_generic(g.type_resolver.get_type_or_default(node.left,
838838
node.left_type)))
839-
is_aggregate := left_sym.kind == .aggregate
840-
if is_aggregate {
841-
parent_left_type := (left_sym.info as ast.Aggregate).sum_type
842-
left_sym = g.table.sym(parent_left_type)
843-
}
839+
is_aggregate := node.left is ast.Ident && g.comptime.get_ct_type_var(node.left) == .aggregate
844840
right_sym := g.table.sym(node.right_type)
845841
if left_sym.kind == .interface && right_sym.kind == .interface {
846842
g.gen_interface_is_op(node)
@@ -880,7 +876,7 @@ fn (mut g Gen) infix_expr_is_op(node ast.InfixExpr) {
880876
sub_sym := g.table.sym(sub_type)
881877
g.write('_${left_sym.cname}_${sub_sym.cname}_index')
882878
return
883-
} else if left_sym.kind == .sum_type {
879+
} else if left_sym.kind == .sum_type || is_aggregate {
884880
g.write('_typ ${cmp_op} ')
885881
}
886882
if node.right is ast.None {

‎vlib/v/gen/c/match.v‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,9 @@ fn (mut g Gen) match_expr_sumtype(node ast.MatchExpr, is_expr bool, cond_var str
218218
}
219219
cur_expr := unsafe { &branch.exprs[sumtype_index] }
220220
if cond_sym.kind == .sum_type {
221+
if cur_expr is ast.TypeNode {
222+
g.type_resolver.update_ct_type(cond_var, cur_expr.typ)
223+
}
221224
g.write('${dot_or_ptr}_typ == ')
222225
if cur_expr is ast.None {
223226
g.write('${ast.none_type.idx()} /* none */')
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
module main
2+
3+
type Value = int | i64 | u64 | string | []u8
4+
5+
fn d(val Value) string {
6+
match val {
7+
int, i64, u64, []u8 {
8+
s := sizeof(val)
9+
x := val
10+
return 'Value is number or byte array, size=${s} ${x}'
11+
}
12+
string {
13+
x := val
14+
return 'Value is string: ${x}'
15+
}
16+
}
17+
}
18+
19+
fn test_main() {
20+
assert d(Value(0)) == 'Value is number or byte array, size=4 0'
21+
assert d(Value(i64(1))) == 'Value is number or byte array, size=8 1'
22+
assert d(Value(u64(2))) == 'Value is number or byte array, size=8 2'
23+
assert d(Value([u8(1), 2])) == 'Value is number or byte array, size=32 [1, 2]'
24+
assert d(Value('')) == 'Value is string: '
25+
}

‎vlib/v/tests/typeof_aggregate_test.v‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,6 @@ fn test_typeof_aggregate() {
4141

4242
assert rets.len == 3
4343
assert rets[0] == 'The type of `a` is `Foo`'
44-
assert rets[1] == 'The type of `a` is `(Bar | Baz | Bazaar)` and its text says bar'
45-
assert rets[2] == 'The type of `a` is `(Bar | Baz | Bazaar)` and its text says baz'
44+
assert rets[1] == 'The type of `a` is `Bar` and its text says bar'
45+
assert rets[2] == 'The type of `a` is `Baz` and its text says baz'
4646
}

‎vlib/v/type_resolver/type_resolver.v‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,13 @@ pub fn (mut t TypeResolver) get_type(node ast.Expr) ast.Type {
190190
ctyp
191191
}
192192
}
193+
.aggregate {
194+
t.get_ct_type_or_default(node.name, if node.obj.smartcasts.len > 0 {
195+
node.obj.smartcasts.last()
196+
} else {
197+
node.obj.typ
198+
})
199+
}
193200
.key_var, .value_var {
194201
// key and value variables from normal for stmt
195202
t.get_ct_type_or_default(node.name, ast.void_type)

0 commit comments

Comments
 (0)