-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
WIP: controlling dispatch with varargs of defined length (rebased) #10911
Conversation
Passing all tests. Since this went through review once already, I'll merge soon if I don't hear anything to the contrary. |
I think I found a bug:
The new vararg types seem to have the interesting property of being "epsilon" larger than some concrete type:
I think we will eventually have to bite the bullet and make these type-equal. Making vararg types always abstract is kind of clever, since it sidesteps various issues, but I wonder if it will have unintended consequences. |
To get this working well (at least as well as NTuples do now) it might be easiest to reuse/replace all the existing NTuple code with this, and make |
Also |
Thanks for the review! I'll wager that both of those issues are due to the fact that I broke the symmetry of I confess I'm not sure I understand what you mean about the NTuple unification, but I will study it and ask again if I can't figure it out. |
I mean that since |
Got it. I was concerned that since we don't allow "interior" varargs this couldn't really be what you meant, but I guess since they're already "packed" it will be OK. |
Now I'm beginning to get a better appreciation for the kinds of things that keep you up at night. For example, what should I suspect this needs to be fixed before we can really implement |
Wow, it's great that there's a separate commit for that. I didn't notice that at first. Nicely done @timholy ! |
Fixes up the expanded ast so that jl_is_rest_arg, as called from emit_function (step 2), works properly and avoids a later segfault.
This is at least enough to get the build working
The block of tests focused on subtype and intersect all pass now.
I'm making progress: replacing julia> N = TypeVar(:N,true)
N
julia> Tuple{} <: NTuple{N,Int}
true
julia> Tuple{Array{Int,2}} <: Tuple{Array{Int,N}}
true
julia> Tuple{Array{Int,2}} <: Tuple{Array{Int,N}, Vararg{Int}}
true In the new branch the first should be translated to julia> Tuple{Array{Int,0}} <: Tuple{Array{Int,N},Vararg{Int,N}}
true but that we'd also presumably want julia> Tuple{Array{Int,2}} <: Tuple{Array{Int,N},Vararg{Int,N}}
false However, the whole |
Ah, this has nothing to do with varargs/ntuples: julia> Tuple{Array{Int,2},Array{Int,3}} <: Tuple{Array{Int,N},Array{Int,N}}
true So I guess |
I guess that
|
It doesn't, though. (You can check on master using my last example.) I think |
Maybe (hopefully) this will change with #8974 , when it will become easier to create such types as @UnionAll N Tuple{Array{Int,N},Array{Int,N}} ? |
OK, now this is getting much further: 1955 lines into I vote we rename this PR "tupoca:lips:" |
Most computations on the type lattice are only required to overapproximate the result for correctness. That is The failure mode for inexactness should only be spurious ambiguity warnings where you would be forced to implement the dispatch rules by hand because the method table can't figure it out by itself (and sub-optimal type inference). Typevars are another business however and I'm not sure they are handled everywhere as one would expect. |
The difference re typevars is simply that jl_type_intersect takes the |
In the future, the only reason for the typevar arguments to jl_type_intersect will be to request values for particular variables, i.e. compute the intersection plus tell me what constraints it implies about the specified variables. |
Meaning, you'd rather see the intersection code return something that's not |
No, no, if intersection knows there are incompatible constraints, it should absolutely return Bottom. The returned environment in that case should generally not be used. In inexact cases the returned environment will have overly broad constraints like T=T. |
This uses a more systematic approach, and should be more maintainable. Also adds lots of documentation about the strategy.
@JeffBezanson, I'm finding some differences in subtyping behavior with let N = TypeVar(:N,true), V = TypeVar(:V, NTuple{N,Int}), T = TypeVar(:T,true)
@test Tuple{} <: NTuple
@test Tuple{} <: NTuple{N,Int}
@test Tuple{} <: NTuple{N,T}
@test !(Array{Tuple{}} <: Array{NTuple}) # is the difference...
@test Array{Tuple{}} <: Array{NTuple{N}} # ...here desirable?
@test Array{Tuple{}} <: Array{NTuple{N,Int}}
@test Array{Tuple{}} <: Array{NTuple{N,T}}
@test Array{Tuple{Int}} <: Array{NTuple{N,Int}}
@test Array{Tuple{}} <: Array{NTuple{TypeVar(:N),Int}} # these two...
@test !(Array{Tuple{Int}} <: Array{Tuple{Vararg{Int}}}) # ...conflict
@test !(Array{Tuple{Int}} <: Array{Tuple{Int,Vararg{Int}}})
@test Tuple{Type{Int8}, Tuple{}} <: Tuple{Type{Int8}, NTuple{N,Int}}
@test Tuple{Type{Int8}, Tuple{Int,Int}} <: Tuple{Type{Int8}, NTuple{N,Int}}
@test V <: NTuple # and...
@test !(V <: Tuple{Vararg}) # ...here
end If it helps, I can pull out the lines of source that causes these differences; the last one (the (Note: small edits applied to the above after initial posting.) |
I may have this about ready (it's not pushed yet, just on my own machine). But I'm running into a snafu I should have anticipated much earlier. I'd like to make the typealias look like this: #typealias NTuple{N,T} Tuple{Vararg{T,N}}
const NTuple = Tuple{Vararg{Any}}
const NTuple{N} = Tuple{Vararg{Any,N}}
const NTuple{N,T} = Tuple{Vararg{T,N}} but of course this doesn't work. Unfortunately, the commented-out typealias (which is permissible syntax) causes @test !(issubtype(Array{Tuple{Vararg{Int}}},Array{NTuple})) EDIT: hmm, maybe that test simply has to go. After all, we have julia> Array{Tuple{Int}} <: Array{NTuple}
true so A secondary point is that I wonder if there are any negatives to having this typealias in |
Superseded by #11242 |
#10691 needed to be reworked in the wake of the merger of #10380. I decided the easiest approach would be to start fresh. Compared to that PR, this
foo(x::Vararg{Any,3})
.Aside from those, it's basically the same as #10691.