@@ -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.
142198pub fn span_lint_and_then < C , S , F > ( cx : & C , lint : & ' static Lint , sp : S , msg : & str , f : F )
143199where
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.
155235pub 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.
162266pub 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
0 commit comments