Skip to content

Potential issues with Rust's grammar I might upstream to r-l/r at some point #7

@fmease

Description

@fmease
  • S { 0 } is legal as a pattern but not as an expression
    • it's a "shorthand" for the unwritable S { 0: 0 } where both 0s are identifiers
    • ideally we'd reject both I think (would need to crater ofc)
    • but I'm also fine with allowing S { 0 } in expressions just to achieve consistency
  • tuple field access $expr.0usize is illegal (since very recently) but $expr.0x0, $expr.0e1 (but not $expr.0e+1 thankfully) etc. is still legal
    • (however $expr.1 != $expr.01 and $expr.0 != $expr.0_, so it all doesn't really matter)
    • the same thing applies to builtin # offset_of(…) / core::mem::offset_of!(…)
  • match () { X } is accepted but not match () { X, } (under feature never_patterns)
    • a comma may only follow if the pattern "may contain a never pattern" (which includes all macro calls)
    • I'm not very happy to have such a heuristic essentially in the grammar
    • this issue basically only exists because of ,| recovery in patterns
    • to restrict a feature just to keep a nice diagnostic + recovery is questionable imo
    • moreover, we could move that diagnostic to a later compiler stage
  • const block items permit visibility
    • this is mentioned in the tracking issue: Tracking Issue for item-level const blocks rust-lang/rust#149226
    • however, it's under Unresolved Questions while it's clearly undesirable
    • we literally have a lint for pub const _: … = …; now
    • moreover, I doubt that this could be useful for macro DSLs
    • finally, rustc rejects fn f() { pub const {} } already anyway
    • I'm going to open an issue or a PR if this doesn't get fixed within the next 6 months (today is 2026-02-08)
  • we consider impl F() -> impl X + Y, impl F() -> dyn X + Y etc. ambiguous but not impl Fn() -> for<> X + Y
    • super minor, maybe not even a bug? my head is spinning
    • (obviously impl Fn() -> X + Y is intentionally not considered ambiguous)
    • similarly, dyn F() -> fn() -> X + Y is not considered ambiguous
    • in conclusion, it's quite an artificial & specialized restriction
    • more weirdly even, we're allowing fn f<T: F() -> 'a + Copy>(){} and counting the Copy as a sibling of F, not of 'a; so it gets parsed as (Fn() -> 'a+) + Copy, not Fn() -> ('a + Copy)
    • that happens because we check for the presence of + when encountering 'a in type position without checking whether "+ is allowed" in this context (it isn't)
  • we accept (use<>)+ even though you're not allowed to parenthesize use<…> in "normal" bounds

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-lowTechnical complexity: LowC-socialComplexity: Social in natureK-tracking-issueKind: Tracking issueP-lowPriority: LowS-actionableStatus: Actionable

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions