mirror of
https://github.com/vlang/v.git
synced 2025-09-13 22:42:26 +03:00
checker: disallow structs with @[params]
attribute as mutable function parameters (#21206)
This commit is contained in:
parent
206441c9df
commit
f0abc452fa
4 changed files with 38 additions and 16 deletions
|
@ -254,6 +254,10 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
|
||||||
c.error('generic struct `${pure_sym_name}` in fn declaration must specify the generic type names, e.g. ${pure_sym_name}[T]',
|
c.error('generic struct `${pure_sym_name}` in fn declaration must specify the generic type names, e.g. ${pure_sym_name}[T]',
|
||||||
param.type_pos)
|
param.type_pos)
|
||||||
}
|
}
|
||||||
|
if param.is_mut && arg_typ_sym.info.attrs.any(it.name == 'params') {
|
||||||
|
c.error('declaring a mutable parameter that accepts a struct with the `@[params]` attribute is not allowed',
|
||||||
|
param.type_pos)
|
||||||
|
}
|
||||||
} else if arg_typ_sym.info is ast.Interface {
|
} else if arg_typ_sym.info is ast.Interface {
|
||||||
if arg_typ_sym.info.generic_types.len > 0 && !param.typ.has_flag(.generic)
|
if arg_typ_sym.info.generic_types.len > 0 && !param.typ.has_flag(.generic)
|
||||||
&& arg_typ_sym.info.concrete_types.len == 0 {
|
&& arg_typ_sym.info.concrete_types.len == 0 {
|
||||||
|
@ -1278,8 +1282,11 @@ fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool) ast.
|
||||||
} else {
|
} else {
|
||||||
if param.is_mut {
|
if param.is_mut {
|
||||||
tok := param.specifier()
|
tok := param.specifier()
|
||||||
c.error('function `${node.name}` parameter `${param.name}` is `${tok}`, so use `${tok} ${call_arg.expr}` instead',
|
param_sym := c.table.sym(param.typ)
|
||||||
call_arg.expr.pos())
|
if !(param_sym.info is ast.Struct && param_sym.info.attrs.any(it.name == 'params')) {
|
||||||
|
c.error('function `${node.name}` parameter `${param.name}` is `${tok}`, so use `${tok} ${call_arg.expr}` instead',
|
||||||
|
call_arg.expr.pos())
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
c.fail_if_unreadable(call_arg.expr, arg_typ, 'argument')
|
c.fail_if_unreadable(call_arg.expr, arg_typ, 'argument')
|
||||||
}
|
}
|
||||||
|
|
7
vlib/v/checker/tests/mut_parms_struct_param_err.out
Normal file
7
vlib/v/checker/tests/mut_parms_struct_param_err.out
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
vlib/v/checker/tests/mut_parms_struct_param_err.vv:8:17: error: declaring a mutable parameter that accepts a struct with the `@[params]` attribute is not allowed
|
||||||
|
6 | }
|
||||||
|
7 |
|
||||||
|
8 | fn foo(mut opts Params) bool {
|
||||||
|
| ~~~~~~
|
||||||
|
9 | return opts.a
|
||||||
|
10 | }
|
12
vlib/v/checker/tests/mut_parms_struct_param_err.vv
Normal file
12
vlib/v/checker/tests/mut_parms_struct_param_err.vv
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
@[params]
|
||||||
|
struct Params {
|
||||||
|
mut:
|
||||||
|
a bool
|
||||||
|
x int
|
||||||
|
}
|
||||||
|
|
||||||
|
fn foo(mut opts Params) bool {
|
||||||
|
return opts.a
|
||||||
|
}
|
||||||
|
|
||||||
|
foo(a: true)
|
|
@ -25,7 +25,8 @@ struct Lol {
|
||||||
|
|
||||||
struct User {
|
struct User {
|
||||||
name string
|
name string
|
||||||
age int
|
mut:
|
||||||
|
age int
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Foo {
|
struct Foo {
|
||||||
|
@ -257,14 +258,12 @@ fn bar_config(c Config, def int) {
|
||||||
assert c.def == def
|
assert c.def == def
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mut_bar_config(mut c Config, def int) &Config {
|
|
||||||
c.n = c.def
|
|
||||||
assert c.n == def
|
|
||||||
return unsafe { c }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn foo_user(u User) {}
|
fn foo_user(u User) {}
|
||||||
|
|
||||||
|
fn foo_mut_user(mut u User) {
|
||||||
|
u.age++
|
||||||
|
}
|
||||||
|
|
||||||
fn test_struct_literal_args() {
|
fn test_struct_literal_args() {
|
||||||
foo_config(20,
|
foo_config(20,
|
||||||
n: 10
|
n: 10
|
||||||
|
@ -277,17 +276,14 @@ fn test_struct_literal_args() {
|
||||||
bar_config(Config{}, 10)
|
bar_config(Config{}, 10)
|
||||||
bar_config(Config{ def: 4 }, 4)
|
bar_config(Config{ def: 4 }, 4)
|
||||||
|
|
||||||
mut c_ := Config{
|
|
||||||
def: 10
|
|
||||||
}
|
|
||||||
c := mut_bar_config(mut c_, 10)
|
|
||||||
assert c.n == 10
|
|
||||||
assert c.def == 10
|
|
||||||
|
|
||||||
foo_user(name: 'Peter')
|
foo_user(name: 'Peter')
|
||||||
foo_user(name: 'Peter')
|
foo_user(name: 'Peter')
|
||||||
foo_user(age: 7)
|
foo_user(age: 7)
|
||||||
foo_user(name: 'Stew', age: 50)
|
foo_user(name: 'Stew', age: 50)
|
||||||
|
|
||||||
|
mut user := User{'Stew', 50}
|
||||||
|
foo_mut_user(mut user)
|
||||||
|
assert user.age == 51
|
||||||
}
|
}
|
||||||
|
|
||||||
struct City {
|
struct City {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue