let_and_return: lint more cases in edition ≥ 2024
This commit is contained in:
parent
657dda7b50
commit
5d2fe079ab
7 changed files with 923 additions and 6 deletions
|
|
@ -199,7 +199,7 @@ impl<'a, 'tcx> SigDropChecker<'a, 'tcx> {
|
|||
return false;
|
||||
}
|
||||
|
||||
let result = match ty.kind() {
|
||||
match ty.kind() {
|
||||
rustc_middle::ty::Adt(adt, args) => {
|
||||
// if some field has significant drop,
|
||||
adt.all_fields()
|
||||
|
|
@ -223,9 +223,7 @@ impl<'a, 'tcx> SigDropChecker<'a, 'tcx> {
|
|||
rustc_middle::ty::Tuple(tys) => tys.iter().any(|ty| self.has_sig_drop_attr_impl(ty)),
|
||||
rustc_middle::ty::Array(ty, _) | rustc_middle::ty::Slice(ty) => self.has_sig_drop_attr_impl(*ty),
|
||||
_ => false,
|
||||
};
|
||||
|
||||
result
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ use rustc_middle::ty::adjustment::Adjust;
|
|||
use rustc_middle::ty::{self, GenericArgKind, Ty};
|
||||
use rustc_session::declare_lint_pass;
|
||||
use rustc_span::def_id::LocalDefId;
|
||||
use rustc_span::edition::Edition;
|
||||
use rustc_span::{BytePos, Pos, Span, sym};
|
||||
use std::borrow::Cow;
|
||||
use std::fmt::Display;
|
||||
|
|
@ -235,7 +236,7 @@ impl<'tcx> LateLintPass<'tcx> for Return {
|
|||
&& let Some(initexpr) = &local.init
|
||||
&& let PatKind::Binding(_, local_id, _, _) = local.pat.kind
|
||||
&& path_to_local_id(retexpr, local_id)
|
||||
&& !last_statement_borrows(cx, initexpr)
|
||||
&& (cx.sess().edition() >= Edition::Edition2024 || !last_statement_borrows(cx, initexpr))
|
||||
&& !initexpr.span.in_external_macro(cx.sess().source_map())
|
||||
&& !retexpr.span.in_external_macro(cx.sess().source_map())
|
||||
&& !local.span.from_expansion()
|
||||
|
|
|
|||
265
tests/ui/let_and_return.edition2021.fixed
Normal file
265
tests/ui/let_and_return.edition2021.fixed
Normal file
|
|
@ -0,0 +1,265 @@
|
|||
//@revisions: edition2021 edition2024
|
||||
//@[edition2021] edition:2021
|
||||
//@[edition2024] edition:2024
|
||||
|
||||
#![allow(unused)]
|
||||
#![warn(clippy::let_and_return)]
|
||||
|
||||
use std::cell::RefCell;
|
||||
|
||||
fn test() -> i32 {
|
||||
let _y = 0; // no warning
|
||||
|
||||
5
|
||||
//~^ ERROR: returning the result of a `let` binding from a block
|
||||
//~| NOTE: `-D clippy::let-and-return` implied by `-D warnings`
|
||||
}
|
||||
|
||||
fn test_inner() -> i32 {
|
||||
if true {
|
||||
|
||||
5
|
||||
//~^ ERROR: returning the result of a `let` binding from a block
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
fn test_nowarn_1() -> i32 {
|
||||
let mut x = 5;
|
||||
x += 1;
|
||||
x
|
||||
}
|
||||
|
||||
fn test_nowarn_2() -> i32 {
|
||||
let x = 5;
|
||||
x + 1
|
||||
}
|
||||
|
||||
fn test_nowarn_3() -> (i32, i32) {
|
||||
// this should technically warn, but we do not compare complex patterns
|
||||
let (x, y) = (5, 9);
|
||||
(x, y)
|
||||
}
|
||||
|
||||
fn test_nowarn_4() -> i32 {
|
||||
// this should technically warn, but not b/c of clippy::let_and_return, but b/c of useless type
|
||||
let x: i32 = 5;
|
||||
x
|
||||
}
|
||||
|
||||
fn test_nowarn_5(x: i16) -> u16 {
|
||||
#[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
|
||||
let x = x as u16;
|
||||
x
|
||||
}
|
||||
|
||||
// False positive example
|
||||
trait Decode {
|
||||
fn decode<D: std::io::Read>(d: D) -> Result<Self, ()>
|
||||
where
|
||||
Self: Sized;
|
||||
}
|
||||
|
||||
macro_rules! tuple_encode {
|
||||
($($x:ident),*) => (
|
||||
impl<$($x: Decode),*> Decode for ($($x),*) {
|
||||
#[inline]
|
||||
#[allow(non_snake_case)]
|
||||
fn decode<D: std::io::Read>(mut d: D) -> Result<Self, ()> {
|
||||
// Shouldn't trigger lint
|
||||
Ok(($({let $x = Decode::decode(&mut d)?; $x }),*))
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
fn issue_3792() -> String {
|
||||
use std::io::{self, BufRead, Stdin};
|
||||
|
||||
let stdin = io::stdin();
|
||||
// `Stdin::lock` returns `StdinLock<'static>` so `line` doesn't borrow from `stdin`
|
||||
// https://github.com/rust-lang/rust/pull/93965
|
||||
|
||||
stdin.lock().lines().next().unwrap().unwrap()
|
||||
//~^ ERROR: returning the result of a `let` binding from a block
|
||||
}
|
||||
|
||||
tuple_encode!(T0, T1, T2, T3, T4, T5, T6, T7);
|
||||
|
||||
mod no_lint_if_stmt_borrows {
|
||||
use std::cell::RefCell;
|
||||
use std::rc::{Rc, Weak};
|
||||
struct Bar;
|
||||
|
||||
impl Bar {
|
||||
fn new() -> Self {
|
||||
Bar {}
|
||||
}
|
||||
fn baz(&self) -> u32 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
fn issue_3324(value: Weak<RefCell<Bar>>) -> u32 {
|
||||
let value = value.upgrade().unwrap();
|
||||
let ret = value.borrow().baz();
|
||||
ret
|
||||
//~[edition2024]^ ERROR: returning the result of a `let` binding from a block
|
||||
}
|
||||
|
||||
fn borrows_in_closure(value: Weak<RefCell<Bar>>) -> u32 {
|
||||
fn f(mut x: impl FnMut() -> u32) -> impl FnMut() -> u32 {
|
||||
x
|
||||
}
|
||||
|
||||
let value = value.upgrade().unwrap();
|
||||
let ret = f(|| value.borrow().baz())();
|
||||
ret
|
||||
//~[edition2024]^ ERROR: returning the result of a `let` binding from a block
|
||||
}
|
||||
|
||||
mod free_function {
|
||||
struct Inner;
|
||||
|
||||
struct Foo<'a> {
|
||||
inner: &'a Inner,
|
||||
}
|
||||
|
||||
impl Drop for Foo<'_> {
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
|
||||
impl<'a> Foo<'a> {
|
||||
fn new(inner: &'a Inner) -> Self {
|
||||
Self { inner }
|
||||
}
|
||||
|
||||
fn value(&self) -> i32 {
|
||||
42
|
||||
}
|
||||
}
|
||||
|
||||
fn some_foo(inner: &Inner) -> Foo<'_> {
|
||||
Foo { inner }
|
||||
}
|
||||
|
||||
fn test() -> i32 {
|
||||
let x = Inner {};
|
||||
let value = some_foo(&x).value();
|
||||
value
|
||||
//~[edition2024]^ ERROR: returning the result of a `let` binding from a block
|
||||
}
|
||||
|
||||
fn test2() -> i32 {
|
||||
let x = Inner {};
|
||||
let value = Foo::new(&x).value();
|
||||
value
|
||||
//~[edition2024]^ ERROR: returning the result of a `let` binding from a block
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mod issue_5729 {
|
||||
use std::sync::Arc;
|
||||
|
||||
trait Foo {}
|
||||
|
||||
trait FooStorage {
|
||||
fn foo_cloned(&self) -> Arc<dyn Foo>;
|
||||
}
|
||||
|
||||
struct FooStorageImpl<T: Foo> {
|
||||
foo: Arc<T>,
|
||||
}
|
||||
|
||||
impl<T: Foo + 'static> FooStorage for FooStorageImpl<T> {
|
||||
fn foo_cloned(&self) -> Arc<dyn Foo> {
|
||||
|
||||
(Arc::clone(&self.foo)) as _
|
||||
//~^ ERROR: returning the result of a `let` binding from a block
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mod issue_11335 {
|
||||
pub enum E<T> {
|
||||
A(T),
|
||||
B(T),
|
||||
}
|
||||
|
||||
impl<T> E<T> {
|
||||
pub fn inner(&self) -> &T {
|
||||
|
||||
|
||||
(match self {
|
||||
E::A(x) => x,
|
||||
E::B(x) => x,
|
||||
}) as _
|
||||
//~^ ERROR: returning the result of a `let` binding from a block
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/rust-lang/rust-clippy/issues/11167
|
||||
macro_rules! fn_in_macro {
|
||||
($b:block) => {
|
||||
fn f() -> usize $b
|
||||
}
|
||||
}
|
||||
fn_in_macro!({
|
||||
return 1;
|
||||
});
|
||||
|
||||
fn issue9150() -> usize {
|
||||
let x = 1;
|
||||
#[cfg(any())]
|
||||
panic!("can't see me");
|
||||
x
|
||||
}
|
||||
|
||||
fn issue12801() {
|
||||
fn left_is_if() -> String {
|
||||
|
||||
(if true { "a".to_string() } else { "b".to_string() } + "c")
|
||||
//~^ ERROR: returning the result of a `let` binding from a block
|
||||
}
|
||||
|
||||
fn no_par_needed() -> String {
|
||||
|
||||
"c".to_string() + if true { "a" } else { "b" }
|
||||
//~^ ERROR: returning the result of a `let` binding from a block
|
||||
}
|
||||
|
||||
fn conjunctive_blocks() -> String {
|
||||
|
||||
({ "a".to_string() } + "b" + { "c" } + "d")
|
||||
//~^ ERROR: returning the result of a `let` binding from a block
|
||||
}
|
||||
|
||||
#[allow(clippy::overly_complex_bool_expr)]
|
||||
fn other_ops() {
|
||||
let _ = || {
|
||||
|
||||
(if true { 2 } else { 3 } << 4)
|
||||
//~^ ERROR: returning the result of a `let` binding from a block
|
||||
};
|
||||
let _ = || {
|
||||
|
||||
({ true } || { false } && { 2 <= 3 })
|
||||
//~^ ERROR: returning the result of a `let` binding from a block
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn issue14164() -> Result<u32, ()> {
|
||||
let v = std::cell::RefCell::new(Some(vec![1]));
|
||||
let r = match &*v.borrow() {
|
||||
Some(v) => Ok(Ok(v[0])),
|
||||
None => Ok(Ok(0)),
|
||||
}?;
|
||||
r
|
||||
//~[edition2024]^ ERROR: returning the result of a `let` binding from a block
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
152
tests/ui/let_and_return.edition2021.stderr
Normal file
152
tests/ui/let_and_return.edition2021.stderr
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
error: returning the result of a `let` binding from a block
|
||||
--> tests/ui/let_and_return.rs:13:5
|
||||
|
|
||||
LL | let x = 5;
|
||||
| ---------- unnecessary `let` binding
|
||||
LL | x
|
||||
| ^
|
||||
|
|
||||
= note: `-D clippy::let-and-return` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::let_and_return)]`
|
||||
help: return the expression directly
|
||||
|
|
||||
LL ~
|
||||
LL ~ 5
|
||||
|
|
||||
|
||||
error: returning the result of a `let` binding from a block
|
||||
--> tests/ui/let_and_return.rs:21:9
|
||||
|
|
||||
LL | let x = 5;
|
||||
| ---------- unnecessary `let` binding
|
||||
LL | x
|
||||
| ^
|
||||
|
|
||||
help: return the expression directly
|
||||
|
|
||||
LL ~
|
||||
LL ~ 5
|
||||
|
|
||||
|
||||
error: returning the result of a `let` binding from a block
|
||||
--> tests/ui/let_and_return.rs:84:5
|
||||
|
|
||||
LL | let line = stdin.lock().lines().next().unwrap().unwrap();
|
||||
| --------------------------------------------------------- unnecessary `let` binding
|
||||
LL | line
|
||||
| ^^^^
|
||||
|
|
||||
help: return the expression directly
|
||||
|
|
||||
LL ~
|
||||
LL ~ stdin.lock().lines().next().unwrap().unwrap()
|
||||
|
|
||||
|
||||
error: returning the result of a `let` binding from a block
|
||||
--> tests/ui/let_and_return.rs:179:13
|
||||
|
|
||||
LL | let clone = Arc::clone(&self.foo);
|
||||
| ---------------------------------- unnecessary `let` binding
|
||||
LL | clone
|
||||
| ^^^^^
|
||||
|
|
||||
help: return the expression directly
|
||||
|
|
||||
LL ~
|
||||
LL ~ (Arc::clone(&self.foo)) as _
|
||||
|
|
||||
|
||||
error: returning the result of a `let` binding from a block
|
||||
--> tests/ui/let_and_return.rs:198:13
|
||||
|
|
||||
LL | / let result = match self {
|
||||
LL | | E::A(x) => x,
|
||||
LL | | E::B(x) => x,
|
||||
LL | | };
|
||||
| |______________- unnecessary `let` binding
|
||||
LL |
|
||||
LL | result
|
||||
| ^^^^^^
|
||||
|
|
||||
help: return the expression directly
|
||||
|
|
||||
LL ~
|
||||
LL |
|
||||
LL ~ (match self {
|
||||
LL + E::A(x) => x,
|
||||
LL + E::B(x) => x,
|
||||
LL + }) as _
|
||||
|
|
||||
|
||||
error: returning the result of a `let` binding from a block
|
||||
--> tests/ui/let_and_return.rs:224:9
|
||||
|
|
||||
LL | let s = if true { "a".to_string() } else { "b".to_string() } + "c";
|
||||
| ------------------------------------------------------------------- unnecessary `let` binding
|
||||
LL | s
|
||||
| ^
|
||||
|
|
||||
help: return the expression directly
|
||||
|
|
||||
LL ~
|
||||
LL ~ (if true { "a".to_string() } else { "b".to_string() } + "c")
|
||||
|
|
||||
|
||||
error: returning the result of a `let` binding from a block
|
||||
--> tests/ui/let_and_return.rs:230:9
|
||||
|
|
||||
LL | let s = "c".to_string() + if true { "a" } else { "b" };
|
||||
| ------------------------------------------------------- unnecessary `let` binding
|
||||
LL | s
|
||||
| ^
|
||||
|
|
||||
help: return the expression directly
|
||||
|
|
||||
LL ~
|
||||
LL ~ "c".to_string() + if true { "a" } else { "b" }
|
||||
|
|
||||
|
||||
error: returning the result of a `let` binding from a block
|
||||
--> tests/ui/let_and_return.rs:236:9
|
||||
|
|
||||
LL | let s = { "a".to_string() } + "b" + { "c" } + "d";
|
||||
| -------------------------------------------------- unnecessary `let` binding
|
||||
LL | s
|
||||
| ^
|
||||
|
|
||||
help: return the expression directly
|
||||
|
|
||||
LL ~
|
||||
LL ~ ({ "a".to_string() } + "b" + { "c" } + "d")
|
||||
|
|
||||
|
||||
error: returning the result of a `let` binding from a block
|
||||
--> tests/ui/let_and_return.rs:244:13
|
||||
|
|
||||
LL | let s = if true { 2 } else { 3 } << 4;
|
||||
| -------------------------------------- unnecessary `let` binding
|
||||
LL | s
|
||||
| ^
|
||||
|
|
||||
help: return the expression directly
|
||||
|
|
||||
LL ~
|
||||
LL ~ (if true { 2 } else { 3 } << 4)
|
||||
|
|
||||
|
||||
error: returning the result of a `let` binding from a block
|
||||
--> tests/ui/let_and_return.rs:249:13
|
||||
|
|
||||
LL | let s = { true } || { false } && { 2 <= 3 };
|
||||
| -------------------------------------------- unnecessary `let` binding
|
||||
LL | s
|
||||
| ^
|
||||
|
|
||||
help: return the expression directly
|
||||
|
|
||||
LL ~
|
||||
LL ~ ({ true } || { false } && { 2 <= 3 })
|
||||
|
|
||||
|
||||
error: aborting due to 10 previous errors
|
||||
|
||||
265
tests/ui/let_and_return.edition2024.fixed
Normal file
265
tests/ui/let_and_return.edition2024.fixed
Normal file
|
|
@ -0,0 +1,265 @@
|
|||
//@revisions: edition2021 edition2024
|
||||
//@[edition2021] edition:2021
|
||||
//@[edition2024] edition:2024
|
||||
|
||||
#![allow(unused)]
|
||||
#![warn(clippy::let_and_return)]
|
||||
|
||||
use std::cell::RefCell;
|
||||
|
||||
fn test() -> i32 {
|
||||
let _y = 0; // no warning
|
||||
|
||||
5
|
||||
//~^ ERROR: returning the result of a `let` binding from a block
|
||||
//~| NOTE: `-D clippy::let-and-return` implied by `-D warnings`
|
||||
}
|
||||
|
||||
fn test_inner() -> i32 {
|
||||
if true {
|
||||
|
||||
5
|
||||
//~^ ERROR: returning the result of a `let` binding from a block
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
fn test_nowarn_1() -> i32 {
|
||||
let mut x = 5;
|
||||
x += 1;
|
||||
x
|
||||
}
|
||||
|
||||
fn test_nowarn_2() -> i32 {
|
||||
let x = 5;
|
||||
x + 1
|
||||
}
|
||||
|
||||
fn test_nowarn_3() -> (i32, i32) {
|
||||
// this should technically warn, but we do not compare complex patterns
|
||||
let (x, y) = (5, 9);
|
||||
(x, y)
|
||||
}
|
||||
|
||||
fn test_nowarn_4() -> i32 {
|
||||
// this should technically warn, but not b/c of clippy::let_and_return, but b/c of useless type
|
||||
let x: i32 = 5;
|
||||
x
|
||||
}
|
||||
|
||||
fn test_nowarn_5(x: i16) -> u16 {
|
||||
#[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
|
||||
let x = x as u16;
|
||||
x
|
||||
}
|
||||
|
||||
// False positive example
|
||||
trait Decode {
|
||||
fn decode<D: std::io::Read>(d: D) -> Result<Self, ()>
|
||||
where
|
||||
Self: Sized;
|
||||
}
|
||||
|
||||
macro_rules! tuple_encode {
|
||||
($($x:ident),*) => (
|
||||
impl<$($x: Decode),*> Decode for ($($x),*) {
|
||||
#[inline]
|
||||
#[allow(non_snake_case)]
|
||||
fn decode<D: std::io::Read>(mut d: D) -> Result<Self, ()> {
|
||||
// Shouldn't trigger lint
|
||||
Ok(($({let $x = Decode::decode(&mut d)?; $x }),*))
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
fn issue_3792() -> String {
|
||||
use std::io::{self, BufRead, Stdin};
|
||||
|
||||
let stdin = io::stdin();
|
||||
// `Stdin::lock` returns `StdinLock<'static>` so `line` doesn't borrow from `stdin`
|
||||
// https://github.com/rust-lang/rust/pull/93965
|
||||
|
||||
stdin.lock().lines().next().unwrap().unwrap()
|
||||
//~^ ERROR: returning the result of a `let` binding from a block
|
||||
}
|
||||
|
||||
tuple_encode!(T0, T1, T2, T3, T4, T5, T6, T7);
|
||||
|
||||
mod no_lint_if_stmt_borrows {
|
||||
use std::cell::RefCell;
|
||||
use std::rc::{Rc, Weak};
|
||||
struct Bar;
|
||||
|
||||
impl Bar {
|
||||
fn new() -> Self {
|
||||
Bar {}
|
||||
}
|
||||
fn baz(&self) -> u32 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
fn issue_3324(value: Weak<RefCell<Bar>>) -> u32 {
|
||||
let value = value.upgrade().unwrap();
|
||||
|
||||
value.borrow().baz()
|
||||
//~[edition2024]^ ERROR: returning the result of a `let` binding from a block
|
||||
}
|
||||
|
||||
fn borrows_in_closure(value: Weak<RefCell<Bar>>) -> u32 {
|
||||
fn f(mut x: impl FnMut() -> u32) -> impl FnMut() -> u32 {
|
||||
x
|
||||
}
|
||||
|
||||
let value = value.upgrade().unwrap();
|
||||
|
||||
f(|| value.borrow().baz())()
|
||||
//~[edition2024]^ ERROR: returning the result of a `let` binding from a block
|
||||
}
|
||||
|
||||
mod free_function {
|
||||
struct Inner;
|
||||
|
||||
struct Foo<'a> {
|
||||
inner: &'a Inner,
|
||||
}
|
||||
|
||||
impl Drop for Foo<'_> {
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
|
||||
impl<'a> Foo<'a> {
|
||||
fn new(inner: &'a Inner) -> Self {
|
||||
Self { inner }
|
||||
}
|
||||
|
||||
fn value(&self) -> i32 {
|
||||
42
|
||||
}
|
||||
}
|
||||
|
||||
fn some_foo(inner: &Inner) -> Foo<'_> {
|
||||
Foo { inner }
|
||||
}
|
||||
|
||||
fn test() -> i32 {
|
||||
let x = Inner {};
|
||||
|
||||
some_foo(&x).value()
|
||||
//~[edition2024]^ ERROR: returning the result of a `let` binding from a block
|
||||
}
|
||||
|
||||
fn test2() -> i32 {
|
||||
let x = Inner {};
|
||||
|
||||
Foo::new(&x).value()
|
||||
//~[edition2024]^ ERROR: returning the result of a `let` binding from a block
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mod issue_5729 {
|
||||
use std::sync::Arc;
|
||||
|
||||
trait Foo {}
|
||||
|
||||
trait FooStorage {
|
||||
fn foo_cloned(&self) -> Arc<dyn Foo>;
|
||||
}
|
||||
|
||||
struct FooStorageImpl<T: Foo> {
|
||||
foo: Arc<T>,
|
||||
}
|
||||
|
||||
impl<T: Foo + 'static> FooStorage for FooStorageImpl<T> {
|
||||
fn foo_cloned(&self) -> Arc<dyn Foo> {
|
||||
|
||||
(Arc::clone(&self.foo)) as _
|
||||
//~^ ERROR: returning the result of a `let` binding from a block
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mod issue_11335 {
|
||||
pub enum E<T> {
|
||||
A(T),
|
||||
B(T),
|
||||
}
|
||||
|
||||
impl<T> E<T> {
|
||||
pub fn inner(&self) -> &T {
|
||||
|
||||
|
||||
(match self {
|
||||
E::A(x) => x,
|
||||
E::B(x) => x,
|
||||
}) as _
|
||||
//~^ ERROR: returning the result of a `let` binding from a block
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/rust-lang/rust-clippy/issues/11167
|
||||
macro_rules! fn_in_macro {
|
||||
($b:block) => {
|
||||
fn f() -> usize $b
|
||||
}
|
||||
}
|
||||
fn_in_macro!({
|
||||
return 1;
|
||||
});
|
||||
|
||||
fn issue9150() -> usize {
|
||||
let x = 1;
|
||||
#[cfg(any())]
|
||||
panic!("can't see me");
|
||||
x
|
||||
}
|
||||
|
||||
fn issue12801() {
|
||||
fn left_is_if() -> String {
|
||||
|
||||
(if true { "a".to_string() } else { "b".to_string() } + "c")
|
||||
//~^ ERROR: returning the result of a `let` binding from a block
|
||||
}
|
||||
|
||||
fn no_par_needed() -> String {
|
||||
|
||||
"c".to_string() + if true { "a" } else { "b" }
|
||||
//~^ ERROR: returning the result of a `let` binding from a block
|
||||
}
|
||||
|
||||
fn conjunctive_blocks() -> String {
|
||||
|
||||
({ "a".to_string() } + "b" + { "c" } + "d")
|
||||
//~^ ERROR: returning the result of a `let` binding from a block
|
||||
}
|
||||
|
||||
#[allow(clippy::overly_complex_bool_expr)]
|
||||
fn other_ops() {
|
||||
let _ = || {
|
||||
|
||||
(if true { 2 } else { 3 } << 4)
|
||||
//~^ ERROR: returning the result of a `let` binding from a block
|
||||
};
|
||||
let _ = || {
|
||||
|
||||
({ true } || { false } && { 2 <= 3 })
|
||||
//~^ ERROR: returning the result of a `let` binding from a block
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn issue14164() -> Result<u32, ()> {
|
||||
let v = std::cell::RefCell::new(Some(vec![1]));
|
||||
|
||||
match &*v.borrow() {
|
||||
Some(v) => Ok(Ok(v[0])),
|
||||
None => Ok(Ok(0)),
|
||||
}?
|
||||
//~[edition2024]^ ERROR: returning the result of a `let` binding from a block
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
228
tests/ui/let_and_return.edition2024.stderr
Normal file
228
tests/ui/let_and_return.edition2024.stderr
Normal file
|
|
@ -0,0 +1,228 @@
|
|||
error: returning the result of a `let` binding from a block
|
||||
--> tests/ui/let_and_return.rs:13:5
|
||||
|
|
||||
LL | let x = 5;
|
||||
| ---------- unnecessary `let` binding
|
||||
LL | x
|
||||
| ^
|
||||
|
|
||||
= note: `-D clippy::let-and-return` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::let_and_return)]`
|
||||
help: return the expression directly
|
||||
|
|
||||
LL ~
|
||||
LL ~ 5
|
||||
|
|
||||
|
||||
error: returning the result of a `let` binding from a block
|
||||
--> tests/ui/let_and_return.rs:21:9
|
||||
|
|
||||
LL | let x = 5;
|
||||
| ---------- unnecessary `let` binding
|
||||
LL | x
|
||||
| ^
|
||||
|
|
||||
help: return the expression directly
|
||||
|
|
||||
LL ~
|
||||
LL ~ 5
|
||||
|
|
||||
|
||||
error: returning the result of a `let` binding from a block
|
||||
--> tests/ui/let_and_return.rs:84:5
|
||||
|
|
||||
LL | let line = stdin.lock().lines().next().unwrap().unwrap();
|
||||
| --------------------------------------------------------- unnecessary `let` binding
|
||||
LL | line
|
||||
| ^^^^
|
||||
|
|
||||
help: return the expression directly
|
||||
|
|
||||
LL ~
|
||||
LL ~ stdin.lock().lines().next().unwrap().unwrap()
|
||||
|
|
||||
|
||||
error: returning the result of a `let` binding from a block
|
||||
--> tests/ui/let_and_return.rs:107:9
|
||||
|
|
||||
LL | let ret = value.borrow().baz();
|
||||
| ------------------------------- unnecessary `let` binding
|
||||
LL | ret
|
||||
| ^^^
|
||||
|
|
||||
help: return the expression directly
|
||||
|
|
||||
LL ~
|
||||
LL ~ value.borrow().baz()
|
||||
|
|
||||
|
||||
error: returning the result of a `let` binding from a block
|
||||
--> tests/ui/let_and_return.rs:118:9
|
||||
|
|
||||
LL | let ret = f(|| value.borrow().baz())();
|
||||
| --------------------------------------- unnecessary `let` binding
|
||||
LL | ret
|
||||
| ^^^
|
||||
|
|
||||
help: return the expression directly
|
||||
|
|
||||
LL ~
|
||||
LL ~ f(|| value.borrow().baz())()
|
||||
|
|
||||
|
||||
error: returning the result of a `let` binding from a block
|
||||
--> tests/ui/let_and_return.rs:150:13
|
||||
|
|
||||
LL | let value = some_foo(&x).value();
|
||||
| --------------------------------- unnecessary `let` binding
|
||||
LL | value
|
||||
| ^^^^^
|
||||
|
|
||||
help: return the expression directly
|
||||
|
|
||||
LL ~
|
||||
LL ~ some_foo(&x).value()
|
||||
|
|
||||
|
||||
error: returning the result of a `let` binding from a block
|
||||
--> tests/ui/let_and_return.rs:157:13
|
||||
|
|
||||
LL | let value = Foo::new(&x).value();
|
||||
| --------------------------------- unnecessary `let` binding
|
||||
LL | value
|
||||
| ^^^^^
|
||||
|
|
||||
help: return the expression directly
|
||||
|
|
||||
LL ~
|
||||
LL ~ Foo::new(&x).value()
|
||||
|
|
||||
|
||||
error: returning the result of a `let` binding from a block
|
||||
--> tests/ui/let_and_return.rs:179:13
|
||||
|
|
||||
LL | let clone = Arc::clone(&self.foo);
|
||||
| ---------------------------------- unnecessary `let` binding
|
||||
LL | clone
|
||||
| ^^^^^
|
||||
|
|
||||
help: return the expression directly
|
||||
|
|
||||
LL ~
|
||||
LL ~ (Arc::clone(&self.foo)) as _
|
||||
|
|
||||
|
||||
error: returning the result of a `let` binding from a block
|
||||
--> tests/ui/let_and_return.rs:198:13
|
||||
|
|
||||
LL | / let result = match self {
|
||||
LL | | E::A(x) => x,
|
||||
LL | | E::B(x) => x,
|
||||
LL | | };
|
||||
| |______________- unnecessary `let` binding
|
||||
LL |
|
||||
LL | result
|
||||
| ^^^^^^
|
||||
|
|
||||
help: return the expression directly
|
||||
|
|
||||
LL ~
|
||||
LL |
|
||||
LL ~ (match self {
|
||||
LL + E::A(x) => x,
|
||||
LL + E::B(x) => x,
|
||||
LL + }) as _
|
||||
|
|
||||
|
||||
error: returning the result of a `let` binding from a block
|
||||
--> tests/ui/let_and_return.rs:224:9
|
||||
|
|
||||
LL | let s = if true { "a".to_string() } else { "b".to_string() } + "c";
|
||||
| ------------------------------------------------------------------- unnecessary `let` binding
|
||||
LL | s
|
||||
| ^
|
||||
|
|
||||
help: return the expression directly
|
||||
|
|
||||
LL ~
|
||||
LL ~ (if true { "a".to_string() } else { "b".to_string() } + "c")
|
||||
|
|
||||
|
||||
error: returning the result of a `let` binding from a block
|
||||
--> tests/ui/let_and_return.rs:230:9
|
||||
|
|
||||
LL | let s = "c".to_string() + if true { "a" } else { "b" };
|
||||
| ------------------------------------------------------- unnecessary `let` binding
|
||||
LL | s
|
||||
| ^
|
||||
|
|
||||
help: return the expression directly
|
||||
|
|
||||
LL ~
|
||||
LL ~ "c".to_string() + if true { "a" } else { "b" }
|
||||
|
|
||||
|
||||
error: returning the result of a `let` binding from a block
|
||||
--> tests/ui/let_and_return.rs:236:9
|
||||
|
|
||||
LL | let s = { "a".to_string() } + "b" + { "c" } + "d";
|
||||
| -------------------------------------------------- unnecessary `let` binding
|
||||
LL | s
|
||||
| ^
|
||||
|
|
||||
help: return the expression directly
|
||||
|
|
||||
LL ~
|
||||
LL ~ ({ "a".to_string() } + "b" + { "c" } + "d")
|
||||
|
|
||||
|
||||
error: returning the result of a `let` binding from a block
|
||||
--> tests/ui/let_and_return.rs:244:13
|
||||
|
|
||||
LL | let s = if true { 2 } else { 3 } << 4;
|
||||
| -------------------------------------- unnecessary `let` binding
|
||||
LL | s
|
||||
| ^
|
||||
|
|
||||
help: return the expression directly
|
||||
|
|
||||
LL ~
|
||||
LL ~ (if true { 2 } else { 3 } << 4)
|
||||
|
|
||||
|
||||
error: returning the result of a `let` binding from a block
|
||||
--> tests/ui/let_and_return.rs:249:13
|
||||
|
|
||||
LL | let s = { true } || { false } && { 2 <= 3 };
|
||||
| -------------------------------------------- unnecessary `let` binding
|
||||
LL | s
|
||||
| ^
|
||||
|
|
||||
help: return the expression directly
|
||||
|
|
||||
LL ~
|
||||
LL ~ ({ true } || { false } && { 2 <= 3 })
|
||||
|
|
||||
|
||||
error: returning the result of a `let` binding from a block
|
||||
--> tests/ui/let_and_return.rs:261:5
|
||||
|
|
||||
LL | / let r = match &*v.borrow() {
|
||||
LL | | Some(v) => Ok(Ok(v[0])),
|
||||
LL | | None => Ok(Ok(0)),
|
||||
LL | | }?;
|
||||
| |_______- unnecessary `let` binding
|
||||
LL | r
|
||||
| ^
|
||||
|
|
||||
help: return the expression directly
|
||||
|
|
||||
LL ~
|
||||
LL ~ match &*v.borrow() {
|
||||
LL + Some(v) => Ok(Ok(v[0])),
|
||||
LL + None => Ok(Ok(0)),
|
||||
LL + }?
|
||||
|
|
||||
|
||||
error: aborting due to 15 previous errors
|
||||
|
||||
|
|
@ -1,3 +1,7 @@
|
|||
//@revisions: edition2021 edition2024
|
||||
//@[edition2021] edition:2021
|
||||
//@[edition2024] edition:2024
|
||||
|
||||
#![allow(unused)]
|
||||
#![warn(clippy::let_and_return)]
|
||||
|
||||
|
|
@ -101,6 +105,7 @@ mod no_lint_if_stmt_borrows {
|
|||
let value = value.upgrade().unwrap();
|
||||
let ret = value.borrow().baz();
|
||||
ret
|
||||
//~[edition2024]^ ERROR: returning the result of a `let` binding from a block
|
||||
}
|
||||
|
||||
fn borrows_in_closure(value: Weak<RefCell<Bar>>) -> u32 {
|
||||
|
|
@ -111,6 +116,7 @@ mod no_lint_if_stmt_borrows {
|
|||
let value = value.upgrade().unwrap();
|
||||
let ret = f(|| value.borrow().baz())();
|
||||
ret
|
||||
//~[edition2024]^ ERROR: returning the result of a `let` binding from a block
|
||||
}
|
||||
|
||||
mod free_function {
|
||||
|
|
@ -142,12 +148,14 @@ mod no_lint_if_stmt_borrows {
|
|||
let x = Inner {};
|
||||
let value = some_foo(&x).value();
|
||||
value
|
||||
//~[edition2024]^ ERROR: returning the result of a `let` binding from a block
|
||||
}
|
||||
|
||||
fn test2() -> i32 {
|
||||
let x = Inner {};
|
||||
let value = Foo::new(&x).value();
|
||||
value
|
||||
//~[edition2024]^ ERROR: returning the result of a `let` binding from a block
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -244,7 +252,6 @@ fn issue12801() {
|
|||
}
|
||||
}
|
||||
|
||||
// Do not lint
|
||||
fn issue14164() -> Result<u32, ()> {
|
||||
let v = std::cell::RefCell::new(Some(vec![1]));
|
||||
let r = match &*v.borrow() {
|
||||
|
|
@ -252,6 +259,7 @@ fn issue14164() -> Result<u32, ()> {
|
|||
None => Ok(Ok(0)),
|
||||
}?;
|
||||
r
|
||||
//~[edition2024]^ ERROR: returning the result of a `let` binding from a block
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue