Skip to content

Commit

Permalink
all: allow using aliases as keys in map (#8589)
Browse files Browse the repository at this point in the history
  • Loading branch information
Delta456 authored Feb 8, 2021
1 parent 8cb01ba commit 09cff69
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 3 deletions.
2 changes: 1 addition & 1 deletion vlib/v/gen/c/cgen.v
Original file line number Diff line number Diff line change
Expand Up @@ -3724,7 +3724,7 @@ fn (mut g Gen) map_init(node ast.MapInit) {
key_typ_str := g.typ(node.key_type)
value_typ_str := g.typ(node.value_type)
value_typ := g.table.get_type_symbol(node.value_type)
key_typ := g.table.get_type_symbol(node.key_type)
key_typ := g.table.get_final_type_symbol(node.key_type)
hash_fn, key_eq_fn, clone_fn, free_fn := g.map_fn_ptrs(key_typ)
size := node.vals.len
mut shared_styp := '' // only needed for shared &[]{...}
Expand Down
8 changes: 7 additions & 1 deletion vlib/v/parser/parse_type.v
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,18 @@ pub fn (mut p Parser) parse_map_type() table.Type {
}
p.check(.lsbr)
key_type := p.parse_type()
is_alias := p.table.get_type_symbol(key_type).kind == .alias
if key_type.idx() == 0 {
// error is reported in parse_type
return 0
}
if !(key_type in [table.string_type_idx, table.voidptr_type_idx]
if is_alias && !(key_type in [table.string_type_idx, table.voidptr_type_idx]
|| ((key_type.is_int() || key_type.is_float()) && !key_type.is_ptr())) {
p.error('cannot use the alias type as the parent type is unsupported')
return 0
}
if !(key_type in [table.string_type_idx, table.voidptr_type_idx]
|| ((key_type.is_int() || key_type.is_float() || is_alias) && !key_type.is_ptr())) {
s := p.table.type_to_str(key_type)
p.error_with_pos('maps only support string, integer, float, rune or voidptr keys for now (not `$s`)',
p.tok.position())
Expand Down
2 changes: 1 addition & 1 deletion vlib/v/table/types.v
Original file line number Diff line number Diff line change
Expand Up @@ -550,7 +550,7 @@ pub fn (t &TypeSymbol) is_pointer() bool {

[inline]
pub fn (t &TypeSymbol) is_int() bool {
return t.kind in [.i8, .i16, .int, .i64, .byte, .u16, .u32, .u64, .int_literal]
return t.kind in [.i8, .i16, .int, .i64, .byte, .u16, .u32, .u64, .int_literal, .rune]
}

[inline]
Expand Down
22 changes: 22 additions & 0 deletions vlib/v/tests/map_alias_key_test.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
type Type = int
type RType = rune

fn test_map_key_alias() {
mut m_int := map{12: '12', 2: '2'}
m_int[14] = '14'
m_int[Type(15)] = '15'
assert m_int.str() == "{12: '12', 2: '2', 14: '14', 15: '15'}"
//// /// ///// //
mut m_rune := map{`a`: '12', `l`: '14'}
m_rune[`g`] = '12'
m_rune[RType(`$`)] = '16'
assert m_rune.str() == "{`a`: '12', `l`: '14', `g`: '12', `$`: '16'}"
}

fn test_map_alias_key_init() {
m_int := map{Type(12): '12', Type(2): '2'}
assert m_int.str() == "{12: '12', 2: '2'}"
//// // ///// //
m_rune := map{RType(`a`): '12', RType(`l`): '14'}
assert m_rune.str() == "{`a`: '12', `l`: '14'}"
}

0 comments on commit 09cff69

Please sign in to comment.