Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit f870876

Browse files
committed
Auto merge of rust-lang#6659 - phlip9:let_and_return_fix, r=phansch
Fix let_and_return false positive The issue: See this Rust playground link: https://play.rust-lang.org/?edition=2018&gist=12cb5d1e7527f8c37743b87fc4a53748 Run the above with clippy to see the following warning: ``` warning: returning the result of a `let` binding from a block --> src/main.rs:24:5 | 23 | let value = Foo::new(&x).value(); | --------------------------------- unnecessary `let` binding 24 | value | ^^^^^ | = note: `#[warn(clippy::let_and_return)]` on by default = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#let_and_return help: return the expression directly | 23 | 24 | Foo::new(&x).value() | ``` Implementing the suggested fix, removing the temporary let binding, yields a compiler error: ``` error[E0597]: `x` does not live long enough --> src/main.rs:23:14 | 23 | Foo::new(&x).value() | ---------^^- | | | | | borrowed value does not live long enough | a temporary with access to the borrow is created here ... 24 | } | - | | | `x` dropped here while still borrowed | ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `Foo` | = note: the temporary is part of an expression at the end of a block; consider forcing this temporary to be dropped sooner, before the block's local variables are dropped help: for example, you could save the expression's value in a new local variable `x` and then make `x` be the expression at the end of the block | 23 | let x = Foo::new(&x).value(); x | ^^^^^^^ ^^^ ``` The fix: Of course, clippy looks like it should already handle this edge case; however, it appears `utils::fn_def_id` is not returning a `DefId` for `Foo::new`. Changing the `qpath_res` lookup to use the child Path `hir_id` instead of the parent Call `hir_id` fixes the issue. changelog: none
2 parents 8d82ac5 + 7f1595e commit f870876

File tree

3 files changed

+14
-3
lines changed

3 files changed

+14
-3
lines changed

clippy_lints/src/utils/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1532,10 +1532,11 @@ pub fn fn_def_id(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<DefId> {
15321532
ExprKind::Call(
15331533
Expr {
15341534
kind: ExprKind::Path(qpath),
1535+
hir_id: path_hir_id,
15351536
..
15361537
},
15371538
..,
1538-
) => cx.typeck_results().qpath_res(qpath, expr.hir_id).opt_def_id(),
1539+
) => cx.typeck_results().qpath_res(qpath, *path_hir_id).opt_def_id(),
15391540
_ => None,
15401541
}
15411542
}

tests/ui/let_and_return.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,11 @@ mod no_lint_if_stmt_borrows {
117117
fn drop(&mut self) {}
118118
}
119119

120-
impl Foo<'_> {
120+
impl<'a> Foo<'a> {
121+
fn new(inner: &'a Inner) -> Self {
122+
Self { inner }
123+
}
124+
121125
fn value(&self) -> i32 {
122126
42
123127
}
@@ -132,6 +136,12 @@ mod no_lint_if_stmt_borrows {
132136
let value = some_foo(&x).value();
133137
value
134138
}
139+
140+
fn test2() -> i32 {
141+
let x = Inner {};
142+
let value = Foo::new(&x).value();
143+
value
144+
}
135145
}
136146
}
137147

tests/ui/let_and_return.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ LL | 5
2828
|
2929

3030
error: returning the result of a `let` binding from a block
31-
--> $DIR/let_and_return.rs:154:13
31+
--> $DIR/let_and_return.rs:164:13
3232
|
3333
LL | let clone = Arc::clone(&self.foo);
3434
| ---------------------------------- unnecessary `let` binding

0 commit comments

Comments
 (0)