Skip to content

Commit d3daa1f

Browse files
authored
Improve the "Diagnostic items" chapter (#1427)
1 parent 452b5ab commit d3daa1f

File tree

1 file changed

+49
-30
lines changed

1 file changed

+49
-30
lines changed

src/diagnostics/diagnostic-items.md

+49-30
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# Diagnostic Items
2+
23
While writing lints it's common to check for specific types, traits and
34
functions. This raises the question on how to check for these. Types can be
45
checked by their complete type path. However, this requires hard coding paths
@@ -7,7 +8,8 @@ rustc has introduced diagnostic items that are used to identify types via
78
[`Symbol`]s.
89

910
## Finding diagnostic items
10-
Diagnostic items are added to items inside `rustc`/`std`/`core` with the
11+
12+
Diagnostic items are added to items inside `rustc`/`std`/`core`/`alloc` with the
1113
`rustc_diagnostic_item` attribute. The item for a specific type can be found by
1214
opening the source code in the documentation and looking for this attribute.
1315
Note that it's often added with the `cfg_attr` attribute to avoid compilation
@@ -19,12 +21,15 @@ errors during tests. A definition often looks like this:
1921
struct Penguin;
2022
```
2123

22-
Diagnostic items are usually only added to traits, types and standalone
23-
functions. If the goal is to check for an associated type or method, please use
24-
the diagnostic item of the item and reference [*How To Use Diagnostic
25-
Items*](#how-to-use-diagnostic-items).
24+
Diagnostic items are usually only added to traits,
25+
types,
26+
and standalone functions.
27+
If the goal is to check for an associated type or method,
28+
please use the diagnostic item of the item and reference
29+
[*Using Diagnostic Items*](#using-diagnostic-items).
2630

2731
## Adding diagnostic items
32+
2833
A new diagnostic item can be added with these two steps:
2934

3035
1. Find the target item inside the Rust repo. Now add the diagnostic item as a
@@ -43,45 +48,55 @@ A new diagnostic item can be added with these two steps:
4348
For the naming conventions of diagnostic items, please refer to
4449
[*Naming Conventions*](#naming-conventions).
4550

46-
2. As of <!-- date-check --> February 2022, diagnostic items in code are
47-
accessed via symbols in [`rustc_span::symbol::sym`]. To add your newly
48-
created diagnostic item simply open the module file and add the name (In
49-
this case `Cat`) at the correct point in the list.
51+
2. <!-- date-check: Aug 2022 -->
52+
Diagnostic items in code are accessed via symbols in
53+
[`rustc_span::symbol::sym`].
54+
To add your newly-created diagnostic item,
55+
simply open the module file,
56+
and add the name (In this case `Cat`) at the correct point in the list.
5057

51-
Now you can create a pull request with your changes. :tada: (Note that when
52-
using diagnostic items in other projects like Clippy, it might take some time
53-
until the repos get synchronized.)
58+
Now you can create a pull request with your changes. :tada:
59+
60+
> NOTE:
61+
> When using diagnostic items in other projects like Clippy,
62+
> it might take some time until the repos get synchronized.
5463

5564
## Naming conventions
56-
Diagnostic items don't have a set in stone naming convention yet. These are
57-
some guidelines that should be used for the future, but might differ from
58-
existing names:
59-
60-
* Types, traits and enums are named using UpperCamelCase (Examples: `Iterator`,
61-
* `HashMap`, ...)
62-
* For type names that are used multiple times like `Writer` it's good to choose
63-
a more precise name, maybe by adding the module to it. (Example: `IoWriter`)
64-
* Associated items should not get their own diagnostic items, but instead be
65-
accessed indirectly by the diagnostic item of the type they're originating
66-
from.
65+
66+
Diagnostic items don't have a naming convention yet.
67+
Following are some guidelines that should be used in future,
68+
but might differ from existing names:
69+
70+
* Types, traits, and enums are named using UpperCamelCase
71+
(Examples: `Iterator` and `HashMap`)
72+
* For type names that are used multiple times,
73+
like `Writer`,
74+
it's good to choose a more precise name,
75+
maybe by adding the module to it
76+
(Example: `IoWriter`)
77+
* Associated items should not get their own diagnostic items,
78+
but instead be accessed indirectly by the diagnostic item
79+
of the type they're originating from.
6780
* Freestanding functions like `std::mem::swap()` should be named using
68-
`snake_case` with one important (export) module as a prefix (Example:
69-
`mem_swap`, `cmp_max`)
81+
`snake_case` with one important (export) module as a prefix
82+
(Examples: `mem_swap` and `cmp_max`)
7083
* Modules should usually not have a diagnostic item attached to them.
71-
Diagnostic items were added to avoid the usage of paths, using them on
72-
modules would therefore most likely to be counterproductive.
84+
Diagnostic items were added to avoid the usage of paths,
85+
and using them on modules would therefore most likely be counterproductive.
7386

7487
## Using diagnostic items
88+
7589
In rustc, diagnostic items are looked up via [`Symbol`]s from inside the
7690
[`rustc_span::symbol::sym`] module. These can then be mapped to [`DefId`]s
7791
using [`TyCtxt::get_diagnostic_item()`] or checked if they match a [`DefId`]
7892
using [`TyCtxt::is_diagnostic_item()`]. When mapping from a diagnostic item to
7993
a [`DefId`], the method will return a `Option<DefId>`. This can be `None` if
8094
either the symbol isn't a diagnostic item or the type is not registered, for
81-
instance when compiling with `#[no_std]`. All following examples are based on
82-
[`DefId`]s and their usage.
95+
instance when compiling with `#[no_std]`.
96+
All the following examples are based on [`DefId`]s and their usage.
8397

8498
### Example: Checking for a type
99+
85100
```rust
86101
use rustc_span::symbol::sym;
87102

@@ -96,6 +111,7 @@ fn example_1(cx: &LateContext<'_>, ty: Ty<'_>) -> bool {
96111
```
97112

98113
### Example: Checking for a trait implementation
114+
99115
```rust
100116
/// This example checks if a given [`DefId`] from a method is part of a trait
101117
/// implementation defined by a diagnostic item.
@@ -112,20 +128,23 @@ fn is_diag_trait_item(
112128
```
113129

114130
### Associated Types
131+
115132
Associated types of diagnostic items can be accessed indirectly by first
116133
getting the [`DefId`] of the trait and then calling
117134
[`TyCtxt::associated_items()`]. This returns an [`AssocItems`] object which can
118135
be used for further checks. Checkout
119136
[`clippy_utils::ty::get_iterator_item_ty()`] for an example usage of this.
120137

121138
### Usage in Clippy
139+
122140
Clippy tries to use diagnostic items where possible and has developed some
123141
wrapper and utility functions. Please also refer to its documentation when
124142
using diagnostic items in Clippy. (See [*Common tools for writing
125143
lints*][clippy-Common-tools-for-writing-lints].)
126144

127145
## Related issues
128-
This lists some related issues. These are probably only interesting to people
146+
147+
These are probably only interesting to people
129148
who really want to take a deep dive into the topic :)
130149

131150
* [rust#60966]: The Rust PR that introduced diagnostic items

0 commit comments

Comments
 (0)