Easier-to-read syntax for associated type projections

Has there ever been serious discussion around introducing a simpler syntax for at least the majority of cases for associated-type projections? (I've tried some initial searching here but came up empty; I also recognize discussions may be on GitHub, Zulip, or elsewhere).

The Chalk book has a pretty good introduction to associated type projections, for reference: Type equality and unification

The particular thing I'm thinking about is that right now associated types can either be specified with the short syntax MyType::MyAssociatedType or, if that's insufficient, the much more verbose <MyType as SomeTrait>::MyAssociatedType.

Readability problems arise when you end up with multiple layers of these associated type projections, which causes increasing nesting of as-clauses and path segments for each successive associated type.

If, for example, you need to specify a trait bound on some multiply-chained associated-type projection, you end up with something unwieldy like (copied from the libp2p crate):

<<<THandler as IntoProtocolsHandler>
    ::Handler as ProtocolsHandler>
    ::OutboundProtocol as OutboundUpgrade<SubstreamRef<Arc<TMuxer>>>>
    ::Error : Send

One of the key challenges of this syntax is the nesting of < and > brackets to contain the Type as Trait clauses. This makes it difficult to read this syntax left-to-right. I think in general this lack of readability is a barrier to users and writers of Rust code with more complex type bounds.

I have not seriously explored the likely edge cases which may arise in alternate syntax, and it may be that there is not a perfect design for a left-to-right-readable syntax for associated type projections. That said, it seems plausible to me that there could be at least a majority-case-covering syntax.

The following is an idea of one possible shape of that syntax, proposed only to show what I mean by "left-to-right readable." I have no particular preference for any specific symbols.

// The above code, rewritten to use some imagined shorter
// syntax for associated type projections.
THandler/IntoProtocolsHandler
    ::Handler/ProtocolsHandler
    ::OutboundProtocol/OutboundUpgrade<SubstreamRef<Arc<TMuxer>>>
    ::Error: Send

Happy to hear if I've missed prior art here, prior discussions, or any thoughts people may have.

2 Likes

I wonder if allowing people to write something like

Handler = <THandler as IntoProtocolsHandler>::Handler,
Protocol = <Handler as ProtocolsHandler>::OutboundProtocol,
Upgrade = OutboundUpgrade<SubstreamRef<Arc<TMuxer>>>,
Error = <Protocol as Upgrade>::Error,
Error: Send

Today the above isn't representable (but can be approximated with type or type parameters, sometimes).

4 Likes

What is newly writable in 1.79, although still a bit annoying to nest like this, is:

THandler: IntoProtocolsHandler<
    Handler: ProtocolsHandler<
        OutboundProtocol: OutboundUpgrade<
            SubstreamRef<Arc<Mixer>>,
            Error: Send,
        >,
    >,
>,

The <> still get nested, but in a more left-to-right manner this way.

5 Likes

Weird idea - maybe it could have a similar syntax to what Odin uses for constant declarations, where you specify the type/trait inside the double colon (w/ bracketing to make it unambiguous?):

THandler:<IntoProtocolsHandler>:
    Handler:<ProtocolsHandler>:
    OutboundProtocol:<OutboundUpgrade<SubstreamRef<Arc<TMuxer>>>>:
    Error: Send

and then the normal double colon would just mean that the context is inferred

1 Like

I think this would be really nice for functions.

fn harvest<T>(farm: T) -> Crop
where
    T: Farm,
    Crop = <T::Field as Arable>::Crop,
{
    // ..
}

The signature provides a big picture idea of what the function does and the where clause holds any advanced details directly below, it's great

2 Likes

Ah this is actually fairly nice! The <> bunching up at the end is less of a concern to me, personally. Maybe this isn't so necessary to change given the syntax here.

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.