1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
# `auto_traits`
The tracking issue for this feature is [#13231]
[#13231]: https://github.com/rust-lang/rust/issues/13231
----
The `auto_traits` feature gate allows you to define auto traits.
Auto traits, like [`Send`] or [`Sync`] in the standard library, are marker traits
that are automatically implemented for every type, unless the type, or a type it contains,
has explicitly opted out via a negative impl. (Negative impls are separately controlled
by the `negative_impls` feature.)
[`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html
[`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html
```rust,ignore (partial-example)
impl !Trait for Type {}
```
Example:
```rust
#![feature(negative_impls)]
#![feature(auto_traits)]
auto trait Valid {}
struct True;
struct False;
impl !Valid for False {}
struct MaybeValid<T>(T);
fn must_be_valid<T: Valid>(_t: T) { }
fn main() {
// works
must_be_valid( MaybeValid(True) );
// compiler error - trait bound not satisfied
// must_be_valid( MaybeValid(False) );
}
```
## Automatic trait implementations
When a type is declared as an `auto trait`, we will automatically
create impls for every struct/enum/union, unless an explicit impl is
provided. These automatic impls contain a where clause for each field
of the form `T: AutoTrait`, where `T` is the type of the field and
`AutoTrait` is the auto trait in question. As an example, consider the
struct `List` and the auto trait `Send`:
```rust
struct List<T> {
data: T,
next: Option<Box<List<T>>>,
}
```
Presuming that there is no explicit impl of `Send` for `List`, the
compiler will supply an automatic impl of the form:
```rust
struct List<T> {
data: T,
next: Option<Box<List<T>>>,
}
unsafe impl<T> Send for List<T>
where
T: Send, // from the field `data`
Option<Box<List<T>>>: Send, // from the field `next`
{ }
```
Explicit impls may be either positive or negative. They take the form:
```rust,ignore (partial-example)
impl<...> AutoTrait for StructName<..> { }
impl<...> !AutoTrait for StructName<..> { }
```
## Coinduction: Auto traits permit cyclic matching
Unlike ordinary trait matching, auto traits are **coinductive**. This
means, in short, that cycles which occur in trait matching are
considered ok. As an example, consider the recursive struct `List`
introduced in the previous section. In attempting to determine whether
`List: Send`, we would wind up in a cycle: to apply the impl, we must
show that `Option<Box<List>>: Send`, which will in turn require
`Box<List>: Send` and then finally `List: Send` again. Under ordinary
trait matching, this cycle would be an error, but for an auto trait it
is considered a successful match.
## Items
Auto traits cannot have any trait items, such as methods or associated types. This ensures that we can generate default implementations.
## Supertraits
Auto traits cannot have supertraits. This is for soundness reasons, as the interaction of coinduction with implied bounds is difficult to reconcile.
|