cgen: fix codegen for generic structinit and generic array return (fix #23916) (#23943)

This commit is contained in:
Felipe Pena 2025-03-16 08:09:56 -03:00 committed by GitHub
parent e995d991f1
commit 1f10a65515
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 55 additions and 0 deletions

View File

@ -991,6 +991,17 @@ fn (mut g Gen) call_expr(node ast.CallExpr) {
if unaliased_type.has_option_or_result() {
ret_typ = unaliased_type
}
} else if node.return_type_generic != 0 && node.raw_concrete_types.len == 0 {
unwrapped_ret_typ := g.unwrap_generic(node.return_type_generic)
if !unwrapped_ret_typ.has_flag(.generic) {
ret_sym := g.table.sym(unwrapped_ret_typ)
if ret_sym.info is ast.Array && g.table.sym(node.return_type_generic).kind == .array {
// Make []T returns T type when array was supplied to T
if g.table.type_to_str(node.return_type_generic).count('[]') < g.table.type_to_str(unwrapped_ret_typ).count('[]') {
ret_typ = g.unwrap_generic(ret_sym.info.elem_type).derive(unwrapped_ret_typ)
}
}
}
}
mut styp := g.styp(ret_typ)
if gen_or && !is_gen_or_and_assign_rhs {

View File

@ -0,0 +1,32 @@
module main
fn decode_primitive[T]() !T {
$if T is int {
return T(1)
} $else $if T is u8 {
return T(10)
} $else $if T is u16 {
return T(100)
}
return error('decode_primitive: not found')
}
fn decode_array[T](_ []T) ![]T {
mut arr := []T{}
arr << decode_primitive[T]()!
return arr
}
fn decode[T]() !T {
$if T is $array {
a := decode_array(T{})!
return a
}
return error('decode: not found')
}
fn test_main() {
assert decode[[]int]()! == [1]
assert decode[[]u8]()! == [u8(10)]
assert decode[[]u16]()! == [u16(100)]
}

View File

@ -316,6 +316,18 @@ pub fn (mut t TypeResolver) resolve_args(cur_fn &ast.FnDecl, func &ast.Fn, mut n
ctyp = cparam_type_sym.info.elem_type
}
comptime_args[k] = ctyp
} else if mut call_arg.expr is ast.StructInit && call_arg.expr.typ.has_flag(.generic) {
mut ctyp := t.resolver.unwrap_generic(call_arg.expr.typ)
param_typ_sym := t.table.sym(param_typ)
cparam_type_sym := t.table.sym(ctyp)
if param_typ_sym.kind == .array && cparam_type_sym.info is ast.Array {
comptime_args[k] = cparam_type_sym.info.elem_type
} else if param_typ_sym.kind == .map && cparam_type_sym.info is ast.Map {
comptime_args[k] = cparam_type_sym.info.key_type
comptime_args[k + 1] = cparam_type_sym.info.value_type
} else {
comptime_args[k] = ctyp
}
}
}
return comptime_args