Skip to content

Commit 86717f2

Browse files
committed
Auto merge of rust-lang#12445 - y21:document-diagnostic-utils, r=xFrednet
add documentation to the `span_lint_hir` functions As far as I could tell, these weren't documented anywhere, and since this is sometimes needed over `span_lint` for `#[allow]` attrs to work, I thought I would add a little bit of documentation. When I started with clippy development, I also had no idea what these functions were for. changelog: none
2 parents 81debac + 5b1f95c commit 86717f2

File tree

3 files changed

+129
-5
lines changed

3 files changed

+129
-5
lines changed

clippy.toml

+8-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
avoid-breaking-exported-api = false
22

3-
# use the various `span_lint_*` methods instead, which also add a link to the docs
4-
disallowed-methods = [
5-
"rustc_lint::context::LintContext::span_lint",
6-
"rustc_middle::ty::context::TyCtxt::node_span_lint"
7-
]
3+
[[disallowed-methods]]
4+
path = "rustc_lint::context::LintContext::span_lint"
5+
reason = "this function does not add a link to our documentation, please use the `clippy_utils::diagnostics::span_lint*` functions instead"
6+
7+
8+
[[disallowed-methods]]
9+
path = "rustc_middle::ty::context::TyCtxt::node_span_lint"
10+
reason = "this function does not add a link to our documentation, please use the `clippy_utils::diagnostics::span_lint_hir*` functions instead"

clippy_utils/src/diagnostics.rs

