Skip to content
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

Compiler changed my var to const when using an anonymous struct. #21388

Closed
taylorh140 opened this issue Sep 12, 2024 · 3 comments
Closed

Compiler changed my var to const when using an anonymous struct. #21388

taylorh140 opened this issue Sep 12, 2024 · 3 comments
Labels
question No questions on the issue tracker, please.

Comments

@taylorh140
Copy link

Zig Version

0.13.0

Steps to Reproduce and Observed Behavior

So i was debugging a variable in my code, because it was supposed to be incrementing. it wasn't.

I reduced the problem into this code which compiles: https://godbolt.org/z/886c9xWrn

const std = @import("std");

const Test_t = struct {
    a:usize = 0,
    b:usize,
};

pub var TestA = .{.b = 100};  //called @__anon_1427

export fn main() void{
    foo(&TestA);
}

fn foo(tst:*volatile Test_t) callconv(.C) void {
    tst.a+=1;
}

I thought this would add 1 to the TestA.a but it cant. because its constant!
It can be fixed by expliclty setting TestA's type:

const std = @import("std");

const Test_t = struct {
    a:usize = 0,
    b:usize,
};

pub var TestA = Test_t{.b = 100};  //called @example.TestA

export fn main() void{
    foo(&TestA);
}

fn foo(tst:*volatile Test_t) callconv(.C) void {
    tst.a+=1;
}

Looking at the LLVM IR:

before:
@__anon_1427 = internal unnamed_addr constant %example.Test_t { i64 0, i64 100 }, align 8

after:
@example.TestA = internal unnamed_addr global %example.Test_t { i64 0, i64 100 }, align 8

Expected Behavior

I expected the variables to be placed into volatile memory like the .data section. However, in my case it was placed in .rodata and it kept my counter from counting.

@taylorh140 taylorh140 added the bug Observed behavior contradicts documented or intended behavior label Sep 12, 2024
@ikskuh
Copy link
Contributor

ikskuh commented Sep 12, 2024

TestA has an anonymous struct type that looks like this:

struct { comptime b: comptime_int =100 }
``|
when you take a pointer, it implicitly converts into a temporary of `Test_t`.

What you'e written is basically 
```zig
export fn main() void{
    foo(&.{ .b = 100 });
}

If you want your global to have an explicit type, the solution is to specify it like you in your second code or like this:

pub var TestA: Test_t = .{.b = 100};

@Vexu Vexu added question No questions on the issue tracker, please. and removed bug Observed behavior contradicts documented or intended behavior labels Sep 12, 2024
@Vexu Vexu closed this as not planned Won't fix, can't repro, duplicate, stale Sep 12, 2024
@kibels
Copy link

kibels commented Sep 12, 2024

If you were to write

export fn main() void{
   var bar = .{ .b = 100 };
   foo(&bar);
 }

you might expect the struct even if it's anonymous to be mutable. Should it at least be a compiler error that a const was passed to a function mutating it without a @constCast? It is a segfault at runtime from trying to mutate .rodata instead.

Edit: Apologies, I didn't realize the issue was closed because it is solved by an accepted proposal and not because the behavior is intended.

@mlugg
Copy link
Member

mlugg commented Sep 12, 2024

The unexpectedly-allowed coercion here is solved by the accepted (but not yet implemented) proposal #16865.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question No questions on the issue tracker, please.
Projects
None yet
Development

No branches or pull requests

5 participants