cgen: fix default T{} when T is ref type + dereferencing issue when comparing int alias to int (fix #22795) (#22807)

This commit is contained in:
Felipe Pena 2024-11-11 07:08:34 -03:00 committed by GitHub
parent fdc49dc51a
commit 2e353d209d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 37 additions and 9 deletions

View File

@ -187,7 +187,7 @@ fn (mut g Gen) infix_expr_eq_op(node ast.InfixExpr) {
.alias {
// optimize simple eq/ne operation on numbers
if left.unaliased_sym.is_int() {
if left.typ.is_ptr() {
if left.typ.is_ptr() && node.left.is_auto_deref_var() && !right.typ.is_pointer() {
g.write('*'.repeat(left.typ.nr_muls()))
}
g.expr(node.left)

View File

@ -64,6 +64,8 @@ fn (mut g Gen) gen_expr_to_string(expr ast.Expr, etype ast.Type) {
if is_shared {
typ = typ.clear_flag(.shared_f).set_nr_muls(0)
}
// original is_ptr for the typ (aliased type could overwrite it)
is_ptr := typ.is_ptr()
mut sym := g.table.sym(typ)
// when type is non-option alias and doesn't has `str()`, print the aliased value
if mut sym.info is ast.Alias && !sym.has_method('str') && !etype.has_flag(.option) {
@ -113,7 +115,6 @@ fn (mut g Gen) gen_expr_to_string(expr ast.Expr, etype ast.Type) {
|| sym.kind in [.array, .array_fixed, .map, .struct, .multi_return, .sum_type, .interface] {
unwrap_option := expr is ast.Ident && expr.or_expr.kind == .propagate_option
exp_typ := if unwrap_option { typ.clear_flag(.option) } else { typ }
is_ptr := exp_typ.is_ptr()
is_dump_expr := expr is ast.DumpExpr
is_var_mut := expr.is_auto_deref_var()
str_fn_name := g.get_str_fn(exp_typ)
@ -170,7 +171,7 @@ fn (mut g Gen) gen_expr_to_string(expr ast.Expr, etype ast.Type) {
if sym.is_c_struct() {
g.write(c_struct_ptr(sym, typ, str_method_expects_ptr))
} else {
g.write('*'.repeat(typ.nr_muls()))
g.write('*'.repeat(etype.nr_muls()))
}
} else if sym.is_c_struct() {
g.write(c_struct_ptr(sym, typ, str_method_expects_ptr))
@ -201,7 +202,6 @@ fn (mut g Gen) gen_expr_to_string(expr ast.Expr, etype ast.Type) {
g.write('}}}))')
}
} else {
is_ptr := typ.is_ptr()
is_var_mut := expr.is_auto_deref_var()
str_fn_name := g.get_str_fn(typ)
g.write('${str_fn_name}(')

View File

@ -37,9 +37,16 @@ fn (mut g Gen) struct_init(node ast.StructInit) {
g.go_back(3)
return
}
mut sym := g.table.final_sym(g.unwrap_generic(node.typ))
unwrapped_typ := g.unwrap_generic(node.typ)
mut sym := g.table.final_sym(unwrapped_typ)
if sym.kind == .sum_type {
g.write(g.type_default_sumtype(g.unwrap_generic(node.typ), sym))
if node.typ.has_flag(.generic) && unwrapped_typ.is_ptr() {
g.write('&(')
g.write(g.type_default_sumtype(unwrapped_typ.set_nr_muls(0), sym))
g.write(')')
} else {
g.write(g.type_default_sumtype(unwrapped_typ, sym))
}
return
}
is_amp := g.is_amp
@ -120,7 +127,7 @@ fn (mut g Gen) struct_init(node ast.StructInit) {
} else {
// alias to pointer type
if (g.table.sym(node.typ).kind == .alias && g.table.unaliased_type(node.typ).is_ptr())
|| (node.typ.has_flag(.generic) && g.unwrap_generic(node.typ).is_ptr()) {
|| (!sym.is_int() && node.typ.has_flag(.generic) && unwrapped_typ.is_ptr()) {
g.write('&')
}
if is_array || const_msvc_init {
@ -349,10 +356,10 @@ fn (mut g Gen) struct_init(node ast.StructInit) {
g.fixed_array_init(ast.ArrayInit{
pos: node.pos
is_fixed: true
typ: g.unwrap_generic(node.typ)
typ: unwrapped_typ
exprs: [ast.empty_expr]
elem_type: arr_info.elem_type
}, g.unwrap(g.unwrap_generic(node.typ)), '', g.is_amp)
}, g.unwrap(unwrapped_typ), '', g.is_amp)
initialized = true
}
if is_multiline {

View File

@ -0,0 +1,21 @@
struct Struct {}
type StructAlias = Struct
type SumType = Struct | int
type AliasInt = int
fn (d Struct) a[T]() T {
return T{}
}
fn test_main() {
s := Struct{}
assert s.a[&int]() == 0
assert s.a[&int]() == unsafe { nil }
assert s.a[&Struct]() == Struct{}
assert s.a[&SumType]() is Struct
assert s.a[&StructAlias]() == StructAlias{}
assert s.a[&AliasInt]() == AliasInt(0)
}