# Conversion in typed globals (Julia 1.8)

**URL:** <https://discourse.julialang.org/t/conversion-in-typed-globals-julia-1-8/85926>\
**Category:** General Usage\
**Created:** [August 18, 2022, 1:37pm UTC](https://discourse.julialang.org/t/conversion-in-typed-globals-julia-1-8/85926 "2022-08-18T13:37:49Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![aerdely](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aerdely/32/37506_2.png) [@aerdely](https://discourse.julialang.org/u/aerdely)\
**Post date:** [August 18, 2022, 1:37pm UTC](https://discourse.julialang.org/t/conversion-in-typed-globals-julia-1-8/85926/1 "2022-08-18T13:37:49Z")

</div>

I just want to understand this new feature in Julia 1.8

```julia
f(x::Int64) = x^2 + 1
f(3.0 + 0.0im) # ERROR: no method matching f(::ComplexF64), as expected
# But:
x::Int64 = 3.0 + 0.0im # no problem, conversion applied!

```

If I specify a global variable to be of a certain type, I was expecting that to be strict as with methods in functions, but surely I am missing something, any help just to understand will be appreciated.

---

<div class="post-metadata">

**Author:** ![digital\_carver](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/digital_carver/32/33818_2.png) [@digital\_carver](https://discourse.julialang.org/u/digital_carver)\
**Post date:** [August 18, 2022, 1:49pm UTC](https://discourse.julialang.org/t/conversion-in-typed-globals-julia-1-8/85926/2 "2022-08-18T13:49:01Z")

</div>

In the [Type declarations section of the manual](https://docs.julialang.org/en/v1/manual/types/#Type-Declarations), it says:

> When appended to a variable on the left-hand side of an assignment, or as part of a `local` declaration, the `::` operator […] 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`](https://docs.julialang.org/en/v1/base/base/#Base.convert)

For eg.,

```julia
 julia> let 
               local x::Int = 5.0
               @show x
           end
x = 5

```

The same behaviour is extended to the global type declarations with 1.8, which seems reasonable and consistent.

(Btw, it seems this section of the manual needs an update, since it also says:

> Currently, type declarations cannot be used in global scope

and doesn’t mention typed globals anywhere.)

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [August 18, 2022, 1:54pm UTC](https://discourse.julialang.org/t/conversion-in-typed-globals-julia-1-8/85926/3 "2022-08-18T13:54:57Z")

</div>

> [@aerdely](#):
>
> If I specify a global variable to be of a certain type, I was expecting that to be strict as with methods in functions, but surely I am missing something, any help just to understand will be appreciated.

This was an intentional change:

> <https://github.com/JuliaLang/julia/pull/43671>
>
> This is an initial proposal for supporting typed globals based on #43455.
> The s…yntax for this is either \`global x::T\` or just doing \`x::T = 1\` in
> global scope. It is even supported to add these annotations to globals
> from inside functions. ~~The type declaration will then be applied when
> the method is defined and inside the function body conversion to the
> specified type will happen automatically, similar to type annotations
> for local variables.~~
> 
> ~~This conversion will not be applied if the assignment is not done inside
> the same scope of the type annotation however. This could potentially be
> supported as well, but the problem is that this would mean any
> assignment to a global variable - typed or not - would need to go
> through a call to \`convert\` first, since lowering can't know if a given
> binding already has a type annotation. This probably wouldn't be a good
> thing for latency and sysimage size and would add an invalidation risk.~~
> 
> Any assignment to a global now adds a conversion step and a type
> assertion, similar to how type annotations work inside local scopes.
> 
> It is allowed to refine a type annotation, but there will be a warning.
> Widening the type or changing it to any other type that is not a subtype
> of the previous one is an error, since that could cause cached compiled
> code to become invalid.
> 
> replaces #43455
> closes #964

To be clear, it is still strict, in the sense that the conversion will only succeed if it’s actually possible to `convert` without loss of information:

```julia
julia> x::Int = 3 + 1im
ERROR: InexactError: Int64(3 + 1im)
Stacktrace:
 [1] Real
   @ ./complex.jl:44 [inlined]
 [2] convert(#unused#::Type{Int64}, x::Complex{Int64})
   @ Base ./number.jl:7
 [3] top-level scope
   @ REPL[2]:1

```

---

<div class="post-metadata">

**Author:** ![digital\_carver](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/digital_carver/32/33818_2.png) [@digital\_carver](https://discourse.julialang.org/u/digital_carver)\
**Post date:** [August 18, 2022, 1:59pm UTC](https://discourse.julialang.org/t/conversion-in-typed-globals-julia-1-8/85926/4 "2022-08-18T13:59:58Z")

</div>

With functions, the strictness comes from method specialization i.e. Julia creates code specific for the particular types in the signature. `convert`ing arguments automatically would be incompatible with Julia’s dispatch paradigm.

Julia doesn’t intend to be a strictly typed language, so it enforces such strictness only when it has to.

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [August 18, 2022, 2:01pm UTC](https://discourse.julialang.org/t/conversion-in-typed-globals-julia-1-8/85926/5 "2022-08-18T14:01:28Z")

</div>

Also, this type assertion is as strict as other assertions, e.g. like return type assertions:

```julia
julia> foo()::Int = rand(Int) + 0im
foo (generic function with 1 method)

julia> foo()
-3249805689127843005

julia> foo()::Int = rand(Complex{Int})
foo (generic function with 1 method)

julia> foo()
ERROR: InexactError: Int64(4054552448232780990 + 7575752085304089316im)
Stacktrace:
 [1] Real
   @ ./complex.jl:44 [inlined]
 [2] convert
   @ ./number.jl:7 [inlined]
 [3] foo()
   @ Main ./REPL[3]:1
 [4] top-level scope
   @ REPL[4]:1

```

Type annotations in _signatures_ are _not_ type assertions - their use is for dispatch, _never_ type conversions.
