mirror of
https://github.com/vlang/v.git
synced 2025-09-16 10:57:25 -04:00
ast, cgen: fix generics map with the reference argument (#21737)
This commit is contained in:
parent
66c4307897
commit
f4d2389b2f
@ -1229,7 +1229,7 @@ pub fn (mut t Table) add_placeholder_type(name string, language Language) int {
|
||||
ph_type := TypeSymbol{
|
||||
kind: .placeholder
|
||||
name: name
|
||||
cname: util.no_dots(name)
|
||||
cname: util.no_dots(name).replace_each(['&', ''])
|
||||
language: language
|
||||
mod: modname
|
||||
}
|
||||
|
@ -648,7 +648,8 @@ fn (mut g Gen) struct_init_field(sfield ast.StructInitField, language ast.Langua
|
||||
inside_cast_in_heap := g.inside_cast_in_heap
|
||||
g.inside_cast_in_heap = 0 // prevent use of pointers in child structs
|
||||
|
||||
field_unwrap_sym := g.table.sym(g.unwrap_generic(sfield.typ))
|
||||
field_unwrap_typ := g.unwrap_generic(sfield.typ)
|
||||
field_unwrap_sym := g.table.sym(field_unwrap_typ)
|
||||
if field_unwrap_sym.kind == .array_fixed && sfield.expr in [ast.Ident, ast.SelectorExpr] {
|
||||
info := field_unwrap_sym.info as ast.ArrayFixed
|
||||
g.fixed_array_var_init(g.expr_string(sfield.expr), sfield.expr.is_auto_deref_var(),
|
||||
@ -658,21 +659,21 @@ fn (mut g Gen) struct_init_field(sfield ast.StructInitField, language ast.Langua
|
||||
tmp_var := g.expr_with_var(sfield.expr, sfield.typ, sfield.expected_type)
|
||||
g.fixed_array_var_init(tmp_var, false, info.elem_type, info.size)
|
||||
} else {
|
||||
if sfield.typ != ast.voidptr_type && sfield.typ != ast.nil_type
|
||||
if field_unwrap_typ != ast.voidptr_type && field_unwrap_typ != ast.nil_type
|
||||
&& (sfield.expected_type.is_ptr() && !sfield.expected_type.has_flag(.shared_f))
|
||||
&& !sfield.expected_type.has_flag(.option) && !sfield.typ.is_any_kind_of_pointer()
|
||||
&& !sfield.typ.is_number() {
|
||||
&& !sfield.expected_type.has_flag(.option)
|
||||
&& !field_unwrap_typ.is_any_kind_of_pointer() && !field_unwrap_typ.is_number() {
|
||||
g.write('/* autoref */&')
|
||||
}
|
||||
|
||||
if (sfield.expected_type.has_flag(.option) && !sfield.typ.has_flag(.option))
|
||||
|| (sfield.expected_type.has_flag(.result) && !sfield.typ.has_flag(.result)) {
|
||||
g.expr_with_opt(sfield.expr, sfield.typ, sfield.expected_type)
|
||||
if (sfield.expected_type.has_flag(.option) && !field_unwrap_typ.has_flag(.option))
|
||||
|| (sfield.expected_type.has_flag(.result) && !field_unwrap_typ.has_flag(.result)) {
|
||||
g.expr_with_opt(sfield.expr, field_unwrap_typ, sfield.expected_type)
|
||||
} else if sfield.expr is ast.LambdaExpr && sfield.expected_type.has_flag(.option) {
|
||||
g.expr_opt_with_cast(sfield.expr, sfield.typ, sfield.expected_type)
|
||||
g.expr_opt_with_cast(sfield.expr, field_unwrap_typ, sfield.expected_type)
|
||||
} else {
|
||||
g.left_is_opt = true
|
||||
g.expr_with_cast(sfield.expr, sfield.typ, sfield.expected_type)
|
||||
g.expr_with_cast(sfield.expr, field_unwrap_typ, sfield.expected_type)
|
||||
}
|
||||
}
|
||||
g.inside_cast_in_heap = inside_cast_in_heap // restore value for further struct inits
|
||||
|
92
vlib/v/tests/generics_map_with_reference_arg_test.v
Normal file
92
vlib/v/tests/generics_map_with_reference_arg_test.v
Normal file
@ -0,0 +1,92 @@
|
||||
import datatypes
|
||||
import time
|
||||
|
||||
struct Entry[V] {
|
||||
mut:
|
||||
value V
|
||||
load_time u32
|
||||
}
|
||||
|
||||
struct Lru[T, V] {
|
||||
mut:
|
||||
m map[T]Entry[V]
|
||||
list datatypes.DoublyLinkedList[T]
|
||||
cap u32 = 1000
|
||||
ttl u32 = 3
|
||||
on_del ?fn (T, V)
|
||||
pub mut:
|
||||
hits u32
|
||||
miss u32
|
||||
}
|
||||
|
||||
pub fn new[T, V](cap u32, ttl u32) &Lru[T, V] {
|
||||
return &Lru[T, V]{
|
||||
cap: cap
|
||||
ttl: ttl
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut l Lru[T, V]) set_on_del(on_del fn (T, V)) {
|
||||
l.on_del = on_del
|
||||
}
|
||||
|
||||
pub fn (mut l Lru[T, V]) add(k T, v V) {
|
||||
if l.m.len >= (l.cap * 97 / 100) {
|
||||
l.remove_expired(0)
|
||||
for l.m.len > (l.cap * 90 / 100) {
|
||||
l.del(l.list.pop_back() or { return })
|
||||
}
|
||||
}
|
||||
l.m[k] = Entry[V]{v, u32(time.now().unix())}
|
||||
l.list.push_front(k)
|
||||
}
|
||||
|
||||
pub fn (mut l Lru[T, V]) get(k T) ?V {
|
||||
l.remove_expired(0)
|
||||
if k in l.m {
|
||||
l.list.delete(l.list.index(k) or { return none })
|
||||
l.list.push_front(k)
|
||||
l.hits++
|
||||
return l.m[k].value
|
||||
}
|
||||
l.miss++
|
||||
return none
|
||||
}
|
||||
|
||||
pub fn (mut l Lru[T, V]) remove_expired(cnt int) {
|
||||
now := u32(time.now().unix())
|
||||
iter := l.list.back_iterator()
|
||||
del_cnt := 0
|
||||
for key in iter {
|
||||
if e := l.m[key] {
|
||||
if e.load_time + l.ttl >= now || (cnt > 0 && del_cnt >= cnt) {
|
||||
break
|
||||
}
|
||||
l.del(key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut l Lru[T, V]) del(k T) {
|
||||
if k in l.m {
|
||||
val := l.m[k].value
|
||||
l.m.delete(k)
|
||||
l.list.delete(l.list.index(k) or { -1 })
|
||||
on_del := l.on_del or { return }
|
||||
on_del(k, val)
|
||||
}
|
||||
}
|
||||
|
||||
struct TT {
|
||||
age int
|
||||
dd int
|
||||
}
|
||||
|
||||
fn test_generic_map_with_reference_arg() {
|
||||
mut c := new[int, &TT](10, 3)
|
||||
c.add(1, &TT{2, 2})
|
||||
ret := c.get(1)?
|
||||
println(ret)
|
||||
assert ret.age == 2
|
||||
assert ret.dd == 2
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user