Skip to content

Commit 3803822

Browse files
committed
trait bounds initial setup
1 parent 9753ddb commit 3803822

File tree

2 files changed

+44
-50
lines changed

2 files changed

+44
-50
lines changed

src/items/generics.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,14 @@ struct Foo<#[my_flexible_clone(unbounded)] H> {
310310
}
311311
```
312312

313+
## Instantiation
314+
315+
r[items.generics.instantiation]
316+
When using an item its generic parameters have to get instantiated.
317+
318+
> [!NOTE]
319+
> This is a placeholder for future expansion and overlaps with [items.fn.generics.mono].
320+
313321
[array repeat expression]: ../expressions/array-expr.md
314322
[arrays]: ../types/array.md
315323
[slices]: ../types/slice.md

src/trait-bounds.md

Lines changed: 36 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -44,66 +44,52 @@ certain common cases:
4444
`trait A { type B: Copy; }` is equivalent to
4545
`trait A where Self::B: Copy { type B; }`.
4646

47+
r[bound.global]
48+
49+
Bounds which does not use the item's parameters or any higher-ranked lifetimes are considered global.
50+
51+
Global bounds must be satisfiable without relying on any where clauses.
52+
4753
r[bound.satisfaction]
48-
Bounds on an item must be satisfied when using the item. When type checking and
49-
borrow checking a generic item, the bounds can be used to determine that a
50-
trait is implemented for a type. For example, given `Ty: Trait`
5154

52-
* In the body of a generic function, methods from `Trait` can be called on `Ty`
53-
values. Likewise associated constants on the `Trait` can be used.
54-
* Associated types from `Trait` can be used.
55-
* Generic functions and types with a `T: Trait` bounds can be used with `Ty`
56-
being used for `T`.
55+
The bounds of an item must be satisfied when using that item.
5756

58-
```rust
59-
# type Surface = i32;
60-
trait Shape {
61-
fn draw(&self, surface: Surface);
62-
fn name() -> &'static str;
63-
}
57+
r[bound.satisfaction.impl]
6458

65-
fn draw_twice<T: Shape>(surface: Surface, sh: T) {
66-
sh.draw(surface); // Can call method because T: Shape
67-
sh.draw(surface);
68-
}
59+
A trait bound can be satisfied by using an implementation of that trait. An implementation is applicable if
60+
its generic parameters can be instantiated so that its self type and trait arguments are equal to the trait bound
61+
and the where-bounds of the impl can be recursively satisfied.
6962

70-
fn copy_and_draw_twice<T: Copy>(surface: Surface, sh: T) where T: Shape {
71-
let shape_copy = sh; // doesn't move sh because T: Copy
72-
draw_twice(surface, sh); // Can use generic function because T: Shape
73-
}
63+
r[bound.satisfaction.bounds]
7464

75-
struct Figure<S: Shape>(S, S);
65+
While inside of a generic item, trait bounds can be satisfied by using the where-bounds of the current item as the item is able to assume that its bounds are satisfied. For this, the where-bound is then equated with the trait bound that needs to be satisfied.
7666

77-
fn name_figure<U: Shape>(
78-
figure: Figure<U>, // Type Figure<U> is well-formed because U: Shape
79-
) {
80-
println!(
81-
"Figure of two {}",
82-
U::name(), // Can use associated function
83-
);
67+
r[bound.satisfaction.candidate-preference]
68+
69+
> This is purely descriptive. Candidate preference behavior may change in future releases and must not be relied upon for correctness or soundness.
70+
71+
If there are multiple ways to satisfy a trait bound, some groups of candidate are preferred over others. In case a single group has multiple different candidates, the bound remains ambiguous. Candidate preference has the following order
72+
- builtin implementations of `Sized`
73+
- if there are any non-global where-bounds, all where-bounds
74+
- impls
75+
- global where-bounds
76+
77+
```rust
78+
struct Container<T> {
79+
inner: Vec<T>,
80+
}
81+
impl<T: Clone> for Container<T> {
82+
fn clone(&self) -> Self {
83+
Container { inner: self.inner.clone() }
84+
}
8485
}
85-
```
8686

87-
r[bound.trivial]
88-
Bounds that don't use the item's parameters or [higher-ranked lifetimes] are checked when the item is defined.
89-
It is an error for such a bound to be false.
90-
91-
r[bound.special]
92-
[`Copy`], [`Clone`], and [`Sized`] bounds are also checked for certain generic types when using the item, even if the use does not provide a concrete type.
93-
It is an error to have `Copy` or `Clone` as a bound on a mutable reference, [trait object], or [slice].
94-
It is an error to have `Sized` as a bound on a trait object or slice.
95-
96-
```rust,compile_fail
97-
struct A<'a, T>
98-
where
99-
i32: Default, // Allowed, but not useful
100-
i32: Iterator, // Error: `i32` is not an iterator
101-
&'a mut T: Copy, // (at use) Error: the trait bound is not satisfied
102-
[T]: Sized, // (at use) Error: size cannot be known at compilation
103-
{
104-
f: &'a T,
87+
fn is_clone<T: Clone>() {}
88+
fn generic_fn<T: Clone>() {
89+
// `Container<T>: Clone` is satisfied via the impl above. This requires
90+
// the nested trait bound `T: Clone` which is satisfied via the where-bound.
91+
is_clone::<Container<T>>();
10592
}
106-
struct UsesA<'a, T>(A<'a, T>);
10793
```
10894

10995
r[bound.trait-object]

0 commit comments

Comments
 (0)