vlang / v

Simple, fast, safe, compiled language for developing maintainable software. Compiles itself in <1s with zero library dependencies. Supports automatic C => V translation. https://vlang.io
MIT License
35.82k stars 2.17k forks source link

Whether the assignment behavior to function parameters should be consistent with the assignment behavior to variables? #15419

Open Silentdoer opened 2 years ago

Silentdoer commented 2 years ago

please see Question 1 and Question 2 and FLAG

import strconv

interface Speaker {
// Question 1: By the way, does this mut have any use for the speak method? 
// Because regardless of whether there is mut in the interface definition, the parameters that implement speak can have mut
mut:
    speak()
}

struct Foo {
mut:
    a int
}

fn (mut foo2 Foo) speak() {
    strconv.v_printf('foo2:%p\n', foo2)
    foo2.a = 9
}

fn main() {
    mut foo := Foo{3}
    // printed 0x14efe5c
    strconv.v_printf('%p\n', foo)

    mut foo1 := foo
    // FLAG, printed 0x14efe1c, foo and foo1 point to different address spaces, So foo copies a copy of the data to foo1
    strconv.v_printf('%p\n', foo1)

    // Question 2: printed foo2:0x14efe5c, foo and foo2 point to the same memory space
    //, So why doesn't foo make a copy of the data here as well as above? Is this inconsistent?
        // The value I expect is that the address printed here is not the same as that of foo, such as prints foo2:0x14efd90
    foo.speak()
}

V version:0.3.0 6a728e1 OS:Windows 10

What did you do? Check the consistency of variable assignments and function parameter assignments as deep or shallow copies

What did you expect to see? prints: 0x14efe5c 0x14efe1c foo2:0x14efe3c // just not equals 0x14efe5c

What did you see instead? 0x14efe5c 0x14efe1c foo2:0x14efe5c

Remove the output result of implementing mut on the speak method parameter:

import strconv

interface Speaker {
// Question 1: By the way, does this mut have any use for the speak method? 
// Because regardless of whether there is mut in the interface definition, the parameters that implement speak can have mut
mut:
    speak()
}

struct Foo {
mut:
    a int
}

// FLAG, Note that I removed the mut
fn (foo2 Foo) speak() {
    strconv.v_printf('foo2:%p\n', foo2)
}

fn main() {
    mut foo := Foo{3}
    // printed 0x14efe5c
    strconv.v_printf('%p\n', foo)

    mut foo1 := foo
    // FLAG, printed 0x14efe1c, foo and foo1 point to different address spaces, So foo copies a copy of the data to foo1
    strconv.v_printf('%p\n', foo1)

    // FLAG, no mut, printed 0x14efddc, foo and foo3 point to different addresses, which is a copy behavior.
    // In this case, the direct assignment of variables(foo3) and the direct assignment of method parameters(foo2) are consistent
    //, both are copy behaviors
    foo3 := foo
    strconv.v_printf('%p\n', foo3)

    // FLAG, printed foo2:0x14efd50, I remove the mut on the parameters of the implement speak method, assigning values to function parameters is the same as assigning values to variables, it's deep copy
    foo.speak()
}
Silentdoer commented 2 years ago

ahh,, no one can anwser?

bogen85 commented 2 years ago

As with #15368 please use the BUG ISSUE TEMPLATE on the first post of an issue.

Silentdoer commented 2 years ago

hi, i update the comment use BUG ISSUE TEMPLATE, by the way what is the usefulness of the mut keyword for interface methods?

interface Speaker {
// Question 1: By the way, does this mut have any use for the speak method? 
// Because regardless of whether there is mut in the interface definition, the parameters that implement speak can have mut
mut:
    speak()
}