]> git.proxmox.com Git - rustc.git/blame - src/doc/unstable-book/src/language-features/on-unimplemented.md
New upstream version 1.40.0+dfsg1
[rustc.git] / src / doc / unstable-book / src / language-features / on-unimplemented.md
CommitLineData
8bb4bdeb
XL
1# `on_unimplemented`
2
3The tracking issue for this feature is: [#29628]
4
5[#29628]: https://github.com/rust-lang/rust/issues/29628
6
7------------------------
8
7cac9316
XL
9The `on_unimplemented` feature provides the `#[rustc_on_unimplemented]`
10attribute, which allows trait definitions to add specialized notes to error
b7449926
XL
11messages when an implementation was expected but not found. You can refer
12to the trait's generic arguments by name and to the resolved type using
13`Self`.
8bb4bdeb 14
7cac9316
XL
15For example:
16
17```rust,compile_fail
18#![feature(on_unimplemented)]
19
abe05a73
XL
20#[rustc_on_unimplemented="an iterator over elements of type `{A}` \
21 cannot be built from a collection of type `{Self}`"]
7cac9316
XL
22trait MyIterator<A> {
23 fn next(&mut self) -> A;
24}
25
26fn iterate_chars<I: MyIterator<char>>(i: I) {
27 // ...
28}
29
30fn main() {
31 iterate_chars(&[1, 2, 3][..]);
32}
33```
34
35When the user compiles this, they will see the following;
36
37```txt
38error[E0277]: the trait bound `&[{integer}]: MyIterator<char>` is not satisfied
39 --> <anon>:14:5
40 |
4114 | iterate_chars(&[1, 2, 3][..]);
abe05a73 42 | ^^^^^^^^^^^^^ an iterator over elements of type `char` cannot be built from a collection of type `&[{integer}]`
7cac9316 43 |
abe05a73 44 = help: the trait `MyIterator<char>` is not implemented for `&[{integer}]`
7cac9316 45 = note: required by `iterate_chars`
b7449926
XL
46```
47
48`on_unimplemented` also supports advanced filtering for better targeting
49of messages, as well as modifying specific parts of the error message. You
50target the text of:
51
52 - the main error message (`message`)
53 - the label (`label`)
54 - an extra note (`note`)
55
56For example, the following attribute
57
58```rust,compile_fail
59#[rustc_on_unimplemented(
60 message="message",
61 label="label",
62 note="note"
63)]
64trait MyIterator<A> {
65 fn next(&mut self) -> A;
66}
67```
68
69Would generate the following output:
70
71```text
72error[E0277]: message
73 --> <anon>:14:5
74 |
7514 | iterate_chars(&[1, 2, 3][..]);
76 | ^^^^^^^^^^^^^ label
77 |
78 = note: note
79 = help: the trait `MyIterator<char>` is not implemented for `&[{integer}]`
80 = note: required by `iterate_chars`
81```
82
83To allow more targeted error messages, it is possible to filter the
84application of these fields based on a variety of attributes when using
85`on`:
7cac9316 86
b7449926
XL
87 - `crate_local`: whether the code causing the trait bound to not be
88 fulfilled is part of the user's crate. This is used to avoid suggesting
89 code changes that would require modifying a dependency.
90 - Any of the generic arguments that can be substituted in the text can be
91 referred by name as well for filtering, like `Rhs="i32"`, except for
92 `Self`.
93 - `_Self`: to filter only on a particular calculated trait resolution, like
94 `Self="std::iter::Iterator<char>"`. This is needed because `Self` is a
95 keyword which cannot appear in attributes.
96 - `direct`: user-specified rather than derived obligation.
97 - `from_method`: usable both as boolean (whether the flag is present, like
98 `crate_local`) or matching against a particular method. Currently used
99 for `try`.
100 - `from_desugaring`: usable both as boolean (whether the flag is present)
416331ca
XL
101 or matching against a particular desugaring. The desugaring is identified
102 with its variant name in the `DesugaringKind` enum.
b7449926
XL
103
104For example, the `Iterator` trait can be annotated in the following way:
105
106```rust,compile_fail
107#[rustc_on_unimplemented(
108 on(
109 _Self="&str",
110 note="call `.chars()` or `.as_bytes()` on `{Self}"
111 ),
112 message="`{Self}` is not an iterator",
113 label="`{Self}` is not an iterator",
114 note="maybe try calling `.iter()` or a similar method"
115)]
116pub trait Iterator {}
7cac9316 117```
8bb4bdeb 118
b7449926
XL
119Which would produce the following outputs:
120
121```text
122error[E0277]: `Foo` is not an iterator
123 --> src/main.rs:4:16
124 |
1254 | for foo in Foo {}
126 | ^^^ `Foo` is not an iterator
127 |
128 = note: maybe try calling `.iter()` or a similar method
129 = help: the trait `std::iter::Iterator` is not implemented for `Foo`
130 = note: required by `std::iter::IntoIterator::into_iter`
131
132error[E0277]: `&str` is not an iterator
133 --> src/main.rs:5:16
134 |
1355 | for foo in "" {}
136 | ^^ `&str` is not an iterator
137 |
138 = note: call `.chars()` or `.bytes() on `&str`
139 = help: the trait `std::iter::Iterator` is not implemented for `&str`
140 = note: required by `std::iter::IntoIterator::into_iter`
141```
532ac7d7
XL
142
143If you need to filter on multiple attributes, you can use `all`, `any` or
144`not` in the following way:
145
146```rust,compile_fail
147#[rustc_on_unimplemented(
148 on(
149 all(_Self="&str", T="std::string::String"),
150 note="you can coerce a `{T}` into a `{Self}` by writing `&*variable`"
151 )
152)]
153pub trait From<T>: Sized { /* ... */ }
154```