parser: allow passing `mut a AliasOfPointerType`

pull/9476/head
Delyan Angelov 2021-03-26 13:38:16 +02:00
parent 52a14e8422
commit 87494fad1d
No known key found for this signature in database
GPG Key ID: 66886C0F12D595ED
2 changed files with 49 additions and 6 deletions

View File

@ -824,13 +824,21 @@ 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, .interface_, .map, .placeholder, .struct_, .sum_type]
&& !typ.is_ptr() && !typ.is_pointer() {
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)
if sym.kind in [.array, .array_fixed, .interface_, .map, .placeholder, .struct_, .sum_type] {
return
}
if typ.is_ptr() || typ.is_pointer() {
return
}
if sym.kind == .alias {
atyp := (sym.info as table.Alias).parent_type
p.check_fn_mutable_arguments(atyp, pos)
return
}
p.error_with_pos(
'mutable arguments are only allowed for arrays, interfaces, maps, pointers, structs or their aliases\n' +
'return values instead: `fn foo(mut n $sym.name) {` => `fn foo(n $sym.name) $sym.name {`',
pos)
}
fn (mut p Parser) check_fn_shared_arguments(typ table.Type, pos token.Position) {

View File

@ -37,3 +37,38 @@ fn test_alias_of_pointer_types() {
assert sizeof(PPZZInt) == sizeof(voidptr)
assert sizeof(PPZZMyStructInt) == sizeof(voidptr)
}
fn test_calling_a_function_expecting_a_mut_alias() {
eprintln('------------------------')
mut s := &MyStructInt{456}
mut ps := PZZMyStructInt(s)
dump(voidptr(s))
dump(voidptr(ps))
eprintln('------------------------')
dump(&MyStructInt(ps))
res := mut_alias(mut ps)
dump(&MyStructInt(ps))
// the alias `ps` is now changed and points to another object
assert res == 123
assert s.x == 456 // should remain the same
assert (&MyStructInt(ps)).x == 789
assert u64(voidptr(s)) != u64(voidptr(ps))
dump(voidptr(s))
dump(voidptr(ps))
eprintln('------------------------')
}
// do not delete this, its generated code eases comparisons with mut_alias
fn mut_struct(mut p ZZMyStructInt) int {
dump(ptr_str(voidptr(p)))
return 999
}
fn mut_alias(mut ps PZZMyStructInt) int {
// dump(ptr_str(voidptr(ps)))
another := &MyStructInt{789}
// dump(ptr_str(voidptr(another)))
ps = PZZMyStructInt(another)
// dump(ptr_str(voidptr(ps)))
return 123
}