Improve the "Diagnostic items" chapter (#1427)
This commit is contained in:
parent
452b5abdd6
commit
d3daa1f28e
|
|
@ -1,4 +1,5 @@
|
|||
# Diagnostic Items
|
||||
|
||||
While writing lints it's common to check for specific types, traits and
|
||||
functions. This raises the question on how to check for these. Types can be
|
||||
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
|
|||
[`Symbol`]s.
|
||||
|
||||
## Finding diagnostic items
|
||||
Diagnostic items are added to items inside `rustc`/`std`/`core` with the
|
||||
|
||||
Diagnostic items are added to items inside `rustc`/`std`/`core`/`alloc` with the
|
||||
`rustc_diagnostic_item` attribute. The item for a specific type can be found by
|
||||
opening the source code in the documentation and looking for this attribute.
|
||||
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:
|
|||
struct Penguin;
|
||||
```
|
||||
|
||||
Diagnostic items are usually only added to traits, types and standalone
|
||||
functions. If the goal is to check for an associated type or method, please use
|
||||
the diagnostic item of the item and reference [*How To Use Diagnostic
|
||||
Items*](#how-to-use-diagnostic-items).
|
||||
Diagnostic items are usually only added to traits,
|
||||
types,
|
||||
and standalone functions.
|
||||
If the goal is to check for an associated type or method,
|
||||
please use the diagnostic item of the item and reference
|
||||
[*Using Diagnostic Items*](#using-diagnostic-items).
|
||||
|
||||
## Adding diagnostic items
|
||||
|
||||
A new diagnostic item can be added with these two steps:
|
||||
|
||||
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:
|
|||
For the naming conventions of diagnostic items, please refer to
|
||||
[*Naming Conventions*](#naming-conventions).
|
||||
|
||||
2. As of <!-- date-check --> February 2022, diagnostic items in code are
|
||||
accessed via symbols in [`rustc_span::symbol::sym`]. To add your newly
|
||||
created diagnostic item simply open the module file and add the name (In
|
||||
this case `Cat`) at the correct point in the list.
|
||||
2. <!-- date-check: Aug 2022 -->
|
||||
Diagnostic items in code are accessed via symbols in
|
||||
[`rustc_span::symbol::sym`].
|
||||
To add your newly-created diagnostic item,
|
||||
simply open the module file,
|
||||
and add the name (In this case `Cat`) at the correct point in the list.
|
||||
|
||||
Now you can create a pull request with your changes. :tada: (Note that when
|
||||
using diagnostic items in other projects like Clippy, it might take some time
|
||||
until the repos get synchronized.)
|
||||
Now you can create a pull request with your changes. :tada:
|
||||
|
||||
> NOTE:
|
||||
> When using diagnostic items in other projects like Clippy,
|
||||
> it might take some time until the repos get synchronized.
|
||||
|
||||
## Naming conventions
|
||||
Diagnostic items don't have a set in stone naming convention yet. These are
|
||||
some guidelines that should be used for the future, but might differ from
|
||||
existing names:
|
||||
|
||||
* Types, traits and enums are named using UpperCamelCase (Examples: `Iterator`,
|
||||
* `HashMap`, ...)
|
||||
* For type names that are used multiple times like `Writer` it's good to choose
|
||||
a more precise name, maybe by adding the module to it. (Example: `IoWriter`)
|
||||
* Associated items should not get their own diagnostic items, but instead be
|
||||
accessed indirectly by the diagnostic item of the type they're originating
|
||||
from.
|
||||
Diagnostic items don't have a naming convention yet.
|
||||
Following are some guidelines that should be used in future,
|
||||
but might differ from existing names:
|
||||
|
||||
* Types, traits, and enums are named using UpperCamelCase
|
||||
(Examples: `Iterator` and `HashMap`)
|
||||
* For type names that are used multiple times,
|
||||
like `Writer`,
|
||||
it's good to choose a more precise name,
|
||||
maybe by adding the module to it
|
||||
(Example: `IoWriter`)
|
||||
* Associated items should not get their own diagnostic items,
|
||||
but instead be accessed indirectly by the diagnostic item
|
||||
of the type they're originating from.
|
||||
* Freestanding functions like `std::mem::swap()` should be named using
|
||||
`snake_case` with one important (export) module as a prefix (Example:
|
||||
`mem_swap`, `cmp_max`)
|
||||
`snake_case` with one important (export) module as a prefix
|
||||
(Examples: `mem_swap` and `cmp_max`)
|
||||
* Modules should usually not have a diagnostic item attached to them.
|
||||
Diagnostic items were added to avoid the usage of paths, using them on
|
||||
modules would therefore most likely to be counterproductive.
|
||||
Diagnostic items were added to avoid the usage of paths,
|
||||
and using them on modules would therefore most likely be counterproductive.
|
||||
|
||||
## Using diagnostic items
|
||||
|
||||
In rustc, diagnostic items are looked up via [`Symbol`]s from inside the
|
||||
[`rustc_span::symbol::sym`] module. These can then be mapped to [`DefId`]s
|
||||
using [`TyCtxt::get_diagnostic_item()`] or checked if they match a [`DefId`]
|
||||
using [`TyCtxt::is_diagnostic_item()`]. When mapping from a diagnostic item to
|
||||
a [`DefId`], the method will return a `Option<DefId>`. This can be `None` if
|
||||
either the symbol isn't a diagnostic item or the type is not registered, for
|
||||
instance when compiling with `#[no_std]`. All following examples are based on
|
||||
[`DefId`]s and their usage.
|
||||
instance when compiling with `#[no_std]`.
|
||||
All the following examples are based on [`DefId`]s and their usage.
|
||||
|
||||
### Example: Checking for a type
|
||||
|
||||
```rust
|
||||
use rustc_span::symbol::sym;
|
||||
|
||||
|
|
@ -96,6 +111,7 @@ fn example_1(cx: &LateContext<'_>, ty: Ty<'_>) -> bool {
|
|||
```
|
||||
|
||||
### Example: Checking for a trait implementation
|
||||
|
||||
```rust
|
||||
/// This example checks if a given [`DefId`] from a method is part of a trait
|
||||
/// implementation defined by a diagnostic item.
|
||||
|
|
@ -112,6 +128,7 @@ fn is_diag_trait_item(
|
|||
```
|
||||
|
||||
### Associated Types
|
||||
|
||||
Associated types of diagnostic items can be accessed indirectly by first
|
||||
getting the [`DefId`] of the trait and then calling
|
||||
[`TyCtxt::associated_items()`]. This returns an [`AssocItems`] object which can
|
||||
|
|
@ -119,13 +136,15 @@ be used for further checks. Checkout
|
|||
[`clippy_utils::ty::get_iterator_item_ty()`] for an example usage of this.
|
||||
|
||||
### Usage in Clippy
|
||||
|
||||
Clippy tries to use diagnostic items where possible and has developed some
|
||||
wrapper and utility functions. Please also refer to its documentation when
|
||||
using diagnostic items in Clippy. (See [*Common tools for writing
|
||||
lints*][clippy-Common-tools-for-writing-lints].)
|
||||
|
||||
## Related issues
|
||||
This lists some related issues. These are probably only interesting to people
|
||||
|
||||
These are probably only interesting to people
|
||||
who really want to take a deep dive into the topic :)
|
||||
|
||||
* [rust#60966]: The Rust PR that introduced diagnostic items
|
||||
|
|
|
|||
Loading…
Reference in New Issue