Skip to content

Is possible to changed a function argument that was passed by value mid function by changing the original variable #21485

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
lassade opened this issue Sep 21, 2024 · 3 comments
Labels
bug Observed behavior contradicts documented or intended behavior

Comments

@lassade
Copy link

lassade commented Sep 21, 2024

Zig Version

0.14.0-dev.1298+d9e8671d9

Steps to Reproduce and Observed Behavior

Minimal test repo code

const std = @import("std");

const Node = extern struct {
    id: u32 = 0,
    kind: u16 = 0,
    ver: u16 = 0,
};

const Context = struct {
    visitor: *Vistor,
};

const Vistor = struct {
    selected: Node = .{},
};

fn visit(target: Node, context: anytype) void {
    if (target.id == 0 or target.kind == 0 or target.ver == 0) {
        @panic("`target` is not invalid"); // will never happen
    }

    context.visitor.selected = .{}; // invalidate selected

    if (target.id == 0 or target.kind == 0 or target.ver == 0) {
        @panic("`target` changed it's value, but I thought it was passed by value not by ref!");
    }

    // can't continue because the target value changed!
}

test {
    var visitor = Vistor{};
    visitor.selected = .{ .id = 8, .kind = 1, .ver = 9 }; // starts with a valid target

    var context = Context{ .visitor = &visitor }; // create a context

    const temp = visitor.selected; // copy selected into a temp variable just to be sure
    visit(temp, &context);
}

Expected Behavior

I wasn't expecting the value of target to change mid function because I changed other variable. The only explanation is that zig is not passing it by value!

@lassade lassade added the bug Observed behavior contradicts documented or intended behavior label Sep 21, 2024
@squeek502
Copy link
Collaborator

Related / possible duplicate: #5973

@rohlem
Copy link
Contributor

rohlem commented Sep 22, 2024

The only explanation is that zig is not passing it by value!

You are correct, and this is somewhat documented: https://ziglang.org/documentation/master/#Pass-by-value-Parameters
A workaround in status-quo is to make an explicit stack copy const x = y; and then use that copy instead.

The current documentation is missing details on what is / isn't allowed to happen here,
and the current implementation is missing a safety check in safe build modes (#2301).

@lassade
Copy link
Author

lassade commented Sep 22, 2024

The stack copy doesn't work, unless I force it some how to be var instead of const, but not sure if this a reliable workaround in other build modes

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Observed behavior contradicts documented or intended behavior
Projects
None yet
Development

No branches or pull requests

3 participants