# \`@propagate\_inbounds\` and \`@boundscheck\` vs \`checkbounds\`

**URL:** <https://discourse.julialang.org/t/propagate-inbounds-and-boundscheck-vs-checkbounds/7147>\
**Category:** General Usage\
**Created:** [November 18, 2017, 5:22am UTC](https://discourse.julialang.org/t/propagate-inbounds-and-boundscheck-vs-checkbounds/7147 "2017-11-18T05:22:55Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![mohamed82008](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mohamed82008/32/18171_2.png) [@mohamed82008](https://discourse.julialang.org/u/mohamed82008)\
**Post date:** [November 18, 2017, 5:22am UTC](https://discourse.julialang.org/t/propagate-inbounds-and-boundscheck-vs-checkbounds/7147/1 "2017-11-18T05:22:55Z")

</div>

`checkbounds` is intuitive, but how does it compare and work with the other 2? Pulled from the following example in JuAFEM.jl:

```julia
@propagate_inbounds function assemble!(g::AbstractVector{T}, edof::AbstractVector{Int}, ge::AbstractVector{T}) where {T}
    @boundscheck checkbounds(g, edof)
    @inbounds for i in 1:length(edof)
        g[edof[i]] += ge[i]
    end
end

```

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [November 18, 2017, 1:44pm UTC](https://discourse.julialang.org/t/propagate-inbounds-and-boundscheck-vs-checkbounds/7147/2 "2017-11-18T13:44:50Z")

</div>

`checkbounds` is a helper function and it doesn’t need to work with the other two.

The semantic of `@inbounds`, `@boundcheck` and `@propagate_inbounds` are pretty well documented.

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [November 18, 2017, 2:13pm UTC](https://discourse.julialang.org/t/propagate-inbounds-and-boundscheck-vs-checkbounds/7147/3 "2017-11-18T14:13:55Z")

</div>

I’m on a phone or I would do it myself, but a link to the relevant documentation would be helpful here.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [November 18, 2017, 3:59pm UTC](https://discourse.julialang.org/t/propagate-inbounds-and-boundscheck-vs-checkbounds/7147/4 "2017-11-18T15:59:28Z")

</div>

Did you mean [https://docs.julialang.org/en/latest/devdocs/boundscheck/](https://docs.julialang.org/en/latest/devdocs/boundscheck/) ?

---

<div class="post-metadata">

**Author:** ![mohamed82008](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mohamed82008/32/18171_2.png) [@mohamed82008](https://discourse.julialang.org/u/mohamed82008)\
**Post date:** [November 18, 2017, 8:41pm UTC](https://discourse.julialang.org/t/propagate-inbounds-and-boundscheck-vs-checkbounds/7147/5 "2017-11-18T20:41:39Z")

</div>

Note: This comment is full of mistakes, that I didn’t even bother correcting it. Please read on for the correct understanding.

So I would like to paraphrase the docs and specialize on the above example, correct me if I am wrong.

It seems that `@boundscheck`, which should ideally surround only bound checking lines, communicates with the function calling `assemble!` only if `assemble!` was inlined and the function call was in an `@inbounds` block, telling it (or the compiler really) to skip the lines in the `@boundscheck` block.

`@propagate_inbounds` looks for `@boundscheck` blocks in one deeper layer of function calls, skipping any lines in the `@boundscheck` blocks.

So it is useless to do the following:

1. Use `@propagate_inbounds` if no `@inbounds` block exists in the function. This one is pretty obvious.
2. Use `@boundscheck` block in a function when the function is not inlined and directly called in an `@inbounds` block in the caller function, or is indirectly called in an `@inbounds` block in a function (any number of function calls down the stack) decorated with `@propagate_inbounds`.

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [November 18, 2017, 8:51pm UTC](https://discourse.julialang.org/t/propagate-inbounds-and-boundscheck-vs-checkbounds/7147/6 "2017-11-18T20:51:17Z")

</div>

> [@mohamed82008](#):
>
> @propagate\_inbounds communicates with any function that assemble! calls in its @inbounds block, recursively all the way to the lowest level of the function call tree, skipping any lines in @boundscheck blocks of all the directly or indirectly called functions.

No. `@inbounds` only works with one level of `@inbounds`, `@propagate_inbounds` extends it.

This is clearly documented as

> To override the “one layer of inlining” rule, a function may be marked with @propagate\_inbounds to propagate an inbounds context (or out of bounds context) through one additional layer of inlining.

> [@mohamed82008](#):
>
> Use @propagate\_inbounds if no @inbounds block exists in the function. This one is pretty obvious.

No.

---

<div class="post-metadata">

**Author:** ![mohamed82008](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mohamed82008/32/18171_2.png) [@mohamed82008](https://discourse.julialang.org/u/mohamed82008)\
**Post date:** [November 18, 2017, 8:57pm UTC](https://discourse.julialang.org/t/propagate-inbounds-and-boundscheck-vs-checkbounds/7147/7 "2017-11-18T20:57:38Z")

</div>

> [@yuyichao](#):
>
> No. @inbounds only works with one level of @inbounds, @propagate\_inbounds extends it.

I see so only one additional layer, my bad. I will edit my post.

> [@yuyichao](#):
>
> No.

Could you elaborate? How can `@propagate_inbounds` extend `@inbounds` and yet still work without it?

One more question, the docs seem to imply that the lines in an `@bounds_check` block are only skipped if the function having that block is inlined? Does this mean that an `@inline` decorator is missing from the above example for the `@bounds_check` to be of any use?

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [November 18, 2017, 9:29pm UTC](https://discourse.julialang.org/t/propagate-inbounds-and-boundscheck-vs-checkbounds/7147/8 "2017-11-18T21:29:59Z")

</div>

> [@mohamed82008](#):
>
> How can @propagate\_inbounds extend @inbounds and yet still work without it?

`@propagate_inbounds` propagate `@inbounds` into the function. It has nothing to do with `@inbounds` in the function. `@inbounds` is also independent of anything of the function it is in.

> [@mohamed82008](#):
>
> only skipped if the function having that block is inlined

yes.

> [@mohamed82008](#):
>
> Does this mean that an @inline decorator is missing from the above example for the @bounds\_check to be of any use?

no. please read the docstring

```julia
help?> Base.@propagate_inbounds
  @propagate_inbounds

  Tells the compiler to inline a function while retaining the caller's inbounds context.

```

---

<div class="post-metadata">

**Author:** ![mohamed82008](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mohamed82008/32/18171_2.png) [@mohamed82008](https://discourse.julialang.org/u/mohamed82008)\
**Post date:** [November 18, 2017, 9:42pm UTC](https://discourse.julialang.org/t/propagate-inbounds-and-boundscheck-vs-checkbounds/7147/9 "2017-11-18T21:42:47Z")

</div>

> [@yuyichao](#):
>
> It has nothing to do with @inbounds in the function.

Oh, ok so `@propagate_inbounds` inlines the function and extends the caller function’s `@inbounds` context, it has nothing to do with the functions called by `assemble!` for example. So a simple `@inline` extends the `@inbounds` context only once. For additional extensions, `@propagate_inbounds` is necessary. So if `f1` calls `f2` in an `@inbounds` block, and `f2` calls `f3` without `@inbounds`, then inlining `f2` will extend the `@inbounds` of `f1`, but using `@propagate_inbounds` is necessary before `f3` for the `@inbounds` context of `f1` to be passed to `f3` through `f2`. A side effect of this is that `f3` will be inlined in `f2` which itself is inlined in `f1`. Alternatively, `f2` could have been decorated with `@propagate_inbounds` instead of `@inline`, as the inlining happens anyways. Is this about right?

I think this part is worth adding to the docs link.

```julia
help?> Base.@propagate_inbounds
  @propagate_inbounds

  Tells the compiler to inline a function while retaining the caller's inbounds context.

```
