Grammar ambiguity with left shifts and fully qualified (UFCS) paths

681a2db
Opened by Vadim Petrochenkov at 2023-09-24 17:07:24

Playground: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=35f2e9b9c6d48c33199bc878363a15df

trait Trait {
    const CONST: u8;
}
impl Trait for *const u8 {
    const CONST: u8 = 1;
}

fn main() {
    0<<*const u8 as Trait>::CONST;
}

0<<*const u8 as Trait>::CONST here unambiguously means 0 < (<*const u8 as Trait>::CONST) because it can't be parsed as a shift, but rustc tries to parse it as a shift and report an error:

error: expected expression, found keyword `const`
 --> src/main.rs:9:9
  |
9 |     0<<*const u8 as Trait>::CONST;
  |         ^^^^^

Note that you can't detect this situation using limited lookahead in general case, for example

0<<Trait1 + Trait2 + ... + 'static as Trait>::CONST

is unambiguously a type too, but we don't know it until we see 'static.

This syntax allows to construct fully ambiguous examples as well, e.g.

x<<y as z>::a

can be interpreted as both ((x << y) as z) > (::a) and x < (<y as z>::a).

  1. Doesn’t seem like too much of a problem to me especially that formatting it conventionally

    fn main() {
        0 < <*const u8 as Trait>::CONST;
    }
    

    breaks up the << token and produces "expected" results.

    Simonas Kazlauskas at 2017-10-10 19:45:22

  2. Yeah, this is mostly a theoretical concern.

    Vadim Petrochenkov at 2017-10-10 20:56:11

  3. Triage: Normally I do not touch prio labels since it is up to the owning team to decide prio, but when there seems to be an agreement that this is "mostly a theoretical concern", it seems fine to mark this P-low. Marking as P-low.

    Martin Nordholts at 2023-09-24 17:07:11