mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
cgen: fix generic struct init with generic cast (#16035)
This commit is contained in:
parent
dab1c8a71d
commit
34f233c93f
@ -211,6 +211,7 @@ mut:
|
||||
cur_concrete_types []ast.Type // do not use table.cur_concrete_types because table is global, so should not be accessed by different threads
|
||||
cur_fn &ast.FnDecl = unsafe { nil } // same here
|
||||
cur_lock ast.LockExpr
|
||||
cur_struct_init_typ ast.Type
|
||||
autofree_methods map[int]bool
|
||||
generated_free_methods map[int]bool
|
||||
autofree_scope_stmts []string
|
||||
@ -3300,7 +3301,9 @@ fn (mut g Gen) expr(node_ ast.Expr) {
|
||||
} else {
|
||||
// `user := User{name: 'Bob'}`
|
||||
g.inside_struct_init = true
|
||||
g.cur_struct_init_typ = node.typ
|
||||
g.struct_init(node)
|
||||
g.cur_struct_init_typ = 0
|
||||
g.inside_struct_init = false
|
||||
}
|
||||
}
|
||||
@ -4102,9 +4105,10 @@ fn (mut g Gen) ident(node ast.Ident) {
|
||||
}
|
||||
|
||||
fn (mut g Gen) cast_expr(node ast.CastExpr) {
|
||||
sym := g.table.sym(node.typ)
|
||||
node_typ := g.unwrap_generic(node.typ)
|
||||
sym := g.table.sym(node_typ)
|
||||
if sym.kind in [.sum_type, .interface_] {
|
||||
g.expr_with_cast(node.expr, node.expr_type, node.typ)
|
||||
g.expr_with_cast(node.expr, node.expr_type, node_typ)
|
||||
} else if sym.kind == .struct_ && !node.typ.is_ptr() && !(sym.info as ast.Struct).is_typedef {
|
||||
// deprecated, replaced by Struct{...exr}
|
||||
styp := g.typ(node.typ)
|
||||
@ -4117,7 +4121,7 @@ fn (mut g Gen) cast_expr(node ast.CastExpr) {
|
||||
}
|
||||
g.expr(node.expr)
|
||||
} else if node.expr_type == ast.bool_type && node.typ.is_int() {
|
||||
styp := g.typ(node.typ)
|
||||
styp := g.typ(node_typ)
|
||||
g.write('($styp[]){(')
|
||||
g.expr(node.expr)
|
||||
g.write(')?1:0}[0]')
|
||||
@ -4150,7 +4154,7 @@ fn (mut g Gen) cast_expr(node ast.CastExpr) {
|
||||
}
|
||||
g.expr(node.expr)
|
||||
if node.expr is ast.IntegerLiteral {
|
||||
if node.typ in [ast.u64_type, ast.u32_type, ast.u16_type] {
|
||||
if node_typ in [ast.u64_type, ast.u32_type, ast.u16_type] {
|
||||
if !node.expr.val.starts_with('-') {
|
||||
g.write('U')
|
||||
}
|
||||
|
@ -15,16 +15,27 @@ fn (mut g Gen) unwrap_generic(typ ast.Type) ast.Type {
|
||||
// This should have already happened in the checker, since it also calls
|
||||
// `resolve_generic_to_concrete`. `g.table` is made non-mut to make sure
|
||||
// no one else can accidentally mutates the table.
|
||||
unsafe {
|
||||
mut mut_table := &ast.Table(g.table)
|
||||
if t_typ := mut_table.resolve_generic_to_concrete(typ, if g.cur_fn != nil {
|
||||
g.cur_fn.generic_names
|
||||
} else {
|
||||
[]string{}
|
||||
}, g.cur_concrete_types)
|
||||
mut mut_table := unsafe { &ast.Table(g.table) }
|
||||
if g.cur_fn != unsafe { nil } && g.cur_fn.generic_names.len > 0 {
|
||||
if t_typ := mut_table.resolve_generic_to_concrete(typ, g.cur_fn.generic_names,
|
||||
g.cur_concrete_types)
|
||||
{
|
||||
return t_typ
|
||||
}
|
||||
} else if g.inside_struct_init {
|
||||
if g.cur_struct_init_typ != 0 {
|
||||
sym := g.table.sym(g.cur_struct_init_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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return typ
|
||||
|
21
vlib/v/tests/generic_struct_init_with_generic_cast_test.v
Normal file
21
vlib/v/tests/generic_struct_init_with_generic_cast_test.v
Normal file
@ -0,0 +1,21 @@
|
||||
pub struct Range<T> {
|
||||
start T
|
||||
end T [required]
|
||||
step T = T(1)
|
||||
mut:
|
||||
now T
|
||||
}
|
||||
|
||||
fn test_generic_struct_init_with_generic_cast() {
|
||||
r1 := Range<int>{
|
||||
end: 10
|
||||
}
|
||||
println(r1)
|
||||
|
||||
r2 := Range<f64>{
|
||||
end: 2.2
|
||||
}
|
||||
println(r2)
|
||||
|
||||
assert true
|
||||
}
|
Loading…
Reference in New Issue
Block a user