# How is \`x::T\` lowered? (the actual post)

**URL:** <https://discourse.julialang.org/t/how-is-x-t-lowered-the-actual-post/85590>\
**Category:** Internals & Design\
**Created:** [August 10, 2022, 4:25pm UTC](https://discourse.julialang.org/t/how-is-x-t-lowered-the-actual-post/85590 "2022-08-10T16:25:56Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![cscherrer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cscherrer/32/7631_2.png) [@cscherrer](https://discourse.julialang.org/u/cscherrer)\
**Post date:** [August 10, 2022, 4:25pm UTC](https://discourse.julialang.org/t/how-is-x-t-lowered-the-actual-post/85590/1 "2022-08-10T16:25:56Z")

</div>

I’d like to understand what the compiler does with code like

```julia
function f(x)
    local y :: typeof(x)
    y = x
end

```

The docstring for `typeassert` says “The syntax `x::type` calls this function.”. But this isn’t just a simple substitution, since `y` isn’t defined until later. You can see this in the lowered code, which is entirely rearranged:

```julia
julia> @code_lowered f(3)
CodeInfo(
1 ─ %1 = x
│ %2 = Main.typeof(x)
│ %3 = Base.convert(%2, %1)
│ y = Core.typeassert(%3, %2)
└── return %1
)

```

So how does this lowering actually happen?

For context, I’m trying to be careful about this sort of thing in Tilde, where it can be important for type stability. It would also be very useful for GeneralizedGenerated.jl to handle this idiom. Currently it can’t (see [https://github.com/JuliaStaging/GeneralizedGenerated.jl/issues/71](https://github.com/JuliaStaging/GeneralizedGenerated.jl/issues/71)).

cc @thautwarm

---

<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:** [August 10, 2022, 4:49pm UTC](https://discourse.julialang.org/t/how-is-x-t-lowered-the-actual-post/85590/2 "2022-08-10T16:49:38Z")

</div>

This is not a type assertion, it’s a variable declaration. As explained [in the manual](https://docs.julialang.org/en/v1/manual/types/#Type-Declarations):

> When appended to a variable on the left-hand side of an assignment, or as part of a `local` declaration, the `::` operator means something a bit different: it declares the variable to always have the specified type, like a type declaration in a statically-typed language such as C. Every value assigned to the variable will be converted to the declared type using `convert`.

---

<div class="post-metadata">

**Author:** ![cscherrer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cscherrer/32/7631_2.png) [@cscherrer](https://discourse.julialang.org/u/cscherrer)\
**Post date:** [August 10, 2022, 5:22pm UTC](https://discourse.julialang.org/t/how-is-x-t-lowered-the-actual-post/85590/3 "2022-08-10T17:22:02Z")

</div>

Right, but it’s implemented using `typeassert`, at least in this case.

Anyway, what I’m more curious about is the reordering. In the original code, the declaration comes first, followed by an assignment. I always thought lowered was very conservative in the rewrites it does, and I’m surprised to see things being reordered like this.

I know lowered rewrites `for` loops, and there are nice overviews like [this](https://juliadebug.github.io/JuliaInterpreter.jl/stable/ast/) describing how this works. I was just hoping for something similar to better understand what happens with declarations.

---

<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:** [August 10, 2022, 10:55pm UTC](https://discourse.julialang.org/t/how-is-x-t-lowered-the-actual-post/85590/4 "2022-08-10T22:55:38Z")

</div>

> [@cscherrer](#):
>
> Right, but it’s implemented using `typeassert`, at least in this case.

It’s implemented by calling `y = convert(T, ...)::T` _every time_ you assign to `y` in the lowered code. The reason for the `::T` assertion is to ensure that the compiler gets the correct type of `y`, in case the `convert` call is type-unstable (e.g. a buggy `convert` implementation). In the usual case where the `convert` call is type-stable and inferred, the `::T` assertion is optimized out.

This is clearer if you do multiple assignments to the typed local variable in your function:

```julia
julia> function f(x)
           local y::Float64
           y = x
           y = y + x
       end
f (generic function with 1 method)

julia> @code_lowered f(3)
CodeInfo(
1 ─ %1 = x
│ %2 = Base.convert(Main.Float64, %1)
│ y = Core.typeassert(%2, Main.Float64)
│ %4 = y + x
│ %5 = Base.convert(Main.Float64, %4)
│ y = Core.typeassert(%5, Main.Float64)
└── return %4
)

```

Note that all of the type assertions are eventually optimized away:

```julia
julia> @code_llvm debuginfo=:none f(3)
define double @julia_f_362(i64 signext %0) #0 {
top:
  %1 = sitofp i64 %0 to double
  %2 = fadd double %1, %1
  ret double %2
}

```

---

<div class="post-metadata">

**Author:** ![cscherrer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cscherrer/32/7631_2.png) [@cscherrer](https://discourse.julialang.org/u/cscherrer)\
**Post date:** [August 10, 2022, 11:52pm UTC](https://discourse.julialang.org/t/how-is-x-t-lowered-the-actual-post/85590/5 "2022-08-10T23:52:28Z")

</div>

I see, that makes a lot of sense now. Thanks!
