Skip to content

Commit 588a04f

Browse files
committed
needless_return: Support #[expect] on the return statement
1 parent f24a870 commit 588a04f

File tree

4 files changed

+98
-29
lines changed

4 files changed

+98
-29
lines changed

clippy_lints/src/returns.rs

+32-9
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,21 @@ use clippy_utils::{
77
path_to_local_id, span_contains_cfg, span_find_starting_semi,
88
};
99
use core::ops::ControlFlow;
10+
use rustc_ast::NestedMetaItem;
1011
use rustc_errors::Applicability;
1112
use rustc_hir::intravisit::FnKind;
1213
use rustc_hir::LangItem::ResultErr;
1314
use rustc_hir::{
1415
Block, Body, Expr, ExprKind, FnDecl, HirId, ItemKind, LangItem, MatchSource, Node, OwnerNode, PatKind, QPath, Stmt,
1516
StmtKind,
1617
};
17-
use rustc_lint::{LateContext, LateLintPass, LintContext};
18+
use rustc_lint::{LateContext, LateLintPass, Level, LintContext};
1819
use rustc_middle::lint::in_external_macro;
1920
use rustc_middle::ty::adjustment::Adjust;
2021
use rustc_middle::ty::{self, GenericArgKind, Ty};
2122
use rustc_session::declare_lint_pass;
2223
use rustc_span::def_id::LocalDefId;
23-
use rustc_span::{BytePos, Pos, Span};
24+
use rustc_span::{sym, BytePos, Pos, Span};
2425
use std::borrow::Cow;
2526
use std::fmt::Display;
2627

@@ -91,6 +92,9 @@ declare_clippy_lint! {
9192
/// ### Why is this bad?
9293
/// The `return` is unnecessary.
9394
///
95+
/// Returns may be used to add attributes to the return expression. Return
96+
/// statements with attributes are therefore be accepted by this lint.
97+
///
9498
/// ### Example
9599
/// ```rust,ignore
96100
/// fn foo(x: usize) -> Result<(), Box<dyn Error>> {
@@ -377,13 +381,36 @@ fn check_final_expr<'tcx>(
377381
}
378382
};
379383

380-
if !cx.tcx.hir().attrs(expr.hir_id).is_empty() {
381-
return;
382-
}
383384
let borrows = inner.map_or(false, |inner| last_statement_borrows(cx, inner));
384385
if borrows {
385386
return;
386387
}
388+
if ret_span.from_expansion() {
389+
return;
390+
}
391+
392+
// Returns may be used to turn an expression into a statement in rustc's AST.
393+
// This allows the addition of attributes, like `#[allow]` (See: clippy#9361)
394+
// `#[expect(clippy::needless_return)]` needs to be handled separatly to
395+
// actually fullfil the expectation (clippy::#12998)
396+
match cx.tcx.hir().attrs(expr.hir_id) {
397+
[] => {},
398+
[attr] => {
399+
if matches!(Level::from_attr(attr), Some(Level::Expect(_)))
400+
&& let metas = attr.meta_item_list()
401+
&& let Some(lst) = metas
402+
&& let [NestedMetaItem::MetaItem(meta_item)] = lst.as_slice()
403+
&& let [tool, lint_name] = meta_item.path.segments.as_slice()
404+
&& tool.ident.name == sym::clippy
405+
&& matches!(lint_name.ident.name.as_str(), "needless_return" | "style" | "all")
406+
{
407+
// This is an expectation of the `needless_return` lint
408+
} else {
409+
return;
410+
}
411+
},
412+
_ => return,
413+
}
387414

