Assignment form, where syntax, and a return type

I want to use assignment form and where syntax while specifying the return type. I can’t. Why not? (Presumably I’ve misunderstood what some syntax means.)

To be concrete, here are a few function definitions that compile:

function f(::T)::Nothing where {T} nothing end
f(::T) where {T} = nothing
f()::Nothing = nothing

Here’s one that doesn’t:

f(::T)::Nothing where {T} = nothing

The first example above uses where syntax and has a return type. The second uses assignment form and where syntax. The third uses assignment form and has a return type. Any two, I can do. All three, I can’t. What am I missing?

I feel like I should be able to find this by searching, but I haven’t figured out what to search; apologies.

(ETA I’m on 1.9.2 if that’s relevant… but surely not.)

I don’t think there’s a good reason besides the fact that the parser doesn’t know how to parse it.

1 Like

Ah. So… I didn’t just miss an obvious way to do this?

Do you know if this is something which is actually hard to support parsing? Or is it in some sense an omission for which I should post a bug on github?

Reading that, I’m guessing (f(::T)::Nothing) where {T} = nothing works but I’m not sure

2 Likes

@Benny thanks! That’s exactly what I wanted to see.

And for any future readers, this works (tested) if you need it:

(f(::T)::Nothing) where {T} = nothing

Lastly (linked from the github) here’s an old discourse discussion on the topic, which makes clear what’s going on: Which of `::` and `where` should take precedence?

My question is if the issue is Nothing where {T} appearing like a type of f(::T) to the parser, why isn’t it a problem for function f(::T)? Ignoring the function-end parts, it has almost the same form, just differing by =.

function f(::T)::Nothing where {T}   nothing end
         f(::T)::Nothing where {T} = nothing

My understanding (bear in mind I know little) is that where serves multiple purposes syntactically, and in the function f(::T) case the where really is part of the function syntax. So precedence (of where vs ::) doesn’t make any difference.

Ok I found the key quote in one of the duplicate issues #31560:

This is a difficult parser corner case. I’ve wrestled with it, but there is no straightforward solution. The problem is that generally the right way to parse f(x) :: A where B is as f(x) :: (A where B) because where makes types and the right side of :: has to be a type. For 1-line function definitions only though, we want (f(x) :: A) where B , but we don’t know it’s a function definition until we see the following = , and by then it’s too late. So you need to write function (which I think is more readable for such elaborate definitions anyway), or parenthesize the f(x) :: A part.

Basically function tips off the parser soon enough to treat the where clause properly, but the = only shows up after the where clause when it’s too late. Now I have a little bit more clarity to this old gripe I had, though I still don’t know the issues with the 2 anonymous forms. I at least would like the anonymous function block to work as well as the named one if it were possible without breaking changes.

3 Likes