# Branch on whether a value is known to the compiler

**URL:** <https://discourse.julialang.org/t/branch-on-whether-a-value-is-known-to-the-compiler/34850>\
**Category:** Internals & Design\
**Tags:** proposal\
**Created:** [February 19, 2020, 3:21pm UTC](https://discourse.julialang.org/t/branch-on-whether-a-value-is-known-to-the-compiler/34850 "2020-02-19T15:21:10Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Per](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/per/32/10387_2.png) [@Per](https://discourse.julialang.org/u/Per)\
**Post date:** [February 19, 2020, 3:21pm UTC](https://discourse.julialang.org/t/branch-on-whether-a-value-is-known-to-the-compiler/34850/1 "2020-02-19T15:21:10Z")

</div>

Here’s something that I’ve been thinking about: What if there was a way to write code that works differently depending on whether some value is known to the compiler?

As an example, let’s say I could write:

```julia
@inline function ^(x, p::Integer)
    if @known p
       literal_pow(^, x, Val(p))
    else
       power_by_squaring(x, p)
    end
end

```

where `@known` would be a special macro that would tell the compiler to first do some amount of inlining and constant-folding, then check whether the value of `p` is a constant and branch as a function of that. So `Val(p)` would only be used when it does not result in dynamic dispatch.

Just as with `if @generated`, the programmer would be responsible for ensuring that both branches do the same thing. The compiler would always be free skip constant propagation and just take the `else` branch.

Today, the parser does something similar to the above, but only for `^` and only for literal exponents. (For example `(-1)^(-1)` does not return the same thing as `const p = -1; (-1)^p` does.) Instead of special-casing the `^` operator in the parser, I think it would make sense to have a built-in feature in the language.

One example of where this feature would be useful is [#31138](https://github.com/JuliaLang/julia/pull/31138).  
That PR deals with type-stable handling of code like `t[2:end]` where `t` is a tuple. What makes this hard is the fact that the `getindex` function gets a tuple and a range, but it does not know that the range is created from the literal `2` and the compile-time constant `lastindex(t)`. With a set of if-statements, like `if r.start == 2 && r.stop == length(t)` it is possible to handle some common cases. But it’s not possible to cover every possible case with a finite set of if-statements. (For example, even with that PR, `t[2:end-1]` would not be type-stable.) Being able to run different code depending on whether `r.start` and `r.end` are known to the compiler would make it trivial to handle all cases.

I’ve tried to solve some of these problems with the StaticNumbers package. For example, if `t` is a tuple, then `using StaticNumbers; @stat t[2:end-1]` will extract a sub-tuple in a type-stable way. But I’ve come to the conclusion that this really needs to be done at the compiler level if it is to be done right.

---

<div class="post-metadata">

**Author:** ![Zach\_Christensen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zach_christensen/32/7220_2.png) [@Zach\_Christensen](https://discourse.julialang.org/u/Zach_Christensen)\
**Post date:** [February 19, 2020, 3:29pm UTC](https://discourse.julialang.org/t/branch-on-whether-a-value-is-known-to-the-compiler/34850/2 "2020-02-19T15:29:14Z")

</div>

I like ideas like this where I might be able to interact with the compiler in a very simple way. Unfortunately, I have no idea how complex these things are under the hood

---

<div class="post-metadata">

**Author:** ![Elrod](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/elrod/32/22461_2.png) [@Elrod](https://discourse.julialang.org/u/Elrod)\
**Post date:** [February 19, 2020, 3:31pm UTC](https://discourse.julialang.org/t/branch-on-whether-a-value-is-known-to-the-compiler/34850/3 "2020-02-19T15:31:58Z")

</div>

I would like such a feature.  
But because what is known to the compiler is implementation-dependent (e.g., changes to const prop will change whether or not `p` is known), it would also require the explicit promise that you are not actually changing the behavior in an observable way. Otherwise, your code is likely to break from one version to another.

---

<div class="post-metadata">

**Author:** ![Per](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/per/32/10387_2.png) [@Per](https://discourse.julialang.org/u/Per)\
**Post date:** [February 19, 2020, 4:29pm UTC](https://discourse.julialang.org/t/branch-on-whether-a-value-is-known-to-the-compiler/34850/4 "2020-02-19T16:29:05Z")

</div>

Exactly. Therefore there must exist a documented way to prevent constant propagation, so that unit tests can run through both branches. For example, one might declare that the value stored in a `Ref` is never considered a constant, and then a unit test could look like:

```julia
@test (-1)^(-1) == (-1)^Ref(-1)[]

```

---

<div class="post-metadata">

**Author:** ![Per](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/per/32/10387_2.png) [@Per](https://discourse.julialang.org/u/Per)\
**Post date:** [February 20, 2020, 8:09am UTC](https://discourse.julialang.org/t/branch-on-whether-a-value-is-known-to-the-compiler/34850/5 "2020-02-20T08:09:49Z")

</div>

Another thing that one could to with this: Inside a `@generated` function, the `if @known x` branch could hold the actual value of `x` (while the `else` branch would hold the type as usual).

---

<div class="post-metadata">

**Author:** ![Per](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/per/32/10387_2.png) [@Per](https://discourse.julialang.org/u/Per)\
**Post date:** [February 25, 2020, 9:06am UTC](https://discourse.julialang.org/t/branch-on-whether-a-value-is-known-to-the-compiler/34850/6 "2020-02-25T09:06:41Z")

</div>

The `@known` magic macro could also be used to get “traits” in a very straightforward manner. For example:

```julia
if @known(issymmetric(x)) && issymmetric(x)

```

This would detect if `typeof(x)` is known at compile time and is in one of `Symmetric`, `Hermitian{<:Real}`, `Diagonal`, `UniformScaling` or `Number`, and it would also detect any symmetric user-defined types (as long as they have a method `issymmetric(::MyType) = true`) but it would never do dynamic dispatch or evaluate a slow `issymetric` method at runtime.

---

<div class="post-metadata">

**Author:** ![user664303](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/user664303/32/37843_2.png) [@user664303](https://discourse.julialang.org/u/user664303)\
**Post date:** [June 15, 2023, 11:00am UTC](https://discourse.julialang.org/t/branch-on-whether-a-value-is-known-to-the-compiler/34850/8 "2023-06-15T11:00:13Z")

</div>

I’ve submitted a [feature request](https://github.com/JuliaLang/julia/issues/50176) for this.
