@@ -866,19 +866,17 @@ struct](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/json/struct
866866(and sub-structs) for the JSON serialization. Don't confuse this with
867867[ ` errors::Diag ` ] ( https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/struct.Diag.html ) !
868868
869- ## ` #[rustc_on_unimplemented(...) ] `  
869+ ## ` #[rustc_on_unimplemented] `  
870870
871- The ` #[rustc_on_unimplemented] `  attribute allows trait definitions to add specialized
872- notes to error messages when an implementation was expected but not found.
873- You can refer to the trait's generic arguments by name and to the resolved type using ` Self ` .
874- 
875- For example:
871+ This attribute allows trait definitions to modify error messages when an implementation was
872+ expected but not found. The string literals in the attribute are format strings and can be
873+ formatted with named parameters. See the Formatting
874+ section below for what parameters are permitted.
876875
877876``` rust,ignore 
878- #![feature(rustc_attrs)] 
879- 
880- #[rustc_on_unimplemented="an iterator over elements of type `{A}` \ 
881-     cannot be built from a collection of type `{Self}`"] 
877+ #[rustc_on_unimplemented(message = "an iterator over \ 
878+     elements of type `{A}` cannot be built from a \ 
879+     collection of type `{Self}`")] 
882880trait MyIterator<A> { 
883881    fn next(&mut self) -> A; 
884882} 
@@ -895,32 +893,26 @@ fn main() {
895893When the user compiles this, they will see the following;
896894
897895``` txt 
898- error[E0277]: the trait bound ` &[{integer}]: MyIterator<char>` is not satisfied  
899-   --> <anon>:14:5  
896+ error[E0277]: an iterator over elements of type `char` cannot be built from a collection of type ` &[{integer}]`  
897+   --> src/main.rs:13:19  
900898   | 
901- 14 |     iterate_chars(&[1, 2, 3][..]); 
902-    |     ^^^^^^^^^^^^^ an iterator over elements of type `char` cannot be built from a collection of type `&[{integer}]` 
899+ 13 |     iterate_chars(&[1, 2, 3][..]); 
900+    |     ------------- ^^^^^^^^^^^^^^ the trait `MyIterator<char>` is not implemented for `&[{integer}]` 
901+    |     | 
902+    |     required by a bound introduced by this call 
903903   | 
904-    = help: the trait `MyIterator<char>` is not implemented for `&[{integer}]` 
905-    = note: required by `iterate_chars` 
904+ note: required by a bound in `iterate_chars` 
906905``` 
907906
908- ` rustc_on_unimplemented `  also supports advanced filtering for better targeting
909- of messages, as well as modifying specific parts of the error message. You
910- target the text of:
911- 
907+ You can modify the contents of:
912908 -  the main error message (` message ` )
913909 -  the label (` label ` )
914-  -  an extra  note (` note ` )
910+  -  the  note(s)  (` note ` )
915911
916912For example, the following attribute
917913
918914``` rust,ignore 
919- #[rustc_on_unimplemented( 
920-     message="message", 
921-     label="label", 
922-     note="note" 
923- )] 
915+ #[rustc_on_unimplemented(message = "message", label = "label", note = "note")] 
924916trait MyIterator<A> { 
925917    fn next(&mut self) -> A; 
926918} 
@@ -930,45 +922,61 @@ Would generate the following output:
930922
931923``` text 
932924error[E0277]: message 
933-   --> <anon>:14:5  
925+   --> <file>:10:19  
934926   | 
935- 14 |     iterate_chars(&[1, 2, 3][..]); 
936-    |     ^^^^^^^^^^^^^ label 
927+ 10 |     iterate_chars(&[1, 2, 3][..]); 
928+    |     ------------- ^^^^^^^^^^^^^^ label 
929+    |     | 
930+    |     required by a bound introduced by this call 
937931   | 
938-    = note: note 
939932   = help: the trait `MyIterator<char>` is not implemented for `&[{integer}]` 
940-    = note: required by `iterate_chars` 
933+    = note: note 
934+ note: required by a bound in `iterate_chars` 
941935``` 
942936
937+ The functionality discussed so far is also available with
938+ [ ` #[diagnostic::on_unimplemented] ` ] ( https://doc.rust-lang.org/nightly/reference/attributes/diagnostics.html#the-diagnosticon_unimplemented-attribute ) .
939+ If you can, you should use that instead.
940+ 
941+ ### Filtering  
942+ 
943943To allow more targeted error messages, it is possible to filter the
944- application of these fields based on a variety of attributes when using
945- ` on ` :
944+ application of these fields with ` on ` .
946945
946+ You can filter on the following boolean flags:
947947 -  ` crate_local ` : whether the code causing the trait bound to not be
948948   fulfilled is part of the user's crate. This is used to avoid suggesting
949949   code changes that would require modifying a dependency.
950-  -  Any of the generic arguments that can be substituted in the text can be
951-    referred by name as well for filtering, like ` Rhs="i32" ` , except for
952-    ` Self ` .
953-  -  ` _Self ` : to filter only on a particular calculated trait resolution, like
954-    ` Self="std::iter::Iterator<char>" ` . This is needed because ` Self `  is a
955-    keyword which cannot appear in attributes.
956-  -  ` direct ` : user-specified rather than derived obligation.
957-  -  ` from_desugaring ` : usable both as boolean (whether the flag is present)
958-    or matching against a particular desugaring. The desugaring is identified
959-    with its variant name in the ` DesugaringKind `  enum.
960- 
961- For example, the ` Iterator `  trait can be annotated in the following way:
950+  -  ` direct ` : whether this is an user-specified rather than derived obligation.
951+  -  ` from_desugaring ` : whether we are in some kind of desugaring, like ` ? ` 
952+    or a ` try `  block for example. This flag can also be matched on, see below.
953+ 
954+ You can match on the following names and values, using ` name = "value" ` :
955+  -  ` cause ` : Match against one variant of the ` ObligationCauseCode ` 
956+    enum. Only ` "MainFunctionType" `  is supported.
957+  -  ` from_desugaring ` : Match against a particular variant of the ` DesugaringKind ` 
958+    enum. The desugaring is identified by its variant name, for example
959+    ` "QuestionMark" `  for ` ? `  desugaring or ` "TryBlock" `  for ` try `  blocks.
960+  -  ` Self `  and any generic arguments of the trait, like ` Self = "alloc::string::String" ` 
961+    or ` Rhs="i32" ` .
962+    
963+ The compiler can provide several values to match on, for example:
964+   -  the self_ty, pretty printed with and without type arguments resolved.
965+   -  ` "{integral}" ` , if self_ty is an integral of which the type is known.
966+   -  ` "[]" ` , ` "[{ty}]" ` , ` "[{ty}; _]" ` , ` "[{ty}; $N]" `  when applicable.
967+   -  references to said slices and arrays.
968+   -  ` "fn" ` , ` "unsafe fn" `  or ` "#[target_feature] fn" `  when self is a function.
969+   -  ` "{integer}" `  and ` "{float}" `  if the type is a number but we haven't inferred it yet.
970+   -  combinations of the above, like ` "[{integral}; _]" ` .
971+ 
972+ For example, the ` Iterator `  trait can be filtered in the following way:
962973
963974``` rust,ignore 
964975#[rustc_on_unimplemented( 
965-     on( 
966-         _Self="&str", 
967-         note="call `.chars()` or `.as_bytes()` on `{Self}`" 
968-     ), 
969-     message="`{Self}` is not an iterator", 
970-     label="`{Self}` is not an iterator", 
971-     note="maybe try calling `.iter()` or a similar method" 
976+     on(Self = "&str", note = "call `.chars()` or `.as_bytes()` on `{Self}`"), 
977+     message = "`{Self}` is not an iterator", 
978+     label = "`{Self}` is not an iterator", 
979+     note = "maybe try calling `.iter()` or a similar method" 
972980)] 
973981pub trait Iterator {} 
974982``` 
@@ -997,15 +1005,47 @@ error[E0277]: `&str` is not an iterator
9971005  = note: required by `std::iter::IntoIterator::into_iter` 
9981006``` 
9991007
1000- If you need to filter on multiple attributes, you can use ` all ` , ` any `  or
1001- ` not `  in the following way:
1008+ The ` on `  filter accepts ` all ` , ` any `  and ` not `  predicates similar to the ` cfg `  attribute:
10021009
10031010``` rust,ignore 
1004- #[rustc_on_unimplemented( 
1005-     on( 
1006-         all(_Self="&str", T="std::string::String"), 
1007-         note="you can coerce a `{T}` into a `{Self}` by writing `&*variable`" 
1008-     ) 
1009- )] 
1010- pub trait From<T>: Sized { /* ... */ } 
1011+ #[rustc_on_unimplemented(on( 
1012+     all(Self = "&str", T = "alloc::string::String"), 
1013+     note = "you can coerce a `{T}` into a `{Self}` by writing `&*variable`" 
1014+ ))] 
1015+ pub trait From<T>: Sized { 
1016+     /* ... */ 
1017+ } 
1018+ ``` 
1019+ 
1020+ ### Formatting   
1021+ 
1022+ The string literals are format strings that accept parameters wrapped in braces
1023+ but positional and listed parameters and format specifiers are not accepted.
1024+ The following parameter names are valid:
1025+ -  ` Self `  and all generic parameters of the trait.
1026+ -  ` This ` : the name of the trait the attribute is on, without generics.
1027+ -  ` Trait ` : the name of the "sugared" trait. See ` TraitRefPrintSugared ` .
1028+ -  ` ItemContext ` : the kind of ` hir::Node `  we're in, things like ` "an async block" ` ,
1029+    ` "a function" ` , ` "an async function" ` , etc.
1030+ 
1031+ Something like:
1032+ 
1033+ ``` rust,ignore 
1034+ #![feature(rustc_attrs)] 
1035+ 
1036+ #[rustc_on_unimplemented(message = "Self = `{Self}`, \ 
1037+     T = `{T}`, this = `{This}`, trait = `{Trait}`, \ 
1038+     context = `{ItemContext}`")] 
1039+ pub trait From<T>: Sized { 
1040+     fn from(x: T) -> Self; 
1041+ } 
1042+ 
1043+ fn main() { 
1044+     let x: i8 = From::from(42_i32); 
1045+ } 
1046+ ``` 
1047+ 
1048+ Will format the message into 
1049+ ``` text 
1050+ "Self = `i8`, T = `i32`, this = `From`, trait = `From<i32>`, context = `a function`" 
10111051``` 
0 commit comments