-
-
Notifications
You must be signed in to change notification settings - Fork 5.7k
Implement RefField <: Ref{T} #35453
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
Implement RefField <: Ref{T} #35453
Conversation
Allows describing a GetElementPointer operation on a field of an object, complementary to the existing ones for RefValue and RefArray.
| """ | ||
| RefField <: Ref{T} | ||
| Create an object reflection adaptor that represents the properties of a specific object field. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Took me a while to parse this. Maybe
Obtain a reference to a specific object field, by creating an object reflection adaptor that wraps the parent object and the properties of a specific object field.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or, to focus more on the interface which people will actually use:
"""
RefField(object, field)
Obtain a reference to an individual field of an `object`, where the given `field`
may be an index or a symbol (see also [`Base.fieldindex`](@ref)).
The returned `RefField <: Ref` is an object reflection adaptor that wraps the
parent `object` and the properties of a specific object field.
"""| d::Integer | ||
| e::Complex{BigFloat} | ||
| end | ||
| @testset "RefField" begin |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| @testset "RefField" begin | |
| @testset "RefField struct" begin |
| @test Base.unsafe_convert(Ptr{Integer}, d) == unsafe_load(Ptr{Ptr{Integer}}(d_ptr)) | ||
| @test Base.unsafe_convert(Ptr{Complex{BigFloat}}, e) == unsafe_load(Ptr{Ptr{Integer}}(e_ptr)) | ||
| end | ||
| @testset "RefField" begin |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| @testset "RefField" begin | |
| @testset "RefField mutable struct" begin |
| b_ptr = Base.unsafe_convert(Ptr{ManyFields}, b.x) + 8 | ||
| c_ptr = Base.unsafe_convert(Ptr{ManyFields}, c.x) + 16 | ||
| d_ptr = Base.unsafe_convert(Ptr{ManyFields}, d.x) + 24 | ||
| e_ptr = Base.unsafe_convert(Ptr{ManyFields}, e.x) + 32 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aren't these offsets system dependent?
|
Looks very useful to me. One design question: is it possible to use this recursively to refer to nested fields? Reading the implementation I think not, but it would seem useful. |
What if we made |
No I don't think so, it might be better to allow |
I guess it'd be possible to chain to |
Yes I agree wrapping would be cleaner (especially considering interop with |
| struct RefField{f,T,S} <: Ref{T} | ||
| x::RefValue{S} | ||
| RefField{f,T,S}(x::S) where {f,T,S} = new{f::Int,T,S}(RefValue(x)) | ||
| end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How does this work with immutables? For example, if I have:
x = (a=1, b=2)
ra = RefField(x, :a)
rb = RefField(x, :b)
ra[] = 10
rb[] = 20After this code, I suppose x === (a=1, b=2) still holds? How do I get (a=10, b=20)? Is there going to be some compiler intervention?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this similar to C's address operator &x.a?
|
FYI here is my implementation of nestable Ref (for simple isbits case): https://discourse.julialang.org/t/alternative-to-mutable-named-tuple/38375/15 |
|
Yeah, that code's kinda fundamentally flawed. I do need to look closer into how Ref ends up dealing with nesting though, and probably figure out how it should work before merging this. |
|
Supporting nesting seems pretty complex and can maybe be deferred; for example RefArray doesn't handle nested arrays either. |
Arrays don't have inline storage? |
Some types of arrays do. |
|
This would be really handy! (would happily replace my poor man's |
|
yeah, I just stopped having a use case for this myself, and felt that it potentially also would ideally attempt to deal with nested pointers, for the full "mutating immutables" deal, but that is a hard problem. |
|
Notes from triage: I'm personally in favor of having some version of this to round our our |
Allows describing a GetElementPointer operation on a field of an object,
complementary to the existing ones for RefValue and RefArray.