mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
cgen: fix generic resolver on non generic function (#18381)
This commit is contained in:
parent
84a5fd0051
commit
e9960339f9
@ -1876,7 +1876,7 @@ fn (mut g Gen) expr_with_tmp_var(expr ast.Expr, expr_typ ast.Type, ret_typ ast.T
|
|||||||
}
|
}
|
||||||
|
|
||||||
stmt_str := g.go_before_stmt(0).trim_space()
|
stmt_str := g.go_before_stmt(0).trim_space()
|
||||||
styp := g.base_type(ret_typ)
|
mut styp := g.base_type(ret_typ)
|
||||||
g.empty_line = true
|
g.empty_line = true
|
||||||
|
|
||||||
if g.table.sym(expr_typ).kind == .none_ {
|
if g.table.sym(expr_typ).kind == .none_ {
|
||||||
@ -1885,7 +1885,21 @@ fn (mut g Gen) expr_with_tmp_var(expr ast.Expr, expr_typ ast.Type, ret_typ ast.T
|
|||||||
g.writeln(';')
|
g.writeln(';')
|
||||||
} else {
|
} else {
|
||||||
mut is_ptr_to_ptr_assign := false
|
mut is_ptr_to_ptr_assign := false
|
||||||
|
if ret_typ.has_flag(.generic) {
|
||||||
|
if expr is ast.SelectorExpr && g.cur_concrete_types.len == 0 {
|
||||||
|
// resolve generic struct on selectorExpr inside non-generic function
|
||||||
|
if expr.expr is ast.Ident && (expr.expr as ast.Ident).obj is ast.Var {
|
||||||
|
if ((expr.expr as ast.Ident).obj as ast.Var).expr is ast.StructInit {
|
||||||
|
g.cur_concrete_types << (g.table.sym((expr.expr as ast.Ident).obj.typ).info as ast.Struct).concrete_types
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
styp = g.base_type(g.unwrap_generic(ret_typ))
|
||||||
|
ret_styp := g.typ(g.unwrap_generic(ret_typ)).replace('*', '_ptr')
|
||||||
|
g.writeln('${ret_styp} ${tmp_var};')
|
||||||
|
} else {
|
||||||
g.writeln('${g.typ(ret_typ)} ${tmp_var};')
|
g.writeln('${g.typ(ret_typ)} ${tmp_var};')
|
||||||
|
}
|
||||||
if ret_typ.has_flag(.option) {
|
if ret_typ.has_flag(.option) {
|
||||||
if expr_typ.has_flag(.option) && expr in [ast.StructInit, ast.ArrayInit, ast.MapInit] {
|
if expr_typ.has_flag(.option) && expr in [ast.StructInit, ast.ArrayInit, ast.MapInit] {
|
||||||
if expr is ast.StructInit && (expr as ast.StructInit).init_fields.len > 0 {
|
if expr is ast.StructInit && (expr as ast.StructInit).init_fields.len > 0 {
|
||||||
@ -3693,8 +3707,9 @@ fn (mut g Gen) selector_expr(node ast.SelectorExpr) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
field_is_opt := node.expr is ast.Ident && (node.expr as ast.Ident).is_auto_heap()
|
// var?.field_opt
|
||||||
&& (node.expr as ast.Ident).or_expr.kind != .absent && field_typ.has_flag(.option)
|
field_is_opt := (node.expr is ast.Ident && (node.expr as ast.Ident).is_auto_heap()
|
||||||
|
&& (node.expr as ast.Ident).or_expr.kind != .absent && field_typ.has_flag(.option))
|
||||||
if field_is_opt {
|
if field_is_opt {
|
||||||
g.write('((${g.base_type(field_typ)})')
|
g.write('((${g.base_type(field_typ)})')
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,25 @@ fn (mut g Gen) unwrap_generic(typ ast.Type) ast.Type {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if typ.has_flag(.generic) && g.table.sym(typ).kind == .struct_ {
|
||||||
|
// resolve selector `a.foo` where `a` is struct[T] on non generic function
|
||||||
|
sym := g.table.sym(typ)
|
||||||
|
if sym.info is ast.Struct {
|
||||||
|
if sym.info.generic_types.len > 0 {
|
||||||
|
generic_names := sym.info.generic_types.map(g.table.sym(it).name)
|
||||||
|
if t_typ := mut_table.resolve_generic_to_concrete(typ, generic_names,
|
||||||
|
sym.info.concrete_types)
|
||||||
|
{
|
||||||
|
return t_typ
|
||||||
|
}
|
||||||
|
|
||||||
|
if t_typ := mut_table.resolve_generic_to_concrete(typ, generic_names,
|
||||||
|
g.cur_concrete_types)
|
||||||
|
{
|
||||||
|
return t_typ
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return typ
|
return typ
|
||||||
|
70
vlib/v/tests/generic_selector_test.v
Normal file
70
vlib/v/tests/generic_selector_test.v
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
pub struct List[T] {
|
||||||
|
mut:
|
||||||
|
head ?&Node[T]
|
||||||
|
size int
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (mut l List[T]) prepend(mut node Node[T]) {
|
||||||
|
if head := l.head {
|
||||||
|
node.next = head
|
||||||
|
l.head = &node
|
||||||
|
l.size = l.size + 1
|
||||||
|
} else {
|
||||||
|
l.size = 1
|
||||||
|
l.head = &node
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (mut l List[T]) append(mut node Node[T]) ?int {
|
||||||
|
if h := l.head {
|
||||||
|
_ := h
|
||||||
|
} else {
|
||||||
|
l.head = &node
|
||||||
|
l.size = 0
|
||||||
|
return l.size
|
||||||
|
}
|
||||||
|
|
||||||
|
mut curr_node := l.head
|
||||||
|
for {
|
||||||
|
if curr_node != none {
|
||||||
|
if next_node := curr_node?.next {
|
||||||
|
curr_node = next_node
|
||||||
|
} else {
|
||||||
|
curr_node?.next = &node
|
||||||
|
l.size = l.size + 1
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return l.size
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (mut l List[T]) find_last(node ?&Node[T]) ?&Node[T] {
|
||||||
|
if next := node?.next {
|
||||||
|
return l.find_last(next)
|
||||||
|
} else {
|
||||||
|
return node
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[heap]
|
||||||
|
pub struct Node[T] {
|
||||||
|
mut:
|
||||||
|
data T
|
||||||
|
next ?&Node[T]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_main() {
|
||||||
|
mut list := List[string]{}
|
||||||
|
list.prepend(mut Node{ data: 'zero' })
|
||||||
|
list.prepend(mut Node{ data: 'first' })
|
||||||
|
list.append(mut Node{ data: 'last' }) or { panic('unable to append linked list') }
|
||||||
|
list.append(mut Node{ data: 'very last' }) or { panic('unable to append linked list') }
|
||||||
|
|
||||||
|
assert list.find_last(list.head)? == Node{
|
||||||
|
data: 'very last'
|
||||||
|
}
|
||||||
|
assert list.head?.next?.next?.next? == Node{
|
||||||
|
data: 'very last'
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user