388415
emit_return_lint(cx, ret_span, semi_spans, &replacement, expr.hir_id);
389416
},
@@ -415,10 +442,6 @@ fn emit_return_lint(
415442
replacement: &RetReplacement<'_>,
416443
at: HirId,
417444
) {
418-
if ret_span.from_expansion() {
419-
return;
420-
}
421-
422445
span_lint_hir_and_then(
423446
cx,
424447
NEEDLESS_RETURN,

tests/ui/needless_return.fixed

+26-3
Original file line numberDiff line numberDiff line change
@@ -228,12 +228,35 @@ fn needless_return_macro() -> String {
228228
format!("Hello {}", "world!")
229229
}
230230

231-
fn issue_9361() -> i32 {
232-
let n = 1;
233-
#[allow(clippy::arithmetic_side_effects)]
231+
fn issue_9361(n: i32) -> i32 {
232+
#[expect(clippy::arithmetic_side_effects)]
234233
return n + n;
235234
}
236235

236+
mod issue_12998 {
237+
238+
fn expect_lint() -> i32 {
239+
let x = 1;
240+
241+
#[expect(clippy::needless_return)]
242+
return x;
243+
}
244+
245+
fn expect_group() -> i32 {
246+
let x = 1;
247+
248+
#[expect(clippy::style)]
249+
return x;
250+
}
251+
252+
fn expect_all() -> i32 {
253+
let x = 1;
254+
255+
#[expect(clippy::all)]
256+
return x;
257+
}
258+
}
259+
237260
fn issue8336(x: i32) -> bool {
238261
if x > 0 {
239262
println!("something");

tests/ui/needless_return.rs

+26-3
Original file line numberDiff line numberDiff line change
@@ -236,12 +236,35 @@ fn needless_return_macro() -> String {
236236
return format!("Hello {}", "world!");
237237
}
238238

239-
fn issue_9361() -> i32 {
240-
let n = 1;
241-
#[allow(clippy::arithmetic_side_effects)]
239+
fn issue_9361(n: i32) -> i32 {
240+
#[expect(clippy::arithmetic_side_effects)]
242241
return n + n;
243242
}
244243

244+
mod issue_12998 {
245+
246+
fn expect_lint() -> i32 {
247+
let x = 1;
248+
249+
#[expect(clippy::needless_return)]
250+
return x;
251+
}
252+
253+
fn expect_group() -> i32 {
254+
let x = 1;
255+
256+
#[expect(clippy::style)]
257+
return x;
258+
}
259+
260+
fn expect_all() -> i32 {
261+
let x = 1;
262+
263+
#[expect(clippy::all)]
264+
return x;
265+
}
266+
}
267+
245268
fn issue8336(x: i32) -> bool {
246269
if x > 0 {
247270
println!("something");

tests/ui/needless_return.stderr

+14-14
Original file line numberDiff line numberDiff line change
@@ -483,7 +483,7 @@ LL + format!("Hello {}", "world!")
483483
|
484484

485485
error: unneeded `return` statement
486-
--> tests/ui/needless_return.rs:248:9
486+
--> tests/ui/needless_return.rs:271:9
487487
|
488488
LL | return true;
489489
| ^^^^^^^^^^^
@@ -497,7 +497,7 @@ LL ~ }
497497
|
498498

499499
error: unneeded `return` statement
500-
--> tests/ui/needless_return.rs:250:9
500+
--> tests/ui/needless_return.rs:273:9
501501
|
502502
LL | return false;
503503
| ^^^^^^^^^^^^
@@ -509,7 +509,7 @@ LL ~ }
509509
|
510510

511511
error: unneeded `return` statement
512-
--> tests/ui/needless_return.rs:257:13
512+
--> tests/ui/needless_return.rs:280:13
513513
|
514514
LL | return 10;
515515
| ^^^^^^^^^
@@ -524,7 +524,7 @@ LL ~ }
524524
|
525525

526526
error: unneeded `return` statement
527-
--> tests/ui/needless_return.rs:260:13
527+
--> tests/ui/needless_return.rs:283:13
528528
|
529529
LL | return 100;
530530
| ^^^^^^^^^^
@@ -537,7 +537,7 @@ LL ~ }
537537
|
538538

539539
error: unneeded `return` statement
540-
--> tests/ui/needless_return.rs:268:9
540+
--> tests/ui/needless_return.rs:291:9
541541
|
542542
LL | return 0;
543543
| ^^^^^^^^
@@ -549,7 +549,7 @@ LL ~ }
549549
|
550550

551551
error: unneeded `return` statement
552-
--> tests/ui/needless_return.rs:275:13
552+
--> tests/ui/needless_return.rs:298:13
553553
|
554554
LL | return *(x as *const isize);
555555
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -564,7 +564,7 @@ LL ~ }
564564
|
565565

566566
error: unneeded `return` statement
567-
--> tests/ui/needless_return.rs:277:13
567+
--> tests/ui/needless_return.rs:300:13
568568
|
569569
LL | return !*(x as *const isize);
570570
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -577,7 +577,7 @@ LL ~ }
577577
|
578578

579579
error: unneeded `return` statement
580-
--> tests/ui/needless_return.rs:284:20
580+
--> tests/ui/needless_return.rs:307:20
581581
|
582582
LL | let _ = 42;
583583
| ____________________^
@@ -594,7 +594,7 @@ LL + let _ = 42;
594594
|
595595

596596
error: unneeded `return` statement
597-
--> tests/ui/needless_return.rs:291:20
597+
--> tests/ui/needless_return.rs:314:20
598598
|
599599
LL | let _ = 42; return;
600600
| ^^^^^^^
@@ -606,7 +606,7 @@ LL + let _ = 42;
606606
|
607607

608608
error: unneeded `return` statement
609-
--> tests/ui/needless_return.rs:303:9
609+
--> tests/ui/needless_return.rs:326:9
610610
|
611611
LL | return Ok(format!("ok!"));
612612
| ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -618,7 +618,7 @@ LL + Ok(format!("ok!"))
618618
|
619619

620620
error: unneeded `return` statement
621-
--> tests/ui/needless_return.rs:305:9
621+
--> tests/ui/needless_return.rs:328:9
622622
|
623623
LL | return Err(format!("err!"));
624624
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -630,7 +630,7 @@ LL + Err(format!("err!"))
630630
|
631631

632632
error: unneeded `return` statement
633-
--> tests/ui/needless_return.rs:311:9
633+
--> tests/ui/needless_return.rs:334:9
634634
|
635635
LL | return if true { 1 } else { 2 };
636636
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -642,7 +642,7 @@ LL + if true { 1 } else { 2 }
642642
|
643643

644644
error: unneeded `return` statement
645-
--> tests/ui/needless_return.rs:315:9
645+
--> tests/ui/needless_return.rs:338:9
646646
|
647647
LL | return if b1 { 0 } else { 1 } | if b2 { 2 } else { 3 } | if b3 { 4 } else { 5 };
648648
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -654,7 +654,7 @@ LL + (if b1 { 0 } else { 1 } | if b2 { 2 } else { 3 } | if b3 { 4 } else
654654
|
655655

656656
error: unneeded `return` statement
657-
--> tests/ui/needless_return.rs:336:5
657+
--> tests/ui/needless_return.rs:359:5
658658
|
659659
LL | return { "a".to_string() } + "b" + { "c" };
660660
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

0 commit comments

Comments
 (0)