# Simple infinite loops not looping?

**URL:** <https://discourse.julialang.org/t/simple-infinite-loops-not-looping/62424>\
**Category:** New to Julia\
**Tags:** loops\
**Created:** [June 5, 2021, 11:06am UTC](https://discourse.julialang.org/t/simple-infinite-loops-not-looping/62424 "2021-06-05T11:06:04Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![MarcMush](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/marcmush/32/18006_2.png) [@MarcMush](https://discourse.julialang.org/u/MarcMush)\
**Post date:** [June 5, 2021, 11:06am UTC](https://discourse.julialang.org/t/simple-infinite-loops-not-looping/62424/1 "2021-06-05T11:06:04Z")

</div>

In some cases, a very simple infinite while loop doesn’t loop inifinitly, I guess when the compiler (?) detects the loop is doing nothing and can never escape. Sure, I don’t see any scenario where this could be a problem, but I would like to understand why:

```julia
f(x) = while true end
f(1) # loops infinitely like expected

f(x) = while x end
f(true) # isn't stuck in the loop, exits immediatly

```

as soon as there’s something in the loop, or the condition accesses a global variable, this of course doesn’t happen

---

<div class="post-metadata">

**Author:** ![MarcMush](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/marcmush/32/18006_2.png) [@MarcMush](https://discourse.julialang.org/u/MarcMush)\
**Post date:** [June 5, 2021, 11:18am UTC](https://discourse.julialang.org/t/simple-infinite-loops-not-looping/62424/2 "2021-06-05T11:18:28Z")

</div>

more oddities:

```julia
f(x) = while x<1 end
f(0)

```

loops forever in Julia 1.0.5 but not in more modern versions (I tested 1.3.0, 1.4.1, 1.5.2, 1.6.1)

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [June 5, 2021, 12:13pm UTC](https://discourse.julialang.org/t/simple-infinite-loops-not-looping/62424/3 "2021-06-05T12:13:17Z")

</div>

> [@MarcMush](#):
>
> ```julia
> f(x) = while x end
> f(true) # isn't stuck in the loop, exits immediatly
> 
> ```

Yes, it looks like LLVM optimizes away the loop:

```julia
julia> @code_llvm f(true)
; @ REPL[3]:1 within `f'
define void @julia_f_169(i8 zeroext %0) {
top:
  ret void
}

```

This gave an infinite loop in Julia 0.4 and 0.5, but not in 0.6.

Apparently, LLVM sometimes assumes that loops with no side effects terminate—because failure to terminate is undefined behavior in C++, the compiler thinks it is allowed to do what it wants: [[llvm-dev] Infinite loops with no side effects](https://lists.llvm.org/pipermail/llvm-dev/2017-October/118558.html) … supposedly it will be [fixed in LLVM 12](https://bugs.llvm.org/show_bug.cgi?id=965).

---

<div class="post-metadata">

**Author:** ![simeonschaub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simeonschaub/32/216566_2.png) [@simeonschaub](https://discourse.julialang.org/u/simeonschaub)\
**Post date:** [June 5, 2021, 12:20pm UTC](https://discourse.julialang.org/t/simple-infinite-loops-not-looping/62424/4 "2021-06-05T12:20:24Z")

</div>

There is actually an open issue about this:

> <https://github.com/JuliaLang/julia/issues/40009>
>
> Our longstanding policy on forward progress guarantees has basically been that
> …we expose the LLVM behavior and follow the C/C++ world by considering infinite
> loops to be undefined behavior, leading to behavior like:
> \`\`\`
> julia\> f(x) = x ? true : while true; end
> f (generic function with 1 method)
> 
> julia\> f(true)
> true
> 
> julia\> f(false)
> true
> \`\`\`
> 
> This might not seem to bad, but it can lead to unsoundness and security vulnerabilities ("nice error check you have there, would be a shame if somebody were to see the UB before it")
> \`\`\`
> julia\> @noinline function my\_checkbounds(Alen::Int, i::Int)
> if i \< 0 || i \> Alen
> while true; end # A bad error path, maybe inlined from somewhere
> return false
> end
> return true
> end
> my\_checkbounds (generic function with 2 methods)
> 
> julia\> function my\_getindex(A::Vector{Int}, i::Int)
> my\_checkbounds(length(A), i) || error("Out of bounds!")
> @inbounds A\[i\]
> end
> my\_getindex (generic function with 1 method)
> 
> julia\> my\_getindex(Int\[1\], 100000000)
> 
> signal (11): Segmentation fault
> \`\`\`
> 
> For this reason, more modern languages tend to not make forward progress assumptions. The Rust folks in particular took this quite seriously and recently changed LLVM to require the \`mustprogress\` attribute in order to top into forward progress guarantees (https://reviews.llvm.org/D85393). We should carefully chose what to do here. Since we don't set the new LLVM attribute, LLVM actually no longer makes these forward progress assumptions on our code. However, we do still make such assumptions in our own inference code.
> 
> Now that LLVM is fixed, my preference would be to follow Rust here and stop making any forward progress assumptions.
