1
0
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:
yuyi 2022-10-11 20:00:02 +08:00 committed by GitHub
parent dab1c8a71d
commit 34f233c93f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 47 additions and 11 deletions

View File

@ -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')
}

View File

@ -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

View 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
}