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

Don't require that @inbounds depends only on local information #54270

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 5 additions & 5 deletions base/essentials.jl
Original file line number Diff line number Diff line change
Expand Up @@ -851,11 +851,11 @@ end

Using `@inbounds` may return incorrect results/crashes/corruption
for out-of-bounds indices. The user is responsible for checking it manually.
Only use `@inbounds` when it is certain from the information locally available
that all accesses are in bounds. In particular, using `1:length(A)` instead of
`eachindex(A)` in a function like the one above is _not_ safely inbounds because
the first index of `A` may not be `1` for all user defined types that subtype
`AbstractArray`.
Only use `@inbounds` when you are certain that all accesses are in bounds (as
Copy link
Contributor

Choose a reason for hiding this comment

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

you are

The original "it is" achieves better clarity. Use of "you" could be interpreted as "am I certain? yes, then let's try my luck" -- but one can be wrong.

Instead "it is" implies that a truth exists outside of oneself, and, furthermore, that due to fallibility, one should provide a proof. Whether one actually provides a proof for each @inbounds is unlikely, but if one gets in the habit of thinking that way, the probability of flippant and unsound @inbounds should greatly decrease.

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 agree with @stevengj's #54270 (comment). The crux is that there is no external truth outside of oneself. It's perfectly valid to try your luck. If you're wrong, you might get hard to trace problems, which this docstring indicates clearly.

I, for one, do use @inbounds "flippantly" and unsoundly at many points during early development, and sometimes provide proofs for usage in registered packages (e.g. https://github.com/LilithHafner/AliasTables.jl/blob/ca6eacd2c222e7e797ec446b5cf6343a733f756e/src/AliasTables.jl#L354). That whole range is allowed by the language semantic. It is the place of a style guide or code quality standard to require or encourage correctness proofs, not the place of this language.

Copy link
Contributor

Choose a reason for hiding this comment

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

Eh, it's true: the nature of @inbounds implies acceptance of potential UB. I'm reading too much into "it is" / "you are", anyway.

It is the place of a style guide or code quality standard to require or encourage correctness proofs, not the place of this language.

Requirement, ok. However, I fail to see the harm caused by active discouragement of bad practices in any programming language manual.

The crux is that there is no external truth outside of oneself.

In the metaphysical sense? Perhaps. However, in a machine, the truth value of inbounds? can be determined, albeit, sometimes with a trawling of a great number of states, other people's code, etc.


To complement the tangent: discrete sampling based on tables necessitates @inbounds for performance. This comes from direct experience; incidentally, you may be interested in reading Marsaglia's article "Fast generation of discrete random variables."

Copy link
Member Author

Choose a reason for hiding this comment

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

However, in a machine, the truth value of inbounds? can be determined, albeit, sometimes with a trawling of a great number of states, other people's code, etc.

Julia has an open world (i.e. you can always add more methods later) so it is impossible to make a universal truth determination without also trawling the future or having some alternative formalization of the language that prohibits piracy.

Copy link
Contributor

Choose a reason for hiding this comment

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

Without getting bogged down in metaphysical discussions, I think having a note/comment explaining why the @inbounds is safe next to the use is a good idea, because it provides a future reader with the same context the original author had when determining that the use was safe. As such, I also think the it is formulation is better, because it prompts a user of @inbounds to think about why their use is safe and to state that clearly to a future reader.

Rust has a similar culture around its uses of unsafe, where people put comments next to uses of unsafe to justify & document it for the future.

undefined behavior, e.g. crashes, might occur if this assertion is violated). For
example, using `1:length(A)` instead of `eachindex(A)` in a function like
the one above is _not_ safely inbounds because the first index of `A` may not
be `1` for all user defined types that subtype `AbstractArray`.
"""
macro inbounds(blk)
return Expr(:block,
Expand Down