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
5 changes: 4 additions & 1 deletion src/paths.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,10 @@ Vec::<u8>::with_capacity(1024);
```

r[paths.expr.argument-order]
The order of generic arguments is restricted to lifetime arguments, then type arguments, then const arguments, then equality constraints.
The order of generic arguments is restricted to lifetime arguments, then type arguments, then const arguments, then [equality constraints][bound.equality].

r[paths.expr.generic-bindings]
[GenericArgsBinding]s are currently only allowed for [equality constraints][bound.equality].

r[paths.expr.complex-const-params]
Const arguments must be surrounded by braces unless they are a [literal], an [inferred const], or a single segment path. An [inferred const] may not be surrounded by braces.
Expand Down
57 changes: 57 additions & 0 deletions src/trait-bounds.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,63 @@ r[bound.sized]

`?` is only used to relax the implicit [`Sized`] trait bound for [type parameters] or [associated types]. `?Sized` may not be used as a bound for other types.

r[bound.equality]
## Equality constraints
A trait bound that includes a [GenericArgsBinding] expresses an equality constraint on an associated type of a trait.

```rust
trait Tr { type Output; }
struct S {}
impl Tr for S { type Output = S; }
fn foo<T: Tr<Output=S>>() {}
```

Equality constraints cannot currently be expressed using a [WhereClause].

```rust,compile_fail
# trait Tr { type Output; }
# struct S {}
# impl Tr for S { type Output = S; }
// error: equality constraints are not yet supported in `where` clauses
fn uses_where<T>() where T::Output = S {}
Comment on lines +114 to +121
Copy link
Copy Markdown
Member

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

I'm not sure whether it makes sense to document something that isn't supported, especially since the Reference grammar already implies that.

Technically speaking, equality predicates like this are still part of the language in a gray area since they're syntactically valid in rustc. However, that'll change soon since T-lang has accepted my proposal to remove them. See rust-lang/rust#153513, I just need to tie up some loose ends.

That's why I initially clicked on this PR, I thought you were adding them to the Reference grammar.

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The lack of support for equality constraints in where clauses is specifically called out in RFC 195 (even though it is internally inconsistent on about it). I think it's useful to mention it anyway, because where clauses otherwise generally have superset of the capabilities of bounds attached inline to generic parameters.

```

Equality constraints must come after any input types (type parameters of a trait) in [GenericArgs].

```rust,compile_fail
trait Tr<T> { type Output; fn foo(x: T); }
struct S {}
impl<T> Tr<T> for S { type Output = S; fn foo(x: T) {} }
// error: generic arguments must come before the first constraint
fn wrong_order<T: Tr<Output=S, ()>>() {}
```

Equality constraints cannot be used in a [QualifiedPathType].

```rust,compile_fail,E0229
# trait Tr<T> { type Output; fn foo(x: T); }
# struct S {}
# impl<T> Tr<T> for S { type Output = S; fn foo(x: T) {} }
// error[E0229]: associated item constraints are not allowed here
fn uses_qualified_path() { <S as Tr<(), Output=S>>::foo(()); }
```

r[bound.equality.trait-object]
Equality constraints are *required* for generic [trait objects].
Copy link
Copy Markdown
Member

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

That's too imprecise, they aren't required per se.

They are required for associated types specifically or rephrased, every associated type from the trait itself or from any of its supertraits needs to be constrained in the trait object type ... unless it has a where Self: Sized; clause or was already constrained via supertrait bounds.

In any case, isn't this partially or fully duplicating facts from the Dyn compatibility section and thus redundant?

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Equality constraints appear to currently only be valid for associated types, as stated earlier in the proposed text. Stating that they are required for trait objects implies that they apply only to associated types.

In any case, isn't this partially or fully duplicating facts from the Dyn compatibility section and thus redundant?

Where is the requirement to fully specify associated types on trait objects in the existing Reference? It doesn't logically belong in the section on dyn compatibility, because a generic trait can be dyn compatible.

There is a case for describing this requirement in the section on trait objects, but I think it makes more sense to put it with the other trait bounds.


```rust,compile_fail,E0191
trait Foo<Input1, Input2> {
type Output1;
type Output2;
}
// correct: not a trait object
fn uses_foo<T: Foo<u8, u16>>(x: T) {}
// error[E0191]: the value of the associated types `Output1` and `Output2` in `Foo<u8, u16>` must be specified
fn uses_foo_obj(x: Box<dyn Foo<u8, u16>>) {}
// correct: all associated types constrained
fn also_foo_obj(x: Box<dyn Foo<u8, u16, Output1=u8, Output2=u16>>) {}
```

r[bound.lifetime]
## Lifetime bounds

Expand Down
Loading