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

?struct{ptr: *anyopaque} is 16 bytes instead of 8 bytes #15808

Closed
Jarred-Sumner opened this issue May 21, 2023 · 6 comments
Closed

?struct{ptr: *anyopaque} is 16 bytes instead of 8 bytes #15808

Jarred-Sumner opened this issue May 21, 2023 · 6 comments
Labels
bug Observed behavior contradicts documented or intended behavior

Comments

@Jarred-Sumner
Copy link
Contributor

Zig Version

0.11.0-dev.2777+b95cdf0ae

Steps to Reproduce and Observed Behavior

zig test repro.zig
pub const Foo = struct {
    bar: *anyopaque,
};

test {
    @compileLog(@import("std").fmt.comptimePrint("Foo size {d}", .{@sizeOf(?Foo)}));
}
/Users/jarred/Desktop/repro.zig:6:5: error: found compile log statement
    @compileLog(@import("std").fmt.comptimePrint("Foo size {d}", .{@sizeOf(?Foo)}));
    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Compile Log Output:
@as(*const [11:0]u8, "Foo size 16")

Expected Behavior

The type ?*anyopaque should be the same size as the type ?struct {ptr: *anyopaque} because there are no other fields. Maybe this optimization could be done in ZIR?

@Jarred-Sumner Jarred-Sumner added the bug Observed behavior contradicts documented or intended behavior label May 21, 2023
@rohlem
Copy link
Contributor

rohlem commented May 21, 2023

duplicate or maybe subtask of #104

@Jarred-Sumner
Copy link
Contributor Author

Jarred-Sumner commented May 21, 2023

It's a special case - there already is code for making optional pointers the same size as regular pointers. Could that be reused here for structs with a single field as a pointer?

@leecannon
Copy link
Contributor

leecannon commented May 21, 2023

But null is not a valid value of *anyopaque so the flag for the optional must be stored seperately from the pointer as zig cannot use the zero value.

Even an optimization on ?struct {ptr: ?*anyopaque} to be the same size as ?*anyopaque would be invalid as there would only be enough space to store one null value but there are two seperate optionals and the user could branch on either optional being null.

@Jarred-Sumner
Copy link
Contributor Author

But null is not a valid value of *anyopaque so the flag for the optional must be stored seperately from the pointer as zig cannot use the zero value.

Even an optimization on ?struct {ptr: ?*anyopaque} to be the same size as ?*anyopaque would be invalid as there would only be enough space to store one null value but there are two seperate optionals and the user could branch on either optional being null.

Yes that is correct. I'm not suggesting that this optimization would apply to ?struct {ptr: ?*anyopaque}. I'm suggesting it would apply only to ?struct {ptr: *anyopaque} - where the struct has a single field and that field is a non-optional pointer. It would functionally be equivalent to ?*anyopaque.

So basically:

// This
const Foo = ?struct { ptr: *anyopaque };

// Becomes the eqvuivalent of
const FooPtr =  ?*anyopaque;

@mlugg
Copy link
Member

mlugg commented May 21, 2023

@leecannon

But null is not a valid value of *anyopaque so the flag for the optional must be stored seperately from the pointer as zig cannot use the zero value.

That's not an issue. The contents of the ptr field are undefined if the struct value is null, so it's valid for this otherwise-impossible zero value to be repurposed for the struct's null value.

@Jarred-Sumner

It's a special case - there already is code for making optional pointers the same size as regular pointers. Could that be reused here for structs with a single field as a pointer?

This optimization isn't quite as trivial as you're suggesting - implementing it as a special case would be quite a lot of work, and it definitely wouldn't be possible on the ZIR level as you initially suggested for a bunch of reasons (for instance, ZIR comes prior to semantic analysis so is untyped, so rewriting field accesses on the struct would be impossible). Much better is to implement a general framework for optional optimization as tracked in #104. (I would consider this a duplicate of that issue.)

@Jarred-Sumner
Copy link
Contributor Author

okay

@Jarred-Sumner Jarred-Sumner closed this as not planned Won't fix, can't repro, duplicate, stale May 21, 2023
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

4 participants