mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
parent
9c2bd24b4f
commit
2963425995
@ -68,6 +68,7 @@ mut:
|
||||
cur_orm_ts table.TypeSymbol
|
||||
error_details []string
|
||||
for_in_mut_val_name string
|
||||
fn_mut_arg_names []string
|
||||
vmod_file_content string // needed for @VMOD_FILE, contents of the file, *NOT its path**
|
||||
vweb_gen_types []table.Type // vweb route checks
|
||||
prevent_sum_type_unwrapping_once bool // needed for assign new values to sum type, stopping unwrapping then
|
||||
@ -2579,7 +2580,7 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
|
||||
assign_stmt.pos)
|
||||
}
|
||||
left_is_ptr := left_type.is_ptr() || left_sym.is_pointer()
|
||||
if left_is_ptr && c.for_in_mut_val_name != left.str() {
|
||||
if left_is_ptr && c.for_in_mut_val_name != left.str() && left.str() !in c.fn_mut_arg_names {
|
||||
if !c.inside_unsafe && assign_stmt.op !in [.assign, .decl_assign] {
|
||||
// ptr op=
|
||||
c.warn('pointer arithmetic is only allowed in `unsafe` blocks', assign_stmt.pos)
|
||||
@ -5512,8 +5513,17 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
|
||||
}
|
||||
}
|
||||
}
|
||||
for param in node.params {
|
||||
if param.is_mut {
|
||||
c.fn_mut_arg_names << param.name
|
||||
}
|
||||
}
|
||||
c.fn_scope = node.scope
|
||||
c.stmts(node.stmts)
|
||||
|
||||
if c.fn_mut_arg_names.len > 0 {
|
||||
c.fn_mut_arg_names.clear()
|
||||
}
|
||||
returns := c.returns || has_top_return(node.stmts)
|
||||
if node.language == .v && !node.no_body && node.return_type != table.void_type && !returns
|
||||
&& node.name !in ['panic', 'exit'] {
|
||||
|
@ -118,6 +118,7 @@ mut:
|
||||
// strs_to_free []string // strings.Builder
|
||||
inside_call bool
|
||||
for_in_mut_val_name string
|
||||
fn_mut_arg_names []string
|
||||
has_main bool
|
||||
inside_const bool
|
||||
comp_for_method string // $for method in T.methods {}
|
||||
@ -1990,7 +1991,7 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
|
||||
} else {
|
||||
g.out.go_back_to(pos)
|
||||
is_var_mut := !is_decl && left is ast.Ident
|
||||
&& g.for_in_mut_val_name == (left as ast.Ident).name
|
||||
&& (g.for_in_mut_val_name == (left as ast.Ident).name || (left as ast.Ident).name in g.fn_mut_arg_names)
|
||||
addr := if is_var_mut { '' } else { '&' }
|
||||
g.writeln('')
|
||||
g.write('memcpy($addr')
|
||||
@ -2061,8 +2062,8 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
|
||||
g.prevent_sum_type_unwrapping_once = true
|
||||
}
|
||||
if !is_fixed_array_copy || is_decl {
|
||||
if !is_decl && left is ast.Ident
|
||||
&& g.for_in_mut_val_name == (left as ast.Ident).name {
|
||||
if !is_decl && var_type != table.string_type_idx && left is ast.Ident
|
||||
&& (g.for_in_mut_val_name == (left as ast.Ident).name || (left as ast.Ident).name in g.fn_mut_arg_names) {
|
||||
g.write('*')
|
||||
}
|
||||
g.expr(left)
|
||||
|
@ -126,6 +126,11 @@ fn (mut g Gen) gen_fn_decl(it ast.FnDecl, skip bool) {
|
||||
g.definitions.write(fn_header)
|
||||
g.write(fn_header)
|
||||
}
|
||||
for param in it.params {
|
||||
if param.is_mut {
|
||||
g.fn_mut_arg_names << param.name
|
||||
}
|
||||
}
|
||||
arg_start_pos := g.out.len
|
||||
fargs, fargtypes := g.fn_args(it.params, it.is_variadic)
|
||||
arg_str := g.out.after(arg_start_pos)
|
||||
@ -170,7 +175,11 @@ fn (mut g Gen) gen_fn_decl(it ast.FnDecl, skip bool) {
|
||||
prev_defer_stmts := g.defer_stmts
|
||||
g.defer_stmts = []
|
||||
g.stmts(it.stmts)
|
||||
//
|
||||
// clear g.fn_mut_arg_names
|
||||
if g.fn_mut_arg_names.len > 0 {
|
||||
g.fn_mut_arg_names.clear()
|
||||
}
|
||||
|
||||
if it.return_type == table.void_type {
|
||||
g.write_defer_stmts_when_needed()
|
||||
}
|
||||
@ -185,7 +194,7 @@ fn (mut g Gen) gen_fn_decl(it ast.FnDecl, skip bool) {
|
||||
if default_expr == '{0}' {
|
||||
if it.return_type.idx() == 1 && it.return_type.has_flag(.optional) {
|
||||
// The default return for anonymous functions that return `?,
|
||||
// should have .ok = true set, otherwise calling them with
|
||||
// should have .ok = true set, otherwise calling them with
|
||||
// optfn() or { panic(err) } will cause a panic:
|
||||
g.writeln('\treturn (Option_void){.ok = true};')
|
||||
} else {
|
||||
|
@ -343,14 +343,16 @@ fn (mut g Gen) gen_expr_to_string(expr ast.Expr, etype table.Type) {
|
||||
} else if sym_has_str_method
|
||||
|| sym.kind in [.array, .array_fixed, .map, .struct_, .multi_return, .sum_type, .interface_] {
|
||||
is_ptr := typ.is_ptr()
|
||||
is_var_mut := expr is ast.Ident
|
||||
&& ((expr as ast.Ident).name == g.for_in_mut_val_name || (expr as ast.Ident).name in g.fn_mut_arg_names)
|
||||
str_fn_name := g.gen_str_for_type(typ)
|
||||
if is_ptr {
|
||||
if is_ptr && !is_var_mut {
|
||||
g.write('_STR("&%.*s\\000", 2, ')
|
||||
}
|
||||
g.write('${str_fn_name}(')
|
||||
if str_method_expects_ptr && !is_ptr {
|
||||
g.write('&')
|
||||
} else if !str_method_expects_ptr && is_ptr {
|
||||
} else if (!str_method_expects_ptr && is_ptr) || is_var_mut {
|
||||
g.write('*')
|
||||
}
|
||||
if expr is ast.ArrayInit {
|
||||
@ -361,7 +363,7 @@ fn (mut g Gen) gen_expr_to_string(expr ast.Expr, etype table.Type) {
|
||||
}
|
||||
g.expr(expr)
|
||||
g.write(')')
|
||||
if is_ptr {
|
||||
if is_ptr && !is_var_mut {
|
||||
g.write(')')
|
||||
}
|
||||
} else {
|
||||
|
23
vlib/v/tests/fn_mut_args_test.v
Normal file
23
vlib/v/tests/fn_mut_args_test.v
Normal file
@ -0,0 +1,23 @@
|
||||
fn func(mut a []int) {
|
||||
a = [1, 2, 3, 4]
|
||||
println('inside fn: $a')
|
||||
assert '$a' == '[1, 2, 3, 4]'
|
||||
}
|
||||
|
||||
fn test_fn_mut_args_of_array() {
|
||||
mut a := [1, 2, 3]
|
||||
func(mut a)
|
||||
println('inside main: $a')
|
||||
assert '$a' == '[1, 2, 3, 4]'
|
||||
}
|
||||
|
||||
fn init_map(mut n map[string]int) {
|
||||
n = {'one': 1}
|
||||
}
|
||||
|
||||
fn test_fn_mut_args_of_map() {
|
||||
mut m := map[string]int{}
|
||||
init_map(mut m)
|
||||
println(m)
|
||||
assert m == {'one': 1}
|
||||
}
|
Loading…
Reference in New Issue
Block a user