# 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 =#
#= REPL: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`