-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
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
use case: initialize struct with one field pointing to another #172
Comments
Correct me if I'm wrong, but this would only be useful for structs that can be guaranteed to be at a certain address at compile time (e.g. const at top-level of a module), right? I'm just trying to wrap my head around this. |
Correct. It is a bit error prone, since the reference becomes invalid if you use byval struct assignment. But it is possible to generate such static data structures, so it should arguably be expressible in zig. |
Maybe #169 could help: fn foo() -> Thing {
Thing {
field1: &this.field2,
field2: 1234,
}
} There's still a problem to solve here, however. In general, fields which point to other fields in a struct are pointing to an address on the stack, which becomes invalid when the function returns a struct byval. We're actually considering making it a compile error to pass or return structs or other large objects by value. This is where the abstraction of executing code at compile time gets a bit leaky, because it actually does make sense to return a struct byval if the function runs at compile time. This is maybe another hint that the following syntax for return values might be better (explicit naming of return value storage): fn foo() -> (result: &Thing) {
result.field1 = &result.field2;
result.field2 = 1234;
} Another idea I had just now is that we can have copying structs be a compile error by default. In order to allow structs to be mem copied or byvalue assigned, you'd have to add This way when you have a struct more complicated than Plain Old Data, you can be sure that nobody accidentally copies the memory thinking that the new memory will be valid. There should be a way to override this safety check when necessary. Maybe the struct's own copy implementation is aware of the issues with copying and knows to patch up the incorrect fields after doing a mem copy. |
After having dealt with C++ default copy constructors, I'd advocate for no-copy being the default, and needing to specify If we define "copying" as recursively copying each element (as opposed to jumping straight to memcpy), then the no-copy restriction is contagious to any struct containing a no-copy struct, which is probably what we want. |
Sounds good. I think we can get away with defining these semantics while still having it codegen to a memcpy. |
Related to #591 (comment) |
This use case is solved by the result location semantics proposed in #2765 and this code: const Thing = struct {
field1: &i32,
field2: i32,
};
fn foo() -> Thing {
var result = Thing{
.field1 = undefined,
.field2 = 1234,
};
result.field1 = &result.field2;
return result;
} |
The text was updated successfully, but these errors were encountered: