Skip to main content

write_dot_receiver

Function write_dot_receiver 

Source
fn write_dot_receiver<W: Write, T: AstInfo>(
    f: &mut AstFormatter<W>,
    expr: &Expr<T>,
)
Expand description

Write expr as the receiver of a . operator (used by FieldAccess and WildcardAccess), parenthesizing when the receiver could re-bind the trailing dot on reparse. The . token has very high precedence and both the lexer and parser greedily extend adjacent tokens: 1.x tokenizes the number 1. and leaves x as an alias, and 'a'::T.x consumes T.x as a qualified type name. The whitelist below covers receivers that print as self-terminating syntax (parenthesized exprs, function calls, bracketed collections, etc.). Anything else gets explicit parens.

A bare Identifier/QualifiedWildcard receiver is not safe: a then .b/.* prints as a.b/a.*, which reparses as the qualified identifier Identifier([a, b]) / QualifiedWildcard([a]) rather than a field/wildcard access. The parser only ever builds those accesses over a parenthesized receiver ((a).b), so it wraps the name in Expr::Nested. A bare name here is a Nested-stripped AST and must be re-parenthesized. A FieldAccess / WildcardAccess receiver is safe, because its own printing already parenthesizes a bare-name base ((a).b.c), so the chain stays self-delimiting.

The quantified-subquery forms (AnySubquery/AllSubquery, printed <expr> <op> ANY (<query>)) are likewise not safe: they end in a (query) that is only a sub-part, so a trailing .x/.* binds to that inner subquery rather than the whole expression. (Contrast Subquery/ArraySubquery/… which are a single (…)/ARRAY(…) primary, so a trailing dot attaches to the whole thing.)