3 The tracking issue for this feature is: [#29628]
5 [#29628]: https://github.com/rust-lang/rust/issues/29628
7 ------------------------
9 The `on_unimplemented` feature provides the `#[rustc_on_unimplemented]`
10 attribute, which allows trait definitions to add specialized notes to error
11 messages when an implementation was expected but not found. You can refer
12 to the trait's generic arguments by name and to the resolved type using
18 #![feature(on_unimplemented)]
20 #[rustc_on_unimplemented="an iterator over elements of type `{A}` \
21 cannot be built from a collection of type `{Self}`"]
23 fn next(&mut self) -> A;
26 fn iterate_chars<I: MyIterator<char>>(i: I) {
31 iterate_chars(&[1, 2, 3][..]);
35 When the user compiles this, they will see the following;
38 error[E0277]: the trait bound `&[{integer}]: MyIterator<char>` is not satisfied
41 14 | iterate_chars(&[1, 2, 3][..]);
42 | ^^^^^^^^^^^^^ an iterator over elements of type `char` cannot be built from a collection of type `&[{integer}]`
44 = help: the trait `MyIterator<char>` is not implemented for `&[{integer}]`
45 = note: required by `iterate_chars`
48 `on_unimplemented` also supports advanced filtering for better targeting
49 of messages, as well as modifying specific parts of the error message. You
52 - the main error message (`message`)
54 - an extra note (`note`)
56 For example, the following attribute
59 #[rustc_on_unimplemented(
65 fn next(&mut self) -> A;
69 Would generate the following output:
75 14 | iterate_chars(&[1, 2, 3][..]);
79 = help: the trait `MyIterator<char>` is not implemented for `&[{integer}]`
80 = note: required by `iterate_chars`
83 To allow more targeted error messages, it is possible to filter the
84 application of these fields based on a variety of attributes when using
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
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
100 - `from_desugaring`: usable both as boolean (whether the flag is present)
101 or matching against a particular desugaring.
103 For example, the `Iterator` trait can be annotated in the following way:
106 #[rustc_on_unimplemented(
109 note="call `.chars()` or `.as_bytes()` on `{Self}"
111 message="`{Self}` is not an iterator",
112 label="`{Self}` is not an iterator",
113 note="maybe try calling `.iter()` or a similar method"
115 pub trait Iterator {}
118 Which would produce the following outputs:
121 error[E0277]: `Foo` is not an iterator
124 4 | for foo in Foo {}
125 | ^^^ `Foo` is not an iterator
127 = note: maybe try calling `.iter()` or a similar method
128 = help: the trait `std::iter::Iterator` is not implemented for `Foo`
129 = note: required by `std::iter::IntoIterator::into_iter`
131 error[E0277]: `&str` is not an iterator
135 | ^^ `&str` is not an iterator
137 = note: call `.chars()` or `.bytes() on `&str`
138 = help: the trait `std::iter::Iterator` is not implemented for `&str`
139 = note: required by `std::iter::IntoIterator::into_iter`
142 If you need to filter on multiple attributes, you can use `all`, `any` or
143 `not` in the following way:
146 #[rustc_on_unimplemented(
148 all(_Self="&str", T="std::string::String"),
149 note="you can coerce a `{T}` into a `{Self}` by writing `&*variable`"
152 pub trait From<T>: Sized { /* ... */ }