Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/items/generics.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ GenericParams -> `<` ( GenericParam (`,` GenericParam)* `,`? )? `>`

GenericParam -> OuterAttribute* ( LifetimeParam | TypeParam | ConstParam )

LifetimeParam -> Lifetime ( `:` LifetimeBounds )?
LifetimeParam -> Lifetime ( `:` LifetimeBounds? )?

TypeParam -> IDENTIFIER ( `:` Bounds? )? ( `=` Type )?

Expand Down Expand Up @@ -234,7 +234,7 @@ WhereClauseItem ->
LifetimeWhereClauseItem
| TypeBoundWhereClauseItem

LifetimeWhereClauseItem -> Lifetime `:` LifetimeBounds
LifetimeWhereClauseItem -> Lifetime `:` LifetimeBounds?

TypeBoundWhereClauseItem -> ForLifetimes? Type `:` Bounds?
```
Expand Down
2 changes: 1 addition & 1 deletion src/items/type-aliases.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ r[items.type]
r[items.type.syntax]
```grammar,items
TypeAlias ->
`type` IDENTIFIER GenericParams? ( `:` Bounds )?
`type` IDENTIFIER GenericParams? ( `:` Bounds? )?
WhereClause?
( `=` Type WhereClause?)? `;`
```
Expand Down
2 changes: 1 addition & 1 deletion src/paths.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ GenericArgsBinding ->
TypePathSegment `=` Type
GenericArgsBounds ->
TypePathSegment `:` Bounds
TypePathSegment `:` Bounds?
```

r[paths.expr.intro]
Expand Down
8 changes: 6 additions & 2 deletions src/types/impl-trait.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ r[type.impl-trait]

r[type.impl-trait.syntax]
```grammar,types
ImplTraitType -> `impl` Bounds
ImplTraitType -> `impl` Bounds?
Comment thread
fmease marked this conversation as resolved.

ImplTraitTypeOneBound -> `impl` TraitBound
ImplTraitTypeOneBound -> `impl` TraitBound?
```

r[type.impl-trait.intro]
Expand All @@ -23,6 +23,10 @@ fn foo(arg: impl Trait) {
fn bar() -> impl Trait {
}
```

@fmease fmease May 27, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I'm mirroring the structure of the section about trait object types here with the name vs. constraint split. I'm definitely not married to it. I actually find the rule name name a bit confusing and I feel like the rule sort of mixes syntax and semantics (just like its preexisting sibling for trait object types).

View changes since the review

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looking more closely at this, I agree the ".name" rules don't really make sense.

Generally we don't want to have an English description of the syntax (which is often very imprecise). I'm thinking we can just drop these two .name rules entirely.

r[type.impl-trait.bounds]
There must be at least one trait bound, no more than one `use<..>` bound, and no more than one opt-out bound (e.g., `?Sized`).

r[type.impl-trait.param]
## Anonymous type parameters

Expand Down
20 changes: 11 additions & 9 deletions src/types/trait-object.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,22 @@ r[type.trait-object]

r[type.trait-object.syntax]
```grammar,types
TraitObjectType -> `dyn`? Bounds
TraitObjectType -> Bounds[^bare-2021] | `dyn`[^dyn-2018] Bounds?

TraitObjectTypeOneBound -> `dyn`? TraitBound
TraitObjectTypeOneBound -> TraitBound[^bare-2021] | `dyn`[^dyn-2018] TraitBound?
```

[^bare-2021]: See [type.trait-object.syntax-edition2021].
[^dyn-2018]: See [type.trait-object.syntax-edition2018].

r[type.trait-object.intro]
A *trait object* is an opaque value of another type that implements a set of traits. The set of traits is made up of a [dyn compatible] *base trait* plus any number of [auto traits].

r[type.trait-object.impls]
Trait objects implement the base trait, its auto traits, and any [supertraits] of the base trait.

r[type.trait-object.name]
Trait objects are written as the keyword `dyn` followed by a set of trait bounds, but with the following restrictions on the trait bounds.

r[type.trait-object.constraint]
There may not be more than one non-auto trait, no more than one lifetime, and opt-out bounds (e.g. `?Sized`) are not allowed. Furthermore, paths to traits may be parenthesized.
r[type.trait-object.bounds]

@fmease fmease May 27, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Changed it to bounds from constraint since the corresponding rule for impl-Trait had to be renamed to bounds not to conflict with the preexisting types.impl-trait.constraint.

View changes since the review

There must be at least one trait bound, there may not be more than one non-auto trait, no more than one lifetime, and opt-out bounds (e.g., `?Sized`) and `use<..>` bounds are not allowed.

For example, given a trait `Trait`, the following are all trait objects:

Expand All @@ -33,11 +33,13 @@ For example, given a trait `Trait`, the following are all trait objects:

r[type.trait-object.syntax-edition2021]
> [!EDITION-2021]
> Before the 2021 edition, the `dyn` keyword may be omitted.
> Before the 2021 edition, the `dyn` keyword may be omitted. In the 2021 edition and beyond, the `dyn` keyword is required semantically.

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], [LIFETIME_TOKEN], `for`, `(` or `?` to be interpreted as a keyword instead of a regular identifier.
>
> Most notably, `dyn`, `dyn::T` and `dyn<T>` will all be treated as type paths. As such, if you want a trait object type with the trait `::module::Trait`, you need to put the path in parentheses and write it as `dyn (::module::Trait)`.
>
> Beginning in the 2018 edition, `dyn` is a true keyword and is not allowed in paths, so the parentheses are not necessary.

Expand Down
Loading