Skip to content

Commit 84a4ab7

Browse files
committed
Auto merge of #7928 - xFrednet:rust-90354-deploy-clippy-docs, r=flip1995
Reference `clippy_utils` docs on nightly-rustc and some other documentation updates The `clippy_utils` crate is now part of the nightly-rustc documentation. See [**very beautiful documentation**](https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/). This PR references them in our documentation and updates some other documentation. changelog: none
2 parents e181011 + 5405152 commit 84a4ab7

File tree

4 files changed

+80
-14
lines changed

4 files changed

+80
-14
lines changed

clippy_utils/src/source.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -155,14 +155,22 @@ fn reindent_multiline_inner(s: &str, ignore_first: bool, indent: Option<usize>,
155155
.join("\n")
156156
}
157157

158-
/// Converts a span to a code snippet if available, otherwise use default.
158+
/// Converts a span to a code snippet if available, otherwise returns the default.
159159
///
160160
/// This is useful if you want to provide suggestions for your lint or more generally, if you want
161-
/// to convert a given `Span` to a `str`.
161+
/// to convert a given `Span` to a `str`. To create suggestions consider using
162+
/// [`snippet_with_applicability`] to ensure that the applicability stays correct.
162163
///
163164
/// # Example
164165
/// ```rust,ignore
165-
/// snippet(cx, expr.span, "..")
166+
/// // Given two spans one for `value` and one for the `init` expression.
167+
/// let value = Vec::new();
168+
/// // ^^^^^ ^^^^^^^^^^
169+
/// // span1 span2
170+
///
171+
/// // The snipped call would return the corresponding code snippet
172+
/// snippet(cx, span1, "..") // -> "value"
173+
/// snippet(cx, span2, "..") // -> "Vec::new()"
166174
/// ```
167175
pub fn snippet<'a, T: LintContext>(cx: &T, span: Span, default: &'a str) -> Cow<'a, str> {
168176
snippet_opt(cx, span).map_or_else(|| Cow::Borrowed(default), From::from)

clippy_utils/src/ty.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,12 @@ pub fn has_iter_method(cx: &LateContext<'_>, probably_ref_ty: Ty<'_>) -> Option<
114114

115115
/// Checks whether a type implements a trait.
116116
/// The function returns false in case the type contains an inference variable.
117-
/// See also [`get_trait_def_id`](super::get_trait_def_id).
117+
///
118+
/// See:
119+
/// * [`get_trait_def_id`](super::get_trait_def_id) to get a trait [`DefId`].
120+
/// * [Common tools for writing lints] for an example how to use this function and other options.
121+
///
122+
/// [Common tools for writing lints]: https://github.com/rust-lang/rust-clippy/blob/master/doc/common_tools_writing_lints.md#checking-if-a-type-implements-a-specific-trait
118123
pub fn implements_trait<'tcx>(
119124
cx: &LateContext<'tcx>,
120125
ty: Ty<'tcx>,
@@ -254,9 +259,17 @@ pub fn is_type_ref_to_diagnostic_item(cx: &LateContext<'_>, ty: Ty<'_>, diag_ite
254259
}
255260
}
256261

