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

RFC: Allow inference of recursion on a decreasing integer type parameter #26172

Merged
merged 1 commit into from
Feb 26, 2018

Conversation

martinholters
Copy link
Member

This makes use of the alternative already mentioned by @vtjnash in the comment.

Motivation

In JuliaArrays/StaticArrays.jl#368, I have implemented an LU decomposition for StaticMatrices that recursively calls itself on sub-matrices. It works (almost) without @generated functions and allows for relatively clean code. Overall, I'm quite happy with the result---except that it doesn't work on 0.7. Well, it works *), but it cannot be inferred, which is bad news for StaticArrays. Slightly simplified, the problem is that lu(::SArray{Tuple{6,6},Float64,2,36} calls lu(::SArray{Tuple{5,5},Float64,2,25} calls SArray{Tuple{4,4},Float64,2,16} and so on, but that latter argument types are considered more complex, making inference bail out of the recursion. However, that coding style in probably recommendable, similar to working with tuples by recursively decomposing them. So it would be really nice to make inference work for it, which this PR achieves.

*) After applying a work-around for #26083.

Drawback

If one writes a recursion where an integer type parameter is successively decremented to zero and starts it at 10000, inference will run into a stack overflow. Could be solved by putting an upper limit on t (or c) here, but it's a bit unclear what that should be.


f_PRNUM(v) = Val{length(Base.tail(ntuple(identity, v)))}() # Val(M-1)
g_PRNUM(::Val{0}) = ()
g_PRNUM(v) = (nothing, g_PRNUM(f_PRNUM(v))...)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll replace _PRNUM here if this gets a general approval.

@@ -256,7 +256,7 @@ function type_more_complex(@nospecialize(t), @nospecialize(c), sources::SimpleVe
return type_more_complex(t, c.a, sources, depth, tupledepth, allowed_tuplelen) &&
type_more_complex(t, c.b, sources, depth, tupledepth, allowed_tuplelen)
elseif isa(t, Int) && isa(c, Int)
return t !== 1 # alternatively, could use !(0 <= t < c)
return !(0 <= t < c)
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can probably also keep && t !== 1.

Or, if we felt like being even more permissive, we could do the comparison with !(abs(t) <= abs(c) || t < n). (for some arbitrary value of n >= 1, such as 1). Maybe just put that as the "# alternatively, could use" comment for the next person? 😜

@martinholters martinholters merged commit 79c7bdd into master Feb 26, 2018
@martinholters martinholters deleted the mh/infer_int_limit branch February 26, 2018 07:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compiler:inference Type inference
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants