-
-
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
[RFC] Add index hint to BoundsError message #43815
base: master
Are you sure you want to change the base?
Conversation
test/arrayops.jl
Outdated
|
||
# Also test : directly for custom types for which it may appear as-is | ||
err = BoundsError(x, (10, :)) | ||
showerror(b, err) | ||
@test String(take!(b)) == | ||
"BoundsError: attempt to access 2×2 Matrix{Float64} at index [10, :]" | ||
"BoundsError: attempt to access 2×2 Matrix{Float64} at index [10, :].\nLegal indices are [1:3, 1:3]." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"BoundsError: attempt to access 2×2 Matrix{Float64} at index [10, :].\nLegal indices are [1:3, 1:3]." | |
"BoundsError: attempt to access 2×2 Matrix{Float64} at index [10, :].\nLegal indices are [1:2, 1:2]." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@gustaphe Thank you for your contribution and welcome to the community. This does make error messege clearer!
Beside the the above typo. I guess you also need to fix the test in Test
and resolve the mismatches in doc examples.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I have a hard time running the tests, they end up running my laptop's memory into the ground and causing a reboot. I thought I found a subset of the tests that would catch everything but sadly some slipped through. I don't want it to seem like I'm brute force debugging this by spamming commits, but I don't have any other method of knowing it works so I kind of am.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is okay to brute force it with CI time. We usually have a little bit of excess. This seems like a good idea. It might conflict eventually with #43738, but let's cross the bridge later, and hopefully merge this sooner.
English isn't my first language, but 'Legal indices' sounds too strong an admonition to me, perhaps 'Valid indices' would sound more pleasant while conveying the same message? |
Mine either, but you're probably right. I was informed of the existing error hint system, not sure if this is much better but it's maybe a little cleaner. I also added some more documentation under "interfaces". The remaining failing build I think has nothing to do with this PR, right? I don't know how to fix it either way. |
I think this is a good idea but it feels a bit "spammy" to print it for e.g. normal arrays. Maybe it should only be printed when the axis is not the standard |
Good shout. I've left the hint in for tuples, because |
IMO this isn't too spammy (especially because Julia is 1 indexed). experienced users are unlikely to see many bounds errors (cause they will write good code), so this is a feature that will mostly be seen by users new to Julia (or programming in general). Getting a good error message the first time you try to take |
Come to think of it I agree. Went back and read the motivation for doing this to begin with, and the latest commit would kind of ruin the main advantage. But I'm deferring the decision, happy to implement whichever version is favored by maintainers. But I'll hold off on sorting out the currently failing tests until then. |
adding a triage label to decide if we want to do this. |
Triage likes this :) |
base/abstractarray.jl
Outdated
@@ -744,7 +744,7 @@ checkbounds_indices(::Type{Bool}, ::Tuple{}, ::Tuple{}) = true | |||
throw_boundserror(A, I) = (@noinline; throw(BoundsError(A, I))) | |||
|
|||
function describe_valid_indices(io::IO, a::AbstractArray{<:Any}, i=nothing) | |||
print(io, "Valid indices are ") | |||
print(io, "\nValid indices are ") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Imo, there should not be a new line here, cf
julia> "fαb"[3]
ERROR: StringIndexError: invalid index [3], valid nearby indices [2]=>'α', [4]=>'b'
base/errorshow.jl
Outdated
@@ -32,9 +32,25 @@ showerror(io::IO, ex) = show(io, ex) | |||
show_index(io::IO, x::Any) = show(io, x) | |||
show_index(io::IO, x::Slice) = show_index(io, x.indices) | |||
show_index(io::IO, x::LogicalIndex) = summary(io, x.mask) | |||
show_index(io::IO, x::OneTo) = print(io, "1:", x.stop) | |||
function show_index(io::IO, x::OneTo) | |||
if x.stop == 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not consistently print as start:stop
no matter then length like before? Also for Tuple
below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe. Just a style choice but it didn't really matter to me. I'll fix.
(Note to self: Strings)
base/errorshow.jl
Outdated
@@ -59,6 +75,27 @@ function showerror(io::IO, ex::BoundsError) | |||
Experimental.show_error_hints(io, ex) | |||
end | |||
|
|||
Experimental.register_error_hint(BoundsError) do io, ex | |||
if ~isdefined(ex, :a) | |||
return print(io, "\nNo description of valid indices available.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO it is not useful to be told that there is no information to be told.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My thinking was that this would prompt package authors to extend this function, but you're right, this is useless.
@@ -236,6 +236,7 @@ ourselves, we can officially define it as a subtype of an [`AbstractArray`](@ref | |||
| `axes(A)` | `map(OneTo, size(A))` | Return a tuple of `AbstractUnitRange{<:Integer}` of valid indices | | |||
| `similar(A, ::Type{S}, inds)` | `similar(A, S, Base.to_shape(inds))` | Return a mutable array with the specified indices `inds` (see below) | | |||
| `similar(T::Union{Type,Function}, inds)` | `T(Base.to_shape(inds))` | Return an array similar to `T` with the specified indices `inds` (see below) | | |||
| `describe_valid_indices(io, A, i)` | | Human readable version of the sentence "Valid indices are ...", for the `BoundsError` message | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For AbstractArrays
a default fallback which shows axes
should be enough, no? Feels pretty strange that with the basic methods above you get everything from sorting to matrix multiplication working, but you have to define this extremely specific thing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is such a fallback, this is in the "optional" section.
base/array.jl
Outdated
ERROR: BoundsError: attempt to access 3-element Vector{Int64} at index [4] | ||
Valid indices are 1:3. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with the suggestion to only do something extra when indices are non-standard. But if something more is added, perhaps the default BoundsError message should instead be
ERROR: BoundsError: attempt to access 3-element Vector{Int64} at index [4] | |
Valid indices are 1:3. | |
ERROR: BoundsError: attempt to access 3-element Vector{Int64} with axes $(axes(...)) at index [4] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 for adding things into the running text, just like the existing index hints for strings:
julia> "fαb"[3]
ERROR: StringIndexError: invalid index [3], valid nearby indices [2]=>'α', [4]=>'b'
I don't see how Julia being 1 indexed has anything to do with the level of spamminess this has.
I don't think this is true and the same can be said for any error message so it isn't a good criteria to use for evaluating error messages.
In that case it can be special cased to only show something when the index is Again, in probably 99% of the cases the indices will be |
Here's a version that causes fewer messages, basically it currently only hints when
Is that better? I don't know which parts of this triage liked and didn't. This will at least help whenever you do |
I suggested a more human friendly error message in this thread on discourse. Thought I'd try it out -- does this implementation make sense to you?