Summary

Change the precedence of + (object bounds) in type grammar so that it is similar to the precedence in the expression grammars.

Motivation

Currently + in types has a much higher precedence than it does in expressions. This means that for example one can write a type like the following:

&Object+Send

Whereas if that were an expression, parentheses would be required:

&(Object+Send)

Besides being confusing in its own right, this loose approach with regard to precedence yields ambiguities with unboxed closure bounds:

fn foo<F>(f: F) where F: FnOnce(&int) -> &Object + Send { }

In this example, it is unclear whether F returns an object which is Send, or whether F itself is Send.

Detailed design

This RFC proposes that the precedence of + be made lower than unary type operators. In addition, the grammar is segregated such that in “open-ended” contexts (e.g., after ->), parentheses are required to use a +, whereas in others (e.g., inside <>), parentheses are not. Here are some examples:

// Before After Note // ~~~~~~ ~~~~~ ~~~~ &Object+Send &(Object+Send) &'a Object+'a &'a (Object+'a) Box<Object+Send> Box<Object+Send> foo::<Object+Send,int>(...) foo::<Object+Send,int>(...) Fn() -> Object+Send Fn() -> (Object+Send) // (*) Fn() -> &Object+Send Fn() -> &(Object+Send) // (*) Must yield a type error, as return type must be `Sized`.

More fully, the type grammar is as follows (EBNF notation):

TYPE = PATH | '&' [LIFETIME] TYPE | '&' [LIFETIME] 'mut' TYPE | '*' 'const' TYPE | '*' 'mut' TYPE | ... | '(' SUM ')' SUM = TYPE { '+' TYPE } PATH = IDS '<' SUM { ',' SUM } '>' | IDS '(' SUM { ',' SUM } ')' '->' TYPE IDS = ['::'] ID { '::' ID }

Where clauses would use the following grammar:

WHERE_CLAUSE = PATH { '+' PATH }

One property of this grammar is that the TYPE nonterminal does not require a terminator as it has no “open-ended” expansions. SUM, in contrast, can be extended any number of times via the + token. Hence is why SUM must be enclosed in parens to make it into a TYPE.

Drawbacks

Common types like &'a Foo+'a become slightly longer (&'a (Foo+'a)).

Alternatives

We could live with the inconsistency between the type/expression grammars and disambiguate where clauses in an ad-hoc way.

Unresolved questions

None.