Skip to content

Fix grammar rules containing or pertaining to bounds#2257

Open
fmease wants to merge 2 commits intorust-lang:masterfrom
fmease:fix-bounds-grammars
Open

Fix grammar rules containing or pertaining to bounds#2257
fmease wants to merge 2 commits intorust-lang:masterfrom
fmease:fix-bounds-grammars

Conversation

@fmease
Copy link
Copy Markdown
Member

@fmease fmease commented May 5, 2026

At least since PR rust-lang/rust#39158 (2017) bounds (what the Reference calls TypeParamBounds) are intentionally always optional after "bound heralds" (:, impl, dyn). However, the Reference didn't reflect this fact everywhere. This PR rectifies this.

For example reference@master considers the following snippets to be syntactically ill-formed which directly contradicts rustc:

Furthermore, the edition disclaimer for trait object types is incomplete / imprecise / inaccurate:

It states that token sequence dyn:: will be interpreted as the start of a path in Rust 2015 which is correct in isolation but far from complete in context. Per argumentum e contrario, it would wrongly imply that in Rust 2015 the following snippets all contain (bare) trait object types:

  • type T = dyn;, type T = (dyn);, type T = [dyn];
  • type T = dyn<>;, type T = dyn<()>;, type T = dyn<<T>::S>;

To address this, I've changed the note to use an exhaustive and positive listing of tokens. The follow set is {PathIdentSegment, LIFETIME_OR_LABEL, for, (, ?} as per rustc's can_begin_dyn_bound_in_edition_2015.

@rustbot rustbot added the S-waiting-on-review Status: The marked PR is awaiting review from a maintainer label May 5, 2026
Comment thread src/types/trait-object.md
r[type.trait-object.syntax]
```grammar,types
TraitObjectType -> `dyn`? TypeParamBounds
TraitObjectType -> TypeParamBounds | `dyn` TypeParamBounds?
Copy link
Copy Markdown
Member Author

@fmease fmease May 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Due to this grammar rule, TypeParamBounds must remain non-empty.

View changes since the review

@fmease fmease force-pushed the fix-bounds-grammars branch from 4200b2e to 7b807ac Compare May 5, 2026 10:25
Comment thread src/types/trait-object.md
r[type.trait-object.syntax-edition2018]
> [!EDITION-2018]
> In the 2015 edition, if the first bound of the trait object is a path that starts with `::`, then the `dyn` will be treated as a part of the path. The first path can be put in parenthesis to get around this. As such, if you want a trait object with the trait `::your_module::Trait`, you should write it as `dyn (::your_module::Trait)`.
> In the 2015 edition, `dyn` must be followed by [PathIdentSegment][grammar-PathIdentSegment], [LIFETIME_OR_LABEL][grammar-LIFETIME_OR_LABEL], `for`, `(` or `?` to be interpreted as the start of a trait object type. Otherwise, it will be interpreted as a regular identifier.
Copy link
Copy Markdown
Member Author

@fmease fmease May 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Originally I wrote Otherwise, it will be interpreted as a regular identifier and thus as the start of a type path. However the final clause wasn't correct strictly speaking: In Rust 2015 in a type context, dyn that's not followed by one of those tokens could start a TypePath (e.g., dyn, dyn::X), a TraitObjectType (e.g., dyn+, dyn + X) or a MacroInvocation (e.g., dyn!(), dyn::m!()), so I've retracted that statement again.

I don't feel like mentioning TypePath, TraitObjectType & MacroInvocation in this sentence since it can easily become outdated. The consequences should be self-evident anyway.

View changes since the review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-review Status: The marked PR is awaiting review from a maintainer

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants