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

Remove @fieldParentPtr builtin #7831

Closed
marler8997 opened this issue Jan 19, 2021 · 10 comments
Closed

Remove @fieldParentPtr builtin #7831

marler8997 opened this issue Jan 19, 2021 · 10 comments
Labels
breaking Implementing this issue could cause existing code to no longer compile or have different behavior. proposal This issue suggests modifications. If it also has the "accepted" label then it is planned.
Milestone

Comments

@marler8997
Copy link
Contributor

This blog shows @fieldParentPtr could be implemented in the standard library: https://www.ryanliptak.com/blog/zig-fieldparentptr-for-dumbos/

Maybe we should remove the builtin in favor of a user implmentation?

@mikdusan

This comment has been minimized.

@ifreund
Copy link
Member

ifreund commented Jan 20, 2021

Zig gives no guarantees about the order of fields and the size of the struct.

Indeed, but that shouldn't matter as @byteOffsetOf() or @bitOffsetOf() give you the information you need.

@daurnimator
Copy link
Contributor

Is @ptrToInt supported at comptime? At least it didn't used to be, which would have been at least one motivation for @fieldParentPtr.

@byteOffsetOf is isomorphic to @fieldParentPtr: you can implement either with the other. (uh, you might need @bitOffsetOf as well I guess for packed structs?)

@rohlem
Copy link
Contributor

rohlem commented Jan 21, 2021

@daurnimator We don't need an absolute address from @ptrToInt, we can instead cast the pointer to the member to [*] u8 (or [*] byte), offset that by -@byteOffsetOf(container_type, member_name) and then cast it to * container_type.
As far as I understood the recent "memory isle" idea, this should all be supported in comptime (as long as your math is correct and you stay in bounds).

On the topic of isomorphisms, @byteOffsetOf and @bitOffsetOf can also be implemented in terms of pointer(-to-many) subtraction (though bit offsets/alignments require currently-missing @typeInfo fields, #6846) so they are also candidates for userspace implementation. No idea how efficient that logic would be at comptime compared to the builtin though.

@jayschwa jayschwa added breaking Implementing this issue could cause existing code to no longer compile or have different behavior. proposal This issue suggests modifications. If it also has the "accepted" label then it is planned. labels Jan 24, 2021
@ghost
Copy link

ghost commented Jan 26, 2021

@offsetOf and ilk are kind of a nightmare for the compiler, since they return comptime values but optimisation doesn't happen until sema; so, if you ever call an offset builtin and use the value at comptime, layout optimisation is skipped entirely. The only use case I've ever seen for the offset builtins over @field/@fieldParentPtr (iterating over fields at runtime without unrolling a hot loop) is actively hurt by the comptime return value, since you have to take great care to avoid inlining the loop.

I have proposed #7888 for this exact issue. If accepted, the offset builtins will not be abusable in this way.

@Vexu Vexu added this to the 0.8.0 milestone Jan 26, 2021
@data-man
Copy link
Contributor

Maybe we should remove the builtin in favor of a user implmentation?

And @field, @hasDecl, @hasField (there is meta.trait.hasField).

???

@ifreund
Copy link
Member

ifreund commented Jan 31, 2021

Maybe we should remove the builtin in favor of a user implmentation?

And @field, @hasDecl, @hasField (there is meta.trait.hasField).

???

I don't think we can remove @field() as it can be used as an l-value in assignments. I don't see any issue with removing @hasDecl() and @hasField() for the std.meta implementations though.

@rohlem
Copy link
Contributor

rohlem commented Jan 31, 2021

IIRC one reason in favour of @hasDecl and @hasField was that they perform direct lookup, so only require O(log(field_count)) in the general case, whereas an std.meta implementation (going via @typeInfo) has to look over all fields, making the operation inherently O(field_count).
These lookups also don't force evaluation of the full type, whereas stubbing @typeInfo with lazy values is more complex (and will probably lead to weird corner cases). See #1439 for some discussion about this.

@data-man
Copy link
Contributor

One reason in favour of trait.hasField/hasDecl:

if (meta.trait.hasField(T, "Name[0-9]") {
	...
}

@andrewrk andrewrk modified the milestones: 0.8.0, 0.9.0 May 19, 2021
@andrewrk
Copy link
Member

It's better to have @fieldParentPtr because the compiler understands the intent and can do things such as

  • emit better compile errors
  • emit safety checks
  • emit better code
  • avoid forcing struct layouts prematurely, causing unnecessary "foo depends on itself" errors

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
breaking Implementing this issue could cause existing code to no longer compile or have different behavior. proposal This issue suggests modifications. If it also has the "accepted" label then it is planned.
Projects
None yet
Development

No branches or pull requests

9 participants