# Rebinding local variable inside function and type stability: does it matter?

**URL:** <https://discourse.julialang.org/t/rebinding-local-variable-inside-function-and-type-stability-does-it-matter/54159>\
**Category:** Performance\
**Tags:** code\_warntype, type-stability\
**Created:** [January 29, 2021, 4:30am UTC](https://discourse.julialang.org/t/rebinding-local-variable-inside-function-and-type-stability-does-it-matter/54159 "2021-01-29T04:30:07Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Shuhua](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/shuhua/32/27618_2.png) [@Shuhua](https://discourse.julialang.org/u/Shuhua)\
**Post date:** [January 29, 2021, 4:30am UTC](https://discourse.julialang.org/t/rebinding-local-variable-inside-function-and-type-stability-does-it-matter/54159/1 "2021-01-29T04:30:07Z")

</div>

Based on my limited understanding of the documentation [here](https://docs.julialang.org/en/v1/manual/performance-tips/#man-code-warntype), _type stability_ mainly pertains to the return type. However, if I change the type of a local variable (essentially rebinding) inside a function as follows:

```julia
g(x) = x + 1.2

function ff()
    x = 1
    x = g(x)
    return x + 2.3
end

```

and `@code_warntype ` gives  
 ![Snipaste_2021-01-29_12-26-41](https://global.discourse-cdn.com/julialang/original/3X/a/a/aacbe03814617a44b427b59076a64bbdf0cb834d.png)

We see that the return type is of course stable. However, I am not sure about the followng issues.

- Does the unstable types of the variable `x` (highlighted in red) hurt performance?
- Is it recommended to use different variable names instead of reassigning in Julia?

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [January 29, 2021, 5:54am UTC](https://discourse.julialang.org/t/rebinding-local-variable-inside-function-and-type-stability-does-it-matter/54159/2 "2021-01-29T05:54:09Z")

</div>

The name `x` doesn’t have a clear type, but Julia’s SSA form has two separate internal variables to split the representation and make it type stable.

> **[Static single-assignment form](https://en.wikipedia.org/wiki/Static_single_assignment_form)**
>
> In compiler design, static single assignment form (often abbreviated as SSA form or simply SSA) is a property of an intermediate representation (IR) that requires each variable to be assigned exactly once and defined before it is used. Existing variables in the original IR are split into versions, new variables typically indicated by the original name with a subscript in textbooks, so that every definition gets its own version. In SSA form, use-def chains are explicit and each contains a single e...

---

<div class="post-metadata">

**Author:** ![Shuhua](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/shuhua/32/27618_2.png) [@Shuhua](https://discourse.julialang.org/u/Shuhua)\
**Post date:** [January 29, 2021, 6:50am UTC](https://discourse.julialang.org/t/rebinding-local-variable-inside-function-and-type-stability-does-it-matter/54159/3 "2021-01-29T06:50:02Z")

</div>

> [@ChrisRackauckas](#):
>
> Julia’s SSA form has two separate internal variables to split the representation and make it type stable.

Thanks for the explanation. I have little knowledge in compiler theory. The conclusion is that reusing variables for different types inside a function does not compromise the performance, even though the variable is apparently type unstable, right?

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [January 29, 2021, 10:23am UTC](https://discourse.julialang.org/t/rebinding-local-variable-inside-function-and-type-stability-does-it-matter/54159/4 "2021-01-29T10:23:54Z")

</div>

In that case it won’t hurt, but not doing that is one of the performance tips: [Performance Tips · The Julia Language](https://docs.julialang.org/en/v1/manual/performance-tips/#Avoid-changing-the-type-of-a-variable)

---

<div class="post-metadata">

**Author:** ![FPGro](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fpgro/32/20822_2.png) [@FPGro](https://discourse.julialang.org/u/FPGro)\
**Post date:** [January 29, 2021, 11:00am UTC](https://discourse.julialang.org/t/rebinding-local-variable-inside-function-and-type-stability-does-it-matter/54159/5 "2021-01-29T11:00:37Z")

</div>

I think that’s only true for variables that are clearly separable for the compiler. Chris here can probably tell you a bit more, but I wouldn’t change the type of a variable in a loop when both the old and the new type may be used. And there are probably more conditions where this is hard on the compiler:

```julia
julia> function assignseparately(x::Int)
       y = (x+1)^4
       z = π/y
       y = y * ℯ^z
       return y
       end
assignseparately (generic function with 1 method)

julia> assignseparately(4)
628.1495015830967

```

This is fine:

```julia
julia> @code_warntype assignseparately(3)
Variables
  #self#::Core.Const(assignseparately)
  x::Int64
  z::Float64
  y::Union{Float64, Int64}

Body::Float64
1 ─ %1 = (x + 1)::Int64
│ %2 = Core.apply_type(Base.Val, 4)::Core.Const(Val{4})
│ %3 = (%2)()::Core.Const(Val{4}())
│ (y = Base.literal_pow(Main.:^, %1, %3))
│ (z = Main.π / y::Int64)
│ %6 = y::Int64::Int64
│ %7 = (Main.ℯ ^ z)::Float64
│ (y = %6 * %7)
└── return y::Float64

```

But this is not:

```julia
julia> function assignloop(x::Int)
       y = x÷2 + 5
       z = 1
       for i in 1:x
           z += i<y ? i : i/y
       end
       z
       end
assignloop (generic function with 1 method)

julia> @code_warntype assignloop(10)
Variables
  #self#::Core.Const(assignloop)
  x::Int64
  @_3::Union{Nothing, Tuple{Int64, Int64}}
  z::Union{Float64, Int64}
  y::Int64
  i::Int64
  @_7::Union{Float64, Int64}

Body::Union{Float64, Int64}
1 ─ %1 = (x ÷ 2)::Int64
│ (y = %1 + 5)
│ (z = 1)
│ %4 = (1:x)::Core.PartialStruct(UnitRange{Int64}, Any[Core.Const(1), Int64])
│ (@_3 = Base.iterate(%4))
│ %6 = (@_3 === nothing)::Bool
│ %7 = Base.not_int(%6)::Bool
└── goto #7 if not %7
2 ┄ %9 = @_3::Tuple{Int64, Int64}::Tuple{Int64, Int64}
│ (i = Core.getfield(%9, 1))
│ %11 = Core.getfield(%9, 2)::Int64
│ %12 = z::Union{Float64, Int64}
│ %13 = (i < y)::Bool
└── goto #4 if not %13
3 ─ (@_7 = i)
└── goto #5
4 ─ (@_7 = i / y)
5 ┄ %18 = @_7::Union{Float64, Int64}
│ (z = %12 + %18)
│ (@_3 = Base.iterate(%4, %11))
│ %21 = (@_3 === nothing)::Bool
│ %22 = Base.not_int(%21)::Bool
└── goto #7 if not %22
6 ─ goto #2
7 ┄ return z

```

Okay you cant see much with the discourse highlighting, but it’s not stable any more `Body::Union{Float64, Int64}`. This is of course artificial, but there are more intricate examples where this can go unnoticed easily. Plus, reading the code is much easier when you don’t reuse names for different things in different places.

---

<div class="post-metadata">

**Author:** ![Shuhua](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/shuhua/32/27618_2.png) [@Shuhua](https://discourse.julialang.org/u/Shuhua)\
**Post date:** [January 29, 2021, 1:56pm UTC](https://discourse.julialang.org/t/rebinding-local-variable-inside-function-and-type-stability-does-it-matter/54159/6 "2021-01-29T13:56:31Z")

</div>

Thanks @FPGro. As stated above:

> [@lmiq](#):
>
> In that case it won’t hurt, but not doing that is one of the performance tips

There are scenarios where reusing a variable name is handy. For example, a function has an argument `data`, and in its first line, we perform `data = preprocess(data)` and we will deal with the preprocessed `data` in the remaining part. Here, the new `data` may have a different type. Nonetheless, the new type of `data` is fixed hereafter. Alternatively, it seems verbose to define `data_pp = preprocess(data)`.

---

<div class="post-metadata">

**Author:** ![FPGro](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fpgro/32/20822_2.png) [@FPGro](https://discourse.julialang.org/u/FPGro)\
**Post date:** [January 29, 2021, 2:18pm UTC](https://discourse.julialang.org/t/rebinding-local-variable-inside-function-and-type-stability-does-it-matter/54159/7 "2021-01-29T14:18:27Z")

</div>

> [@Shuhua](#):
>
> we perform `data = preprocess(data)` and we will deal with the preprocessed `data` in the remaining part

True, this looks harmless enough, and it is fine for the compiler. Just make sure that `preprocess(data)` is type stable. If it’s not, you may “inherit” the instability from that function, but that is of course independent of the naming.

---

<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:** [January 30, 2021, 3:15pm UTC](https://discourse.julialang.org/t/rebinding-local-variable-inside-function-and-type-stability-does-it-matter/54159/8 "2021-01-30T15:15:30Z")

</div>

> [@Shuhua](#):
>
> There are scenarios where reusing a variable name is handy. For example, a function has an argument `data` , and in its first line, we perform `data = preprocess(data)` and we will deal with the preprocessed `data` in the remaining part.

FWIW, I think this is bad style. I would do either

```julia
preprocessed_data = preprocess(data)

```

or if `preprocess` results in a different type,

```julia
function f(data::PreprocessedData)
    ...
end

f(data::RawData) = f(preprocess(data))

```

---

<div class="post-metadata">

**Author:** ![Shuhua](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/shuhua/32/27618_2.png) [@Shuhua](https://discourse.julialang.org/u/Shuhua)\
**Post date:** [January 30, 2021, 4:08pm UTC](https://discourse.julialang.org/t/rebinding-local-variable-inside-function-and-type-stability-does-it-matter/54159/9 "2021-01-30T16:08:50Z")

</div>

> [@Tamas\_Papp](#):
>
> FWIW, I think this is bad style. I would do either
> 
> ```julia
> preprocessed_data = preprocess(data)
> 
> ```

Thanks. I agree with you now. I will follow this recommended style.