+118
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,20 @@ fn docs_link(diag: &mut Diag<'_, ()>, lint: &'static Lint) {
3636
/// Usually it's nicer to provide more context for lint messages.
3737
/// Be sure the output is understandable when you use this method.
3838
///
39+
/// NOTE: Lint emissions are always bound to a node in the HIR, which is used to determine
40+
/// the lint level.
41+
/// For the `span_lint` function, the node that was passed into the `LintPass::check_*` function is
42+
/// used.
43+
///
44+
/// If you're emitting the lint at the span of a different node than the one provided by the
45+
/// `LintPass::check_*` function, consider using [`span_lint_hir`] instead.
46+
/// This is needed for `#[allow]` and `#[expect]` attributes to work on the node
47+
/// highlighted in the displayed warning.
48+
///
49+
/// If you're unsure which function you should use, you can test if the `#[allow]` attribute works
50+
/// where you would expect it to.
51+
/// If it doesn't, you likely need to use [`span_lint_hir`] instead.
52+
///
3953
/// # Example
4054
///
4155
/// ```ignore
@@ -61,6 +75,20 @@ pub fn span_lint<T: LintContext>(cx: &T, lint: &'static Lint, sp: impl Into<Mult
6175
///
6276
/// If you change the signature, remember to update the internal lint `CollapsibleCalls`
6377
///
78+
/// NOTE: Lint emissions are always bound to a node in the HIR, which is used to determine
79+
/// the lint level.
80+
/// For the `span_lint_and_help` function, the node that was passed into the `LintPass::check_*`
81+
/// function is used.
82+
///
83+
/// If you're emitting the lint at the span of a different node than the one provided by the
84+
/// `LintPass::check_*` function, consider using [`span_lint_hir_and_then`] instead.
85+
/// This is needed for `#[allow]` and `#[expect]` attributes to work on the node
86+
/// highlighted in the displayed warning.
87+
///
88+
/// If you're unsure which function you should use, you can test if the `#[allow]` attribute works
89+
/// where you would expect it to.
90+
/// If it doesn't, you likely need to use [`span_lint_hir_and_then`] instead.
91+
///
6492
/// # Example
6593
///
6694
/// ```text
@@ -99,6 +127,20 @@ pub fn span_lint_and_help<T: LintContext>(
99127
///
100128
/// If you change the signature, remember to update the internal lint `CollapsibleCalls`
101129
///
130+
/// NOTE: Lint emissions are always bound to a node in the HIR, which is used to determine
131+
/// the lint level.
132+
/// For the `span_lint_and_note` function, the node that was passed into the `LintPass::check_*`
133+
/// function is used.
134+
///
135+
/// If you're emitting the lint at the span of a different node than the one provided by the
136+
/// `LintPass::check_*` function, consider using [`span_lint_hir_and_then`] instead.
137+
/// This is needed for `#[allow]` and `#[expect]` attributes to work on the node
138+
/// highlighted in the displayed warning.
139+
///
140+
/// If you're unsure which function you should use, you can test if the `#[allow]` attribute works
141+
/// where you would expect it to.
142+
/// If it doesn't, you likely need to use [`span_lint_hir_and_then`] instead.
143+
///
102144
/// # Example
103145
///
104146
/// ```text
@@ -139,6 +181,20 @@ pub fn span_lint_and_note<T: LintContext>(
139181
///
140182
/// If you need to customize your lint output a lot, use this function.
141183
/// If you change the signature, remember to update the internal lint `CollapsibleCalls`
184+
///
185+
/// NOTE: Lint emissions are always bound to a node in the HIR, which is used to determine
186+
/// the lint level.
187+
/// For the `span_lint_and_then` function, the node that was passed into the `LintPass::check_*`
188+
/// function is used.
189+
///
190+
/// If you're emitting the lint at the span of a different node than the one provided by the
191+
/// `LintPass::check_*` function, consider using [`span_lint_hir_and_then`] instead.
192+
/// This is needed for `#[allow]` and `#[expect]` attributes to work on the node
193+
/// highlighted in the displayed warning.
194+
///
195+
/// If you're unsure which function you should use, you can test if the `#[allow]` attribute works
196+
/// where you would expect it to.
197+
/// If it doesn't, you likely need to use [`span_lint_hir_and_then`] instead.
142198
pub fn span_lint_and_then<C, S, F>(cx: &C, lint: &'static Lint, sp: S, msg: &str, f: F)
143199
where
144200
C: LintContext,
@@ -152,13 +208,61 @@ where
152208
});
153209
}
154210

211+
/// Like [`span_lint`], but emits the lint at the node identified by the given `HirId`.
212+
///
213+
/// This is in contrast to [`span_lint`], which always emits the lint at the node that was last
214+
/// passed to the `LintPass::check_*` function.
215+
///
216+
/// The `HirId` is used for checking lint level attributes and to fulfill lint expectations defined
217+
/// via the `#[expect]` attribute.
218+
///
219+
/// For example:
220+
/// ```ignore
221+
/// fn f() { /* <node_1> */
222+
///
223+
/// #[allow(clippy::some_lint)]
224+
/// let _x = /* <expr_1> */;
225+
/// }
226+
/// ```
227+
/// If `some_lint` does its analysis in `LintPass::check_fn` (at `<node_1>`) and emits a lint at
228+
/// `<expr_1>` using [`span_lint`], then allowing the lint at `<expr_1>` as attempted in the snippet
229+
/// will not work!
230+
/// Even though that is where the warning points at, which would be confusing to users.
231+
///
232+
/// Instead, use this function and also pass the `HirId` of `<expr_1>`, which will let
233+
/// the compiler check lint level attributes at the place of the expression and
234+
/// the `#[allow]` will work.
155235
pub fn span_lint_hir(cx: &LateContext<'_>, lint: &'static Lint, hir_id: HirId, sp: Span, msg: &str) {
156236
#[expect(clippy::disallowed_methods)]
157237
cx.tcx.node_span_lint(lint, hir_id, sp, msg.to_string(), |diag| {
158238
docs_link(diag, lint);
159239
});
160240
}
161241

242+
/// Like [`span_lint_and_then`], but emits the lint at the node identified by the given `HirId`.
243+
///
244+
/// This is in contrast to [`span_lint_and_then`], which always emits the lint at the node that was
245+
/// last passed to the `LintPass::check_*` function.
246+
///
247+
/// The `HirId` is used for checking lint level attributes and to fulfill lint expectations defined
248+
/// via the `#[expect]` attribute.
249+
///
250+
/// For example:
251+
/// ```ignore
252+
/// fn f() { /* <node_1> */
253+
///
254+
/// #[allow(clippy::some_lint)]
255+
/// let _x = /* <expr_1> */;
256+
/// }
257+
/// ```
258+
/// If `some_lint` does its analysis in `LintPass::check_fn` (at `<node_1>`) and emits a lint at
259+
/// `<expr_1>` using [`span_lint`], then allowing the lint at `<expr_1>` as attempted in the snippet
260+
/// will not work!
261+
/// Even though that is where the warning points at, which would be confusing to users.
262+
///
263+
/// Instead, use this function and also pass the `HirId` of `<expr_1>`, which will let
264+
/// the compiler check lint level attributes at the place of the expression and
265+
/// the `#[allow]` will work.
162266
pub fn span_lint_hir_and_then(
163267
cx: &LateContext<'_>,
164268
lint: &'static Lint,
@@ -182,6 +286,20 @@ pub fn span_lint_hir_and_then(
182286
///
183287
/// If you change the signature, remember to update the internal lint `CollapsibleCalls`
184288
///
289+
/// NOTE: Lint emissions are always bound to a node in the HIR, which is used to determine
290+
/// the lint level.
291+
/// For the `span_lint_and_sugg` function, the node that was passed into the `LintPass::check_*`
292+
/// function is used.
293+
///
294+
/// If you're emitting the lint at the span of a different node than the one provided by the
295+
/// `LintPass::check_*` function, consider using [`span_lint_hir_and_then`] instead.
296+
/// This is needed for `#[allow]` and `#[expect]` attributes to work on the node
297+
/// highlighted in the displayed warning.
298+
///
299+
/// If you're unsure which function you should use, you can test if the `#[allow]` attribute works
300+
/// where you would expect it to.
301+
/// If it doesn't, you likely need to use [`span_lint_hir_and_then`] instead.
302+
///
185303
/// # Example
186304
///
187305
/// ```text

tests/ui-internal/disallow_span_lint.stderr

+3
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ error: use of a disallowed method `rustc_lint::context::LintContext::span_lint`
44
LL | cx.span_lint(lint, span, msg, |_| {});
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66
|
7+
= note: this function does not add a link to our documentation, please use the `clippy_utils::diagnostics::span_lint*` functions instead (from clippy.toml)
78
= note: `-D clippy::disallowed-methods` implied by `-D warnings`
89
= help: to override `-D warnings` add `#[allow(clippy::disallowed_methods)]`
910

@@ -12,6 +13,8 @@ error: use of a disallowed method `rustc_middle::ty::context::TyCtxt::node_span_
1213
|
1314
LL | tcx.node_span_lint(lint, hir_id, span, msg, |_| {});
1415
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
16+
|
17+
= note: this function does not add a link to our documentation, please use the `clippy_utils::diagnostics::span_lint_hir*` functions instead (from clippy.toml)
1518

1619
error: aborting due to 2 previous errors
1720

0 commit comments

Comments
 (0)