-
-
Notifications
You must be signed in to change notification settings - Fork 5.6k
RFC: move Vararg specType rewriting into dispatch #16159
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
Conversation
This also: - adds an enum classification of Vararg types - implements a few convenience functions - switches some checks from jl_is_va_tuple to jl_va_tuple_kind(t) == JL_VARARG_UNBOUND - updates jl_wrap_vararg to take two inputs - displays such Varargs properly in the REPL
This leaves the old one in place and compares the results of the two. This way we can catch bugs immediately, rather than trying to deduce what went wrong from the indirect consequences.
This also makes tweaks to the algorithm to prevent matches like Array{Tuple{Int}} <: Array{NTuple}
This also turns debugging output back on in preparation for the final implementation The cmdlineargs test fails, but only due to the extra output generated.
Matching the symbols turns out to be really dangerous, it's necessary to match pointers.
Needed for NTuple{Integer} declarations like found in sparsematrix.jl.
On current master, this gave true but Type{Tuple{}} <: Type{Tuple{Vararg}} gave false. Now they both give true.
c.f. "Instantiate Tuple{Vararg{Int,3}} as Tuple{Int,Int,Int}"
this ensures that type-inference gets the same method signature from type-intersection as will be used for the actual call
Will this cause the allocation of a tuple for each call to a varargs function? |
no, that's what we do now (where the callee is expected to make the tuple). this instead modifies it such that dispatch is expected to create the tuple (which for specsig, would be inlined into the caller) |
To me that seems to involve tuples in more of the calling process, making them harder to remove. Of course, in the specsig case the caller already has full knowledge of the callee, so it doesn't make much difference. But outside that case the caller doesn't know it's calling a varargs function, so it doesn't quite seem right for it to be the caller's responsibility to handle it. |
right, the "caller" is dispatch (or specsig, after inlining a specialization). this changes is intended to make it so that passes that consume a LambdaInfo don't generally need to consider whether a signature is varargs – the types of the arguments simply line up with their names (and slot numbers). |
|
bceb51b
to
cd910cf
Compare
I don't really see why this is needed for #11242. I'm also not convinced this is a good idea in general. The core issue is that, currently, every argument tuple type we have refers to the caller's arguments. We need to form these tuple types for dispatch. However, once the arguments are bound to names in the callee, there isn't any need for a tuple type of those. Sure, you can represent any N types with a tuple type, but there is no need for this tuple type itself, which makes it suspect to me. One symptom is that the result of Another symptom is, imagine we want to specialize |
Changing specTypes isn't essential, since we can unambiguously recreate this svec at any point from
where did
yeah, i'm not convinced of the value of that transformation timing myself either. it would probably be just as sensible for the caller to continue making that transform if it cares. (e.g. how it happens in type-inference now, which I deleted after moving the transformation into ml_matches) |
It's just that |
except that it doesn't: |
Jeff's strategy is the one I took in my own attempt at this, #11242 (comment). |
I don't necessarily advocate doing that transformation, I just feel like this increases coupling. Actually I really like the idea of renaming specTypes to argTypes and making it an svec. That greatly clarifies the intended meaning here. From there we just need to be a bit careful about whose responsibility it is to initialize that field. As an interesting data point, |
Actually, we could store these types in |
we would need to change lowering such that if an argument is reused as a variable it gets two slots, but i think that's certainly feasible |
Yes, it might be better to explicitly introduce new slots for assigned arguments, since codegen basically has to implement that anyway. |
#16165 Looks like a case where it would have been more convenient for lowering to have done that transformation. |
e971899
to
92ac59a
Compare
As a start to addressing the need for a specSig representation for vararg calls, this moves the responsibility for forming the varargs argument tuple type from the callee to the caller (e.g. dispatch or specsig). My thought here is that instead of implementing this logic in codegen as a special case, this representation will make it easier to share existing code for allocating and passing around tuples. This means that now we would now have that
length(specTypes) == length(argnames)
. I think this representation (where specTypes maps directly to argnames instead of to the callee's argument tuple) is cleaner than having each consumer effectively re-implement this each time (inference, codegen, generic functions for #12783)this implements #12783 along the way