-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Allow Plan 9/Go style struct embedding #1214
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
Comments
IIRC Zig reserves the right to reorder fields. So the child struct may not have the same field order as the parent. |
What's the problem with that @kyle-github? |
If the compiler can reorder fields, then your "parent" struct might not be embedded at the beginning of the "child" struct. Or, if you flatten it, the fields in the parent part might be in a different order (or even mixed with) the fields of the child part. In other words, for this to work sanely, you also must require that fields are not changed in order from the way they are declared. There are two main requirements that C makes: the first is that a pointer to a struct is a pointer to the first field (lexically) in the struct, the second is that fields are never reordered by the compiler, they are always in the exact order given in the struct definition. Since things as remote as cache line size can impact field ordering choices, placing restrictions on field ordering just for this purpose seems like a large cost. C pays for it all the time now. |
@kyle-github that would be true for upcasting, where you must assume the base class is at offset 0 of the struct. But the Plan 9 extension is a bit more elegant. Agreed the field reordering would not be true for C, so the function knows the offsets of each field from the base struct alone. However, it can do this:
The GCC example is here:
Same idea. |
@kyle-github, that doesn't stop access to any other field, so why would it stop access for an embedded struct? In Go, it's not actually inheritance, it's really just sugar. There are a few facets to this:
Hope this info is helpful to clarify OP's intent. I favor this idea because it's quite convenient in Go, and also plays nice with Go's design for interfaces. |
Thanks @binary132 for explaining. Ya the Plan 9 compiler extensions do exactly the same thing as Go does. Even referring to the member by the anonymous member's type works (note the GCC example I provided does this). |
Note: this feature tends to be really great. Being able to call foo.lock() on an arbitrary struct foo is awesome. This code is from portdat.h of the Plan 9 kernel.
|
Example of an ugly-ness this issue will solve: https://github.com/ziglang/zig/pull/2525/files#diff-41648b87f70e3cdb2d95dc1ce9ed9f38R1042 |
a possible use case this would improve would be API loaders. @MasterQ32's and my own OpenGL loaders would be able to cut down on a lot of code repetition if we could "inherit" fields from other structs. |
After discussing at the design meeting, we've decided that this is too complicated. If we did this, we would need additional complexity to handle cases like #7391, where the outer struct needs to preserve extra invariants in the inner one. In Go, you can override the implementation of an embedded member function when called through the outer struct by providing another with the same name and signature. We feel that this ability to override functions would be necessary to make this form of embedding usable, but is also too complicated to include in this language. Additionally, all of these use cases can be solved with the current language, and the syntax to do them isn’t all that verbose. The reduced form described in #5561 is much simpler, but also much less useful, and possible with the current language semantics, so that has also been rejected. We haven't reached a decision on the more fine grained #7311. We have accepted a variant of #985, which solves the specific use case of interfacing with C libraries like io_uring that use unnamed fields of anonymous struct/unions. |
GCC allows use of
-fplan9-extensions
to accomplish Go-style anonymous struct embedding. See more here. I believe this is a simple C concept (seeing as it was a Plan 9 C compiler extension), so does not conflict with the C-style simplicity of Zig, and adds some nice abstractions to structs for free. The main benefit: extending a struct is by and large unnecessary when the compiler let's you treat the parent struct like it was an instance of the embedded base class (Liskov substitution principle applies to parent structs).One quick example,
stdout
often needs to be replaced withstdout.stream
despite the fact thestdout
is meant to implement a stream. This could simplify all uses ofstdout.stream
back tostdout
.The text was updated successfully, but these errors were encountered: