-
Notifications
You must be signed in to change notification settings - Fork 149
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
Unpirate Union{}[] #685
Unpirate Union{}[] #685
Conversation
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.
I guess this is the correct way to do this?
Although would Vector{Union{}}()
be clearer and avoid a run-time invoke?
It seems julia> @inline f() = invoke(getindex, Tuple{Type}, Union{})
f (generic function with 1 method)
julia> @inline g() = Vector{Union{}}()
g (generic function with 1 method)
julia> @code_typed f()
CodeInfo(
1 ─ %1 = $(Expr(:foreigncall, :(:jl_alloc_array_1d), Array{Union{},1}, svec(Any, Int64), 0, :(:ccall), Array{Union{},1}, 0, 0))::Array{Union{},1}
└── return %1
) => Array{Union{},1}
julia> @code_typed g()
CodeInfo(
1 ─ %1 = $(Expr(:foreigncall, :(:jl_alloc_array_1d), Array{Union{},1}, svec(Any, Int64), 0, :(:ccall), Array{Union{},1}, 0, 0))::Array{Union{},1}
└── return %1
) => Array{Union{},1} I personally prefer |
I should mention that importing StaticArrays still alters the type of error thrown by Before importing StaticArrays:
After importing StaticArrays (of this PR):
Typically exception type is not in the API domain so I'm not sure if we need to care, though. |
Oh wow this is nasty :-/ Good catch. I'm not sure this is the right way to go about fixing this. Adding a lower bound seems like it might work instead? @inline Base.getindex(sa::Type{T}, xs...) where {E, SA{E}<:T<:SA} = similar_type(sa, Size(length(xs)))(xs) We will need fixes for |
Thanks, that's much more elegant. |
Looks good, cheers! I think we can merge this, though I added a suggested comment because having a lower bound is extremely unusual. The fact that this was a problem at all is kind of concerning. I've written a lot of |
Co-Authored-By: Chris Foster <chris42f@gmail.com>
src/initializers.jl
Outdated
@@ -26,6 +26,7 @@ const SA_F64 = SA{Float64} | |||
@inline similar_type(::Type{SA}, ::Size{S}) where {S} = SArray{Tuple{S...}} | |||
@inline similar_type(::Type{SA{T}}, ::Size{S}) where {T,S} = SArray{Tuple{S...}, T} | |||
|
|||
# Lower bound `SA{E}<:T` prevents `T == Union{}` from accidentally matching this signature. | |||
@inline Base.getindex(sa::Type{T}, xs...) where {E, SA{E}<:T<:SA} = similar_type(sa, Size(length(xs)))(xs) |
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.
What about SA
precisely?
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.
There's nothing special about SA
... It's just that ::Type{<:SA}
is considered more specific to matching Union{}
than a generic ::Type{T}
:
julia> foo(::Type{T}) where {T} = "generic"
julia> foo(::Type{<:Int}) = "special"
julia> foo(Union{})
"special"
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.
somewhat disturbing eh?
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.
Yes, I get that part.
I can see the above is fine for SA{Int64}[1,2,3]
. But what about vanilla SA[1,2,3]
? We don't have SA{E} <: SA
for any (invariant) E
, do we?
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.
Oh right, I didn't understand your question. You're asking why T === SA
works here?
We do have SA{E} <: SA
for any choice of E
, but then E
doesn't have a definite value which is kind of weird. Actually this kind of thing has caused the inliner to fail in the past (see #665) for some reason.
The normalization of the following is also doing my head in a bit
julia> T where SA{E} <: T <: SA where E
SA
Uh oh. It turns out that the compiler (inliner?) doesn't like this implementation: julia> foo() = SA[1,2,3]
foo (generic function with 1 method)
julia> @code_typed optimize=true foo()
CodeInfo(
1 ─ %1 = Base.getindex(Main.SA, 1, 2, 3)::Core.Compiler.Const([1, 2, 3], false)
└── return %1
) => SArray{Tuple{3},Int64,1,3} Strangely enough, inference seems to have worked really well and constant propagated everything, but the getindex call is still there. What. |
I rollback to |
I still feel bad about having a special case defined for The lower bound optimization issue seems related to JuliaLang/julia#30713 |
Thanks! That's much better. |
I just noticed another approach was Type₁(U) = Type{T} where {P, U{P} <: T <: U}
@inline Base.getindex(sa::Type₁(SA), xs...) = similar_type(sa, Size(length(xs)))(xs) Inliner does seem to work with this. Maybe it's nice to have something like |
I opened an issue here: JuliaLang/julia#33780 |
Thanks, excellent. By the way do you need this fix urgently? We could release a 0.12.1 more or less immediately if that helps. |
Thanks, but it's not urgent. I just excluded 0.12 in the projects that hits this bug. But now that the registry is automated maybe you can go with more frequency release cycle? |
Yes, I think I'll release soon anyway. I thought @oxinabox's blog post on continuous delivery had some good points (most especially for bug fixes) https://white.ucc.asn.au/2019/09/28/Continuous-Delivery-For-Julia-Packages.html though it would be nice to be a tad more automated. I like your |
I think that's a great ideal. But I can see that you maybe need to be a bit more conservative for "almost- |
Yeah, well 0.12.1 is very conservatively just patching this particular issue so I just released it. |
Union{}[]
does not work after I importStaticArrays
(cb46c2d) due to the newSA[...]
constructor:This PR fixes it by overloading type piracy by yet another type piracy.
(Though I'm not sure if this is technically a type piracy. If you can't overload anything that can accept
Type{Union{}}
, you can't writeType{<:MyType}
. But thengetindex(::Type{Union{}}) = ...
just totally looks like a type piracy...)