To be absolutely clear, erroring at declaring another local variable of the same name does not involve the annotations at all:
julia> function foo(x)
local x
end
ERROR: syntax: local variable name "x" conflicts with an argument
It’s very clearly documented that argument annotations serve multiple dispatch. Nowhere does it say that it restricts the type of instances assigned to a variable. I would argue that would be needlessly restrictive. Say you have a function foo that takes in either a x::Int or x::Float64, and x could switch types in the body x = bar()::Union{Int, Float64}. However, you need to dispatch to separate methods depending on what type the input x is. If the argument annotation restricted x’s type, it’s impossible to pull this off.
I’m prototyping a macro to get rid of the conversions here:
julia> @noconvert function foo(x::Number)
let x::Int = x
x
end
end
foo (generic function with 2 methods)
julia> foo(3)
3
julia> foo(3.0)
ERROR: TypeError: in typeassert, expected Int64, got a value of type Float64
julia> foo(3.5)
ERROR: TypeError: in typeassert, expected Int64, got a value of type Float64