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