# Which of `::` and `where` should take precedence?

Currently (Julia v1.7), `where` takes precedence over `::`. For example:

``````julia> :(f(x::T where T <: Integer))
:(f(x::(T where T <: Integer)))
``````

However, this means that the return type annotation will not play nice with parametric methods:

``````julia> f(x::T)::Int where T<:Integer = x
ERROR: UndefVarError: T not defined
``````

because the parametric definition got bundled with `Int` instead:

``````julia> :(f(x::T)::Int where T<:Integer)
:(f(x::T)::(Int where T <: Integer))
``````

The workaround is to do either of:

``````julia> (f(x::T)::Int) where T<:Integer = x

julia> function (f(x::T)::Int) where T<:Integer
return x
end
``````

which looks like code-smellâ€¦

As such, I would like to discuss the possibility of having `::` take precedence over `where` instead. This would give us the following result:

``````julia> :(f(x::T where T <: Integer))
:(f((x::T) where T <: Integer))

julia> :(f(x::T)::Int where T<:Integer)
:((f(x::T)::Int) where T <: Integer)
``````

and so the outer parametric definition correctly tag the function instead of the return type. This way we can go with the cleaner syntax of:

``````julia> f(x::T)::Int where T<:Integer = x

julia> function f(x::T)::Int where T<:Integer
return x
end
``````

or if we so willed it:

``````julia> function rand_integer_type()::(T where T<:Integer)
...
end
``````

Not sure whether thereâ€™s any issue that arises due to this change, but since `f(x::T) where T<:Integer = x` works and:

``````julia> :(f(x::T) where T<:Integer)
:(f(x::T) where T <: Integer)
``````

I would believe that the parametric information can reach `f`.

Would like to seek our opinion on this please

3 Likes

Wow how did you reach the exact issue so fast >_< I hope I have better skill when it comes to searching the various Julia resourcesâ€¦

Notice that the second example already works as is. Itâ€™s only in â€śshort formâ€ť definitions of functions where the issue arises.

Ah thatâ€™s true, thanks for pointing out. Indeed:

``````julia> :(function f(x::T)::Int where T<:Integer
return x
end)

:(function (f(x::T)::Int) where T <: Integer
#= REPL[1]:1 =#
#= REPL[1]:2 =#
return x
end)
``````

That looks like a hack to me though, i.e. I canâ€™t determine the precedent just by looking at the local code of `A::B where C`â€¦