parser: support `mut:` section in the interface methods, and a mut interface fn modifier (#8092)
parent
1b09954622
commit
72168cd6bc
|
@ -1,4 +1,4 @@
|
|||
vlib/v/checker/tests/function_arg_mutable_err.vv:1:18: error: mutable arguments are only allowed for arrays, maps, structs and pointers
|
||||
vlib/v/checker/tests/function_arg_mutable_err.vv:1:18: error: mutable arguments are only allowed for arrays, interfaces, maps, pointers and structs
|
||||
return values instead: `fn foo(mut n int) {` => `fn foo(n int) int {`
|
||||
1 | fn mod_ptr(mut a int) {
|
||||
| ~~~
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
vlib/v/checker/tests/mut_int.vv:1:14: error: mutable arguments are only allowed for arrays, maps, structs and pointers
|
||||
vlib/v/checker/tests/mut_int.vv:1:14: error: mutable arguments are only allowed for arrays, interfaces, maps, pointers and structs
|
||||
return values instead: `fn foo(mut n int) {` => `fn foo(n int) int {`
|
||||
1 | fn foo(mut x int) {
|
||||
| ~~~
|
||||
|
|
|
@ -700,10 +700,11 @@ fn (mut p Parser) fn_args() ([]table.Param, bool, bool) {
|
|||
|
||||
fn (mut p Parser) check_fn_mutable_arguments(typ table.Type, pos token.Position) {
|
||||
sym := p.table.get_type_symbol(typ)
|
||||
if sym.kind !in [.array, .array_fixed, .struct_, .map, .placeholder, .sum_type] &&
|
||||
if sym.kind !in
|
||||
[.array, .array_fixed, .interface_, .map, .placeholder, .struct_, .sum_type] &&
|
||||
!typ.is_ptr() && !typ.is_pointer()
|
||||
{
|
||||
p.error_with_pos('mutable arguments are only allowed for arrays, maps, structs and pointers\n' +
|
||||
p.error_with_pos('mutable arguments are only allowed for arrays, interfaces, maps, pointers and structs\n' +
|
||||
'return values instead: `fn foo(mut n $sym.name) {` => `fn foo(n $sym.name) $sym.name {`',
|
||||
pos)
|
||||
}
|
||||
|
|
|
@ -462,8 +462,18 @@ fn (mut p Parser) interface_decl() ast.InterfaceDecl {
|
|||
ts.methods = []table.Fn{cap: 20}
|
||||
// Parse methods
|
||||
mut methods := []ast.FnDecl{cap: 20}
|
||||
mut is_mut := false
|
||||
for p.tok.kind != .rcbr && p.tok.kind != .eof {
|
||||
ts = p.table.get_type_symbol(typ) // removing causes memory bug visible by `v -silent test-fmt`
|
||||
if p.tok.kind == .key_mut {
|
||||
if is_mut {
|
||||
p.error_with_pos('redefinition of `mut` section', p.tok.position())
|
||||
return {}
|
||||
}
|
||||
p.next()
|
||||
p.check(.colon)
|
||||
is_mut = true
|
||||
}
|
||||
method_start_pos := p.tok.position()
|
||||
line_nr := p.tok.line_nr
|
||||
name := p.check_name()
|
||||
|
@ -479,6 +489,7 @@ fn (mut p Parser) interface_decl() ast.InterfaceDecl {
|
|||
args2, _, is_variadic := p.fn_args() // TODO merge table.Param and ast.Arg to avoid this
|
||||
mut args := [table.Param{
|
||||
name: 'x'
|
||||
is_mut: is_mut
|
||||
typ: typ
|
||||
is_hidden: true
|
||||
}]
|
||||
|
|
|
@ -7,7 +7,7 @@ mut:
|
|||
breed string
|
||||
}
|
||||
|
||||
fn (mut c Cat) name() string {
|
||||
fn (c &Cat) name() string {
|
||||
if c.breed != '' {
|
||||
assert c.breed == 'Persian'
|
||||
}
|
||||
|
@ -113,7 +113,7 @@ fn test_perform_speak() {
|
|||
*/
|
||||
}
|
||||
|
||||
fn change_animal_breed(a &Animal, new string) {
|
||||
fn change_animal_breed(mut a Animal, new string) {
|
||||
a.set_breed(new)
|
||||
}
|
||||
|
||||
|
@ -122,7 +122,7 @@ fn test_interface_ptr_modification() {
|
|||
breed: 'Persian'
|
||||
}
|
||||
// TODO Should fail and require `mut cat`
|
||||
change_animal_breed(cat, 'Siamese')
|
||||
change_animal_breed(mut cat, 'Siamese')
|
||||
assert cat.breed == 'Siamese'
|
||||
}
|
||||
|
||||
|
@ -218,11 +218,9 @@ fn (mut b Boss) return_speaker2() ?Speaker2 {
|
|||
return b
|
||||
}
|
||||
|
||||
fn return_speaker2(sp Speaker2) Speaker2 {
|
||||
fn return_speaker2(mut sp Speaker2) Speaker2 {
|
||||
s := sp.return_speaker()
|
||||
s2 := sp.return_speaker2() or {
|
||||
return sp
|
||||
}
|
||||
s2 := sp.return_speaker2() or { return *sp }
|
||||
s.speak()
|
||||
s2.speak()
|
||||
return s2
|
||||
|
@ -231,7 +229,7 @@ fn return_speaker2(sp Speaker2) Speaker2 {
|
|||
fn test_interface_returning_interface() {
|
||||
mut b := Boss{'bob'}
|
||||
assert b.name == 'bob'
|
||||
s2 := return_speaker2(b)
|
||||
s2 := return_speaker2(mut b)
|
||||
if s2 is Boss {
|
||||
assert s2.name == 'boss'
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue