rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
97k stars 12.54k forks source link

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

Open petrochenkov opened 6 years ago

petrochenkov commented 6 years ago

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).

nagisa commented 6 years ago

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.

petrochenkov commented 6 years ago

Yeah, this is mostly a theoretical concern.

Enselic commented 12 months ago

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.