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

Base.setindex return type inference quick fix #54463

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

nsajko
Copy link
Contributor

@nsajko nsajko commented May 14, 2024

Xref #54462

@kimikage
Copy link
Contributor

kimikage commented May 14, 2024

In the first place, is it appropriate to use ntuple for code which do not return NTuple?
It is misleading, even if it is intentional and follows the documentation.

(I think it is also misleading that the function _setindex exists in Base. Can't we use _setindex_tuple or something like that?)

I think it would be appropriate to specialize only for true NTuple cases, and naively use Tuple() or (itr...,) without the tricky Vararg for the rest cases. Since the setindex creates a new object and checks the bounds, I suspect the optimization effect by specialization is minor.

Of course, I have no objection to this PR (quick fix) per se.

@kimikage
Copy link
Contributor

E.g.

import Base: setindex

function setindex(x::Tuple, v, i::Integer)
    @boundscheck 1 <= i <= length(x) || throw(BoundsError(x, i))
    @inline
    _setindex_tuple(x, v, i)::Tuple
end

function _setindex_tuple(x::NTuple{N, T}, v::T, i::Integer) where {N, T}
    @inline
    return ntuple(j -> ifelse(j == i, v, x[j]), Val{N}())
end

function _setindex_tuple(x::Tuple, v, i::Integer)
    @inline
    return ((ifelse(j == i, v, xj) for (j, xj) in enumerate(x))...,)::Tuple
end

@nsajko
Copy link
Contributor Author

nsajko commented May 15, 2024

I've got a better fix locally, a recursive implementation of _setindex, not based on ntuple. It's got way better inference. E.g.:

julia> Core.Compiler.return_type(Base.setindex, Tuple{Tuple{Vararg{Int}},Int,Int})
Tuple{Vararg{Int64}}

nsajko added a commit to nsajko/julia that referenced this pull request May 15, 2024
FTR, this PR is part of a series of changes which (re)implement many of
the operations on tuples using a new recursive technique. The ultimate
goal is to hopefully increase the value of the loop-vs-recurse cutoff
(`Any32`, sometimes hardcoded `32`) for tuple operations.

Updates JuliaLang#54462

Closes JuliaLang#54463

Example type inference improvement:

```julia-repl
julia> Core.Compiler.return_type(Base.setindex, Tuple{Tuple{Vararg{Int}},Int,Int})
Tuple{Vararg{Int64}}
```
@nsajko nsajko added the domain:collections Data structures holding multiple items, e.g. sets label May 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
domain:collections Data structures holding multiple items, e.g. sets
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants