github dtolnay/syn 1.0.31

latest releases: 2.0.79, 2.0.78, 2.0.77...
4 years ago
  • Add Expr::parse_without_eager_brace to parse expressions in ambiguous syntactic position.

    Rust grammar has an ambiguity where braces sometimes turn a path expression into a struct initialization and sometimes do not. In the following code, the expression S {} is one expression. Presumably there is an empty struct struct S {} defined somewhere which it is instantiating.

    let _ = *S {};
    
    // parsed by rustc as: `*(S {})`

    We would want to parse the above using Expr::parse after the = token.

    But in the following, S {} is not a struct init expression.

    if *S {} {}
    
    // parsed by rustc as:
    //
    //    if (*S) {
    //        /* empty block */
    //    }
    //    {
    //        /* another empty block */
    //    }

    For that reason we would want to parse if-conditions using Expr::parse_without_eager_brace after the if token. Same for similar syntactic positions such as the condition expr after a while token or the expr at the top of a match.

    The Rust grammar's choices around which way this ambiguity is resolved at various syntactic positions is fairly arbitrary. Really either parse behavior could work in most positions, and language designers just decide each case based on which is more likely to be what the programmer had in mind most of the time.

    if return S {} {}
    
    // parsed by rustc as:
    //
    //    if (return (S {})) {
    //    }
    //
    // but could equally well have been this other arbitrary choice:
    //
    //    if (return S) {
    //    }
    //    {}

    Note the grammar ambiguity on trailing braces is distinct from precedence and is not captured by assigning a precedence level to the braced struct init expr in relation to other operators. This can be illustrated by return 0..S {} vs match 0..S {}. The former parses as return (0..(S {})) implying tighter precedence for struct init than .., while the latter parses as match (0..S) {} implying tighter precedence for .. than struct init, a contradiction.

Don't miss a new syn release

NewReleases is sending notifications on new releases.