257-
/// Checks if the type is equal to a diagnostic item
262+
/// Checks if the type is equal to a diagnostic item. To check if a type implements a
263+
/// trait marked with a diagnostic item use [`implements_trait`].
264+
///
265+
/// For a further exploitation what diagnostic items are see [diagnostic items] in
266+
/// rustc-dev-guide.
267+
///
268+
/// ---
258269
///
259270
/// If you change the signature, remember to update the internal lint `MatchTypeOnDiagItem`
271+
///
272+
/// [Diagnostic Items]: https://rustc-dev-guide.rust-lang.org/diagnostics/diagnostic-items.html
260273
pub fn is_type_diagnostic_item(cx: &LateContext<'_>, ty: Ty<'_>, diag_item: Symbol) -> bool {
261274
match ty.kind() {
262275
ty::Adt(adt, _) => cx.tcx.is_diagnostic_item(diag_item, adt.did),

doc/adding_lints.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -634,7 +634,7 @@ in the following steps:
634634
Here are some pointers to things you are likely going to need for every lint:
635635

636636
* [Clippy utils][utils] - Various helper functions. Maybe the function you need
637-
is already in here (`implements_trait`, `match_def_path`, `snippet`, etc)
637+
is already in here ([`is_type_diagnostic_item`], [`implements_trait`], [`snippet`], etc)
638638
* [Clippy diagnostics][diagnostics]
639639
* [The `if_chain` macro][if_chain]
640640
* [`from_expansion`][from_expansion] and [`in_external_macro`][in_external_macro]
@@ -660,7 +660,10 @@ documentation currently. This is unfortunate, but in most cases you can probably
660660
get away with copying things from existing similar lints. If you are stuck,
661661
don't hesitate to ask on [Zulip] or in the issue/PR.
662662

663-
[utils]: https://github.com/rust-lang/rust-clippy/blob/master/clippy_utils/src/lib.rs
663+
[utils]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/index.html
664+
[`is_type_diagnostic_item`]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/ty/fn.is_type_diagnostic_item.html
665+
[`implements_trait`]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/ty/fn.implements_trait.html
666+
[`snippet`]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/source/fn.snippet.html
664667
[if_chain]: https://docs.rs/if_chain/*/if_chain/
665668
[from_expansion]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/struct.Span.html#method.from_expansion
666669
[in_external_macro]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/lint/fn.in_external_macro.html

doc/common_tools_writing_lints.md

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ You may need following tooltips to catch up with common operations.
44

55
- [Common tools for writing lints](#common-tools-for-writing-lints)
66
- [Retrieving the type of an expression](#retrieving-the-type-of-an-expression)
7-
- [Checking if an expression is calling a specific method](#checking-if-an-expr-is-calling-a-specific-method)
7+
- [Checking if an expr is calling a specific method](#checking-if-an-expr-is-calling-a-specific-method)
8+
- [Checking for a specific type](#checking-for-a-specific-type)
89
- [Checking if a type implements a specific trait](#checking-if-a-type-implements-a-specific-trait)
910
- [Checking if a type defines a specific method](#checking-if-a-type-defines-a-specific-method)
1011
- [Dealing with macros](#dealing-with-macros)
@@ -15,7 +16,7 @@ Useful Rustc dev guide links:
1516
- [Type checking](https://rustc-dev-guide.rust-lang.org/type-checking.html)
1617
- [Ty module](https://rustc-dev-guide.rust-lang.org/ty.html)
1718

18-
# Retrieving the type of an expression
19+
## Retrieving the type of an expression
1920

2021
Sometimes you may want to retrieve the type `Ty` of an expression `Expr`, for example to answer following questions:
2122

@@ -54,7 +55,7 @@ Two noticeable items here:
5455
created by type checking step, it includes useful information such as types
5556
of expressions, ways to resolve methods and so on.
5657

57-
# Checking if an expr is calling a specific method
58+
## Checking if an expr is calling a specific method
5859

5960
Starting with an `expr`, you can check whether it is calling a specific method `some_method`:
6061

@@ -63,9 +64,11 @@ impl LateLintPass<'_> for MyStructLint {
6364
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
6465
if_chain! {
6566
// Check our expr is calling a method
66-
if let hir::ExprKind::MethodCall(path, _, _args, _) = &expr.kind;
67+
if let hir::ExprKind::MethodCall(path, _, [_self_arg, ..], _) = &expr.kind;
6768
// Check the name of this method is `some_method`
6869
if path.ident.name == sym!(some_method);
70+
// Optionally, check the type of the self argument.
71+
// - See "Checking for a specific type"
6972
then {
7073
// ...
7174
}
@@ -74,7 +77,45 @@ impl LateLintPass<'_> for MyStructLint {
7477
}
7578
```
7679

77-
# Checking if a type implements a specific trait
80+
## Checking for a specific type
81+
82+
There are three ways to check if an expression type is a specific type we want to check for.
83+
All of these methods only check for the base type, generic arguments have to be checked separately.
84+
85+
```rust
86+
use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item};
87+
use clippy_utils::{paths, match_def_path};
88+
use rustc_span::symbol::sym;
89+
use rustc_hir::LangItem;
90+
91+
impl LateLintPass<'_> for MyStructLint {
92+
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
93+
// Getting the expression type
94+
let ty = cx.typeck_results().expr_ty(expr);
95+
96+
// 1. Using diagnostic items
97+
// The last argument is the diagnostic item to check for
98+
if is_type_diagnostic_item(cx, ty, sym::Option) {
99+
// The type is an `Option`
100+
}
101+
102+
// 2. Using lang items
103+
if is_type_lang_item(cx, ty, LangItem::RangeFull) {
104+
// The type is a full range like `.drain(..)`
105+
}
106+
107+
// 3. Using the type path
108+
// This method should be avoided if possible
109+
if match_def_path(cx, def_id, &paths::RESULT) {
110+
// The type is a `core::result::Result`
111+
}
112+
}
113+
}
114+
```
115+
116+
Prefer using diagnostic items and lang items where possible.
117+
118+
## Checking if a type implements a specific trait
78119

79120
There are three ways to do this, depending on if the target trait has a diagnostic item, lang item or neither.
80121

@@ -102,6 +143,7 @@ impl LateLintPass<'_> for MyStructLint {
102143

103144
// 3. Using the type path with the expression
104145
// we use `match_trait_method` function from Clippy's utils
146+
// (This method should be avoided if possible)
105147
if match_trait_method(cx, expr, &paths::INTO) {
106148
// `expr` implements `Into` trait
107149
}
@@ -114,7 +156,7 @@ impl LateLintPass<'_> for MyStructLint {
114156
We access lang items through the type context `tcx`. `tcx` is of type [`TyCtxt`][TyCtxt] and is defined in the `rustc_middle` crate.
115157
A list of defined paths for Clippy can be found in [paths.rs][paths]
116158

117-
# Checking if a type defines a specific method
159+
## Checking if a type defines a specific method
118160

119161
To check if our type defines a method called `some_method`:
120162

@@ -140,7 +182,7 @@ impl<'tcx> LateLintPass<'tcx> for MyTypeImpl {
140182
}
141183
```
142184

143-
# Dealing with macros
185+
## Dealing with macros
144186

145187
There are several helpers in [`clippy_utils`][utils] to deal with macros:
146188

0 commit comments

Comments
 (0)