autofree: fix array re-assignment with struct fields
parent
76ed8e3750
commit
5180013aef
|
@ -1519,9 +1519,11 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
|
||||||
ast.IfExpr { return_type = right_expr.typ }
|
ast.IfExpr { return_type = right_expr.typ }
|
||||||
else {}
|
else {}
|
||||||
}
|
}
|
||||||
// Free the old value assigned to this string var (only if it's `str = [new value]`)
|
// Free the old value assigned to this string var (only if it's `str = [new value]`
|
||||||
|
// or `x.str = [new value]` )
|
||||||
mut af := g.pref.autofree && !g.is_builtin_mod && assign_stmt.op == .assign && assign_stmt.left_types.len ==
|
mut af := g.pref.autofree && !g.is_builtin_mod && assign_stmt.op == .assign && assign_stmt.left_types.len ==
|
||||||
1 && assign_stmt.left[0] is ast.Ident
|
1 &&
|
||||||
|
(assign_stmt.left[0] is ast.Ident || assign_stmt.left[0] is ast.SelectorExpr)
|
||||||
// assign_stmt.left_types[0] in [table.string_type, table.array_type] &&
|
// assign_stmt.left_types[0] in [table.string_type, table.array_type] &&
|
||||||
mut sref_name := ''
|
mut sref_name := ''
|
||||||
mut type_to_free := ''
|
mut type_to_free := ''
|
||||||
|
@ -1530,18 +1532,19 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
|
||||||
first_left_sym := g.table.get_type_symbol(assign_stmt.left_types[0])
|
first_left_sym := g.table.get_type_symbol(assign_stmt.left_types[0])
|
||||||
if first_left_type == table.string_type || first_left_sym.kind == .array {
|
if first_left_type == table.string_type || first_left_sym.kind == .array {
|
||||||
type_to_free = if first_left_type == table.string_type { 'string' } else { 'array' }
|
type_to_free = if first_left_type == table.string_type { 'string' } else { 'array' }
|
||||||
ident := assign_stmt.left[0] as ast.Ident
|
mut ok := true
|
||||||
if ident.name != '_' {
|
left0 := assign_stmt.left[0]
|
||||||
/*
|
if left0 is ast.Ident {
|
||||||
g.write('string_free(&')
|
if left0.name == '_' {
|
||||||
g.expr(assign_stmt.left[0])
|
ok = false
|
||||||
g.writeln('); // free str on re-assignment')
|
}
|
||||||
*/
|
}
|
||||||
|
if ok {
|
||||||
sref_name = '_sref$assign_stmt.pos.pos'
|
sref_name = '_sref$assign_stmt.pos.pos'
|
||||||
g.write('$type_to_free $sref_name = (') // TODO we are copying the entire string here, optimize
|
g.write('$type_to_free $sref_name = (') // TODO we are copying the entire string here, optimize
|
||||||
// we can't just do `.str` since we need the extra data from the string struct
|
// we can't just do `.str` since we need the extra data from the string struct
|
||||||
// doing `&string` is also not an option since the stack memory with the data will be overwritten
|
// doing `&string` is also not an option since the stack memory with the data will be overwritten
|
||||||
g.expr(assign_stmt.left[0])
|
g.expr(left0) // assign_stmt.left[0])
|
||||||
g.writeln('); // free $type_to_free on re-assignment2')
|
g.writeln('); // free $type_to_free on re-assignment2')
|
||||||
defer {
|
defer {
|
||||||
if af {
|
if af {
|
||||||
|
|
|
@ -106,10 +106,20 @@ fn reassign_str() {
|
||||||
s = s + '!' // old s ref must be copied and freed after the assignment, since s is still used in the right expr
|
s = s + '!' // old s ref must be copied and freed after the assignment, since s is still used in the right expr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Foo2 {
|
||||||
|
mut:
|
||||||
|
nums []int
|
||||||
|
}
|
||||||
|
|
||||||
fn reassign_arr() {
|
fn reassign_arr() {
|
||||||
mut x := [1, 2, 3]
|
mut x := [1, 2, 3]
|
||||||
// x must be freed before the re-assignment
|
// x must be freed before the re-assignment
|
||||||
x = [4, 5, 6]
|
x = [4, 5, 6]
|
||||||
|
mut foo := Foo2{[10, 20, 30]}
|
||||||
|
foo.nums = [40, 50, 60] // same with struct fields
|
||||||
|
foo.nums = [70, 80, 90]
|
||||||
|
// TODO remove this once structs are freed automatically
|
||||||
|
foo.nums.free()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn match_expr() string {
|
fn match_expr() string {
|
||||||
|
@ -145,9 +155,7 @@ fn optional_str() {
|
||||||
// test assigning an optional to an existing var
|
// test assigning an optional to an existing var
|
||||||
mut p := 0
|
mut p := 0
|
||||||
for {
|
for {
|
||||||
p = opt('query:$q') or {
|
p = opt('query:$q') or { break }
|
||||||
break
|
|
||||||
}
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -161,9 +169,7 @@ fn return_error_with_freed_expr() ?string {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn optional_return() {
|
fn optional_return() {
|
||||||
return_error_with_freed_expr() or {
|
return_error_with_freed_expr() or { return }
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_string(s string) bool {
|
fn handle_string(s string) bool {
|
||||||
|
|
Loading…
Reference in New Issue