@@ -866,19 +866,17 @@ struct](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/json/struct
866
866
(and sub-structs) for the JSON serialization. Don't confuse this with
867
867
[ ` errors::Diag ` ] ( https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/struct.Diag.html ) !
868
868
869
- ## ` #[rustc_on_unimplemented(...) ] `
869
+ ## ` #[rustc_on_unimplemented] `
870
870
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.
876
875
877
876
``` 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}`")]
882
880
trait MyIterator<A> {
883
881
fn next(&mut self) -> A;
884
882
}
@@ -895,32 +893,26 @@ fn main() {
895
893
When the user compiles this, they will see the following;
896
894
897
895
``` 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
900
898
|
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
903
903
|
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`
906
905
```
907
906
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:
912
908
- the main error message (` message ` )
913
909
- the label (` label ` )
914
- - an extra note (` note ` )
910
+ - the note(s) (` note ` )
915
911
916
912
For example, the following attribute
917
913
918
914
``` 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")]
924
916
trait MyIterator<A> {
925
917
fn next(&mut self) -> A;
926
918
}
@@ -930,45 +922,62 @@ Would generate the following output:
930
922
931
923
``` text
932
924
error[E0277]: message
933
- --> <anon>:14:5
925
+ --> <file>>:10:19
934
926
|
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
937
931
|
938
- = note: note
939
932
= 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`
941
935
```
942
936
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
+
943
943
To 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 ` .
946
945
946
+ You can filter on the following boolean flags:
947
947
- ` crate_local ` : whether the code causing the trait bound to not be
948
948
fulfilled is part of the user's crate. This is used to avoid suggesting
949
949
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" ` . You may see older uses of the attribute use ` _Self ` (rather than ` Self ` )
962
+ because using keywords in attributes used to not be permitted.
963
+
964
+ The compiler can provide several values to match on, for example:
965
+ - the self_ty, pretty printed with and without type arguments resolved.
966
+ - ` "{integral}" ` , if self_ty is an integral of which the type is known.
967
+ - ` "[]" ` , ` "[{ty}]" ` , ` "[{ty}; _]" ` , ` "[{ty}; $N]" ` when applicable.
968
+ - references to said slices and arrays.
969
+ - ` "fn" ` , ` "unsafe fn" ` or ` "#[target_feature] fn" ` when self is a function.
970
+ - ` "{integer}" ` and ` "{float}" ` if the type is a number but we haven't inferred it yet.
971
+ - combinations of the above, like ` "[{integral}; _]" ` .
972
+
973
+ For example, the ` Iterator ` trait can be filtered in the following way:
962
974
963
975
``` rust,ignore
964
976
#[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"
977
+ on(Self = "&str", note = "call `.chars()` or `.as_bytes()` on `{Self}`"),
978
+ message = "`{Self}` is not an iterator",
979
+ label = "`{Self}` is not an iterator",
980
+ note = "maybe try calling `.iter()` or a similar method"
972
981
)]
973
982
pub trait Iterator {}
974
983
```
@@ -997,15 +1006,47 @@ error[E0277]: `&str` is not an iterator
997
1006
= note: required by `std::iter::IntoIterator::into_iter`
998
1007
```
999
1008
1000
- If you need to filter on multiple attributes, you can use ` all ` , ` any ` or
1001
- ` not ` in the following way:
1009
+ The ` on ` filter accepts ` all ` , ` any ` and ` not ` predicates similar to the ` cfg ` attribute:
1002
1010
1003
1011
``` 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 { /* ... */ }
1012
+ #[rustc_on_unimplemented(on(
1013
+ all(Self = "&str", T = "alloc::string::String"),
1014
+ note = "you can coerce a `{T}` into a `{Self}` by writing `&*variable`"
1015
+ ))]
1016
+ pub trait From<T>: Sized {
1017
+ /* ... */
1018
+ }
1019
+ ```
1020
+
1021
+ ### Formatting
1022
+
1023
+ The string literals are format strings that accept parameters wrapped in braces
1024
+ but positional and listed parameters and format specifiers are not accepted.
1025
+ The following parameter names are valid:
1026
+ - ` Self ` and all generic parameters of the trait.
1027
+ - ` This ` : the name of the trait the attribute is on, without generics.
1028
+ - ` Trait ` : the name of the "sugared" trait. See ` TraitRefPrintSugared ` .
1029
+ - ` ItemContext ` : the kind of ` hir::Node ` we're in, things like ` "an async block" ` ,
1030
+ ` "a function" ` , ` "an async function" ` , etc.
1031
+
1032
+ Something like:
1033
+
1034
+ ``` rust,ignore
1035
+ #![feature(rustc_attrs)]
1036
+
1037
+ #[rustc_on_unimplemented(message = "Self = `{Self}`, \
1038
+ T = `{T}`, this = `{This}`, trait = `{Trait}`, \
1039
+ context = `{ItemContext}`")]
1040
+ pub trait From<T>: Sized {
1041
+ fn from(x: T) -> Self;
1042
+ }
1043
+
1044
+ fn main() {
1045
+ let x: i8 = From::from(42_i32);
1046
+ }
1047
+ ```
1048
+
1049
+ Will format the message into
1050
+ ``` text
1051
+ "Self = `i8`, T = `i32`, this = `From`, trait = `From<i32>`, context = `a function`"
1011
1052
```
0 commit comments