-
-
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
deprecate unsafe_length for length #40382
Conversation
3cc9cba
to
6c549a9
Compare
Very nice to eliminate these ugly functions. Triage is concerned about what checks we should have though. We discussed checking on construction whether a range will have a correct length, and moving the error there. |
6c549a9
to
9a7bea2
Compare
triage thought this was a reasonable change, but that we should keep the current version around as |
This seems to be a fairly arbitrary case for throwing exceptions, when the user might often use this value in arithmetic afterwards, which is not checked. It leads to awkward complexity in the API however, where it may be unclear which function to reach for, with no particular justification for why a particular usage is "safe". And it inhibits optimization and performance due to the additional checks and error cases (and is not even entirely type-stable).
@JeffBezanson this should be ready to go now. It removes checking for overflow in length for |
This seems to be a fairly arbitrary case for throwing exceptions, when the user might often use this value in arithmetic afterwards, which is not checked. It leads to awkward complexity in the API however, where it may be unclear which function to reach for, with no particular justification for why a particular usage is "safe". And it inhibits optimization and performance due to the additional checks and error cases (and is not even entirely type-stable).
After this pull request julia> using Unitful
julia> length(1u"m":2u"m":0u"m")
0 m |
This seems to be a fairly arbitrary case for throwing exceptions, when the user might often use this value in arithmetic afterwards, which is not checked. It leads to awkward complexity in the API however, where it may be unclear which function to reach for, with no particular justification for why a particular usage is "safe". And it inhibits optimization and performance due to the additional checks and error cases (and is not even entirely type-stable). (cherry picked from commit 3eefaf0)
I noticed [here](#50467 (comment)) that `lastindex(x::Base.OneTo)` is not simply `x.stop`. This PR performs that optimization and many more by assuming `size` always returns positive numbers. ``` julia> @code_native lastindex(Base.OneTo(5)) # master .section __TEXT,__text,regular,pure_instructions .build_version macos, 13, 0 .globl _julia_lastindex_81 ; -- Begin function julia_lastindex_81 .p2align 2 _julia_lastindex_81: ; @julia_lastindex_81 ; ┌ @ abstractarray.jl:423 within `lastindex` ; %bb.0: ; %top ; │┌ @ abstractarray.jl:386 within `eachindex` ; ││┌ @ abstractarray.jl:134 within `axes1` ; │││┌ @ range.jl:708 within `axes` ; ││││┌ @ range.jl:471 within `oneto` ; │││││┌ @ range.jl:469 within `OneTo` @ range.jl:454 ; ││││││┌ @ promotion.jl:532 within `max` ; │││││││┌ @ int.jl:83 within `<` ldr x8, [x0] ; │││││││└ ; │││││││┌ @ essentials.jl:642 within `ifelse` cmp x8, #0 csel x0, x8, xzr, gt ; │└└└└└└└ ret ; └ ; -- End function .subsections_via_symbols julia> @code_native lastindex(Base.OneTo(5)) # pr .section __TEXT,__text,regular,pure_instructions .build_version macos, 13, 0 .globl _julia_lastindex_13253 ; -- Begin function julia_lastindex_13253 .p2align 2 _julia_lastindex_13253: ; @julia_lastindex_13253 ; ┌ @ abstractarray.jl:423 within `lastindex` ; %bb.0: ; %top ldr x0, [x0] ret ; └ ; -- End function .subsections_via_symbols ``` Also removed `axes(r::AbstractRange) = (oneto(length(r)),)` (added in #40382, @vtjnash) as redundant with the general `axes` method. The obvious downside here is that if someone defines an object with negative size, its axes will include Base.OneTo with negative stop. I think that is acceptable, but if not, we can gate this optimization to a set of known types (all AbstractArray types defined in Base should have non-negative size)
This seems to be a fairly arbitrary case for throwing exceptions, when the user might often use this value in arithmetic afterwards (e.g. see
searchsorted
), which is not checked. It leads to awkward complexity in the API however, where it may be unclear which function to reach for, with no particular justification for why a particular usage is "safe". And it may inhibit optimization and performance due to the additional checks and error cases (and is not even entirely type-stable).Performance seems to be basically identical: