Skip to content

Commit

Permalink
cgen: fix hash functions for map[Enum]Value, and `enum Enum as u64 …
Browse files Browse the repository at this point in the history
…{` (fix #23630) (#23632)
  • Loading branch information
spytheman authored Feb 2, 2025
1 parent f291ed8 commit 0132814
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 6 deletions.
15 changes: 9 additions & 6 deletions vlib/v/gen/c/cgen.v
Original file line number Diff line number Diff line change
Expand Up @@ -3328,14 +3328,14 @@ fn (mut g Gen) gen_clone_assignment(var_type ast.Type, val ast.Expr, typ ast.Typ
return true
}

fn (mut g Gen) map_fn_ptrs(key_typ ast.TypeSymbol) (string, string, string, string) {
fn (mut g Gen) map_fn_ptrs(key_sym ast.TypeSymbol) (string, string, string, string) {
mut hash_fn := ''
mut key_eq_fn := ''
mut clone_fn := ''
mut free_fn := '&map_free_nop'
match key_typ.kind {
match key_sym.kind {
.alias {
alias_key_type := (key_typ.info as ast.Alias).parent_type
alias_key_type := (key_sym.info as ast.Alias).parent_type
return g.map_fn_ptrs(g.table.sym(alias_key_type))
}
.u8, .i8, .char {
Expand All @@ -3348,8 +3348,11 @@ fn (mut g Gen) map_fn_ptrs(key_typ ast.TypeSymbol) (string, string, string, stri
key_eq_fn = '&map_eq_int_2'
clone_fn = '&map_clone_int_2'
}
.int, .i32, .u32, .rune, .f32, .enum {
// XTODO i64
.enum {
einfo := (key_sym.info) as ast.Enum
return g.map_fn_ptrs(g.table.sym(einfo.typ))
}
.int, .i32, .u32, .rune, .f32 {
hash_fn = '&map_hash_int_4'
key_eq_fn = '&map_eq_int_4'
clone_fn = '&map_clone_int_4'
Expand All @@ -3374,7 +3377,7 @@ fn (mut g Gen) map_fn_ptrs(key_typ ast.TypeSymbol) (string, string, string, stri
free_fn = '&map_free_string'
}
else {
verror('map key type `${key_typ.name}` not supported')
verror('map key type `${key_sym.name}` not supported')
}
}
return hash_fn, key_eq_fn, clone_fn, free_fn
Expand Down
47 changes: 47 additions & 0 deletions vlib/v/tests/enums/maps_with_enum_flag_keys_test.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// vfmt off
@[flag]
enum Bits8 as u8 {
a1 b1 c1 d1 e1 f1 g1 h1
}
@[flag]
enum Bits16 as u16 {
a1 b1 c1 d1 e1 f1 g1 h1
a2 b2 c2 d2 e2 f2 g2 h2
}
@[flag]
enum Bits32 as u32 {
a1 b1 c1 d1 e1 f1 g1 h1
a2 b2 c2 d2 e2 f2 g2 h2
a3 b3 c3 d3 e3 f3 g3 h3
a4 b4 c4 d4 e4 f4 g4 h4
}
@[flag]
enum Bits64 as u64 {
a1 b1 c1 d1 e1 f1 g1 h1
a2 b2 c2 d2 e2 f2 g2 h2
a3 b3 c3 d3 e3 f3 g3 h3
a4 b4 c4 d4 e4 f4 g4 h4
a5 b5 c5 d5 e5 f5 g5 h5
a6 b6 c6 d6 e6 f6 g6 h6
a7 b7 c7 d7 e7 f7 g7 h7
a8 b8 c8 d8 e8 f8 g8 h8
}
// vfmt on

fn check_map[T](size int) {
println('>>> checking map of ${T.name:10} enum keys, size should be: ${size}')
mut m := map[T]u32{}
for i in 0 .. size {
n := u64(1) << i
m[unsafe { T(n) }] = i
// eprintln('>>> i: ${i:2} | n: ${n:20} | m.len: ${m.len}')
}
assert m.len == size
}

fn test_maps_with_enum_keys_work() {
check_map[Bits8](8)
check_map[Bits16](16)
check_map[Bits32](32)
check_map[Bits64](64)
}

0 comments on commit 0132814

Please sign in to comment.