Skip to content

Commit 85d4b5a

Browse files
committed
Auto merge of rust-lang#10368 - c410-f3r:lock-1, r=xFrednet
[significant_drop_tightening] Evaluate the return expression of a block For whatever reason, the return expression of a block is not contained inside the slice of statements and because of that the lint wasn't evaluating things that could potentially block the release of a lock. ```rust pub fn example() -> i32 { let mutex = Mutex::new(1); let lock = mutex.lock().unwrap(); let _ = *lock; let _ = *lock; do_heavy_computation_that_takes_time_and_returns_i32() } ``` --- changelog: none <!-- changelog_checked -->
2 parents e1da002 + 7518969 commit 85d4b5a

4 files changed

+95
-14
lines changed

clippy_lints/src/significant_drop_tightening.rs

+28-9
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,26 @@ pub struct SignificantDropTightening<'tcx> {
6161
}
6262

6363
impl<'tcx> SignificantDropTightening<'tcx> {
64+
/// Unifies the statements of a block with its return expression.
65+
fn all_block_stmts<'ret, 'rslt, 'stmts>(
66+
block_stmts: &'stmts [hir::Stmt<'tcx>],
67+
dummy_ret_stmt: Option<&'ret hir::Stmt<'tcx>>,
68+
) -> impl Iterator<Item = &'rslt hir::Stmt<'tcx>>
69+
where
70+
'ret: 'rslt,
71+
'stmts: 'rslt,
72+
{
73+
block_stmts.iter().chain(dummy_ret_stmt)
74+
}
75+
6476
/// Searches for at least one statement that could slow down the release of a significant drop.
65-
fn at_least_one_stmt_is_expensive(stmts: &[hir::Stmt<'_>]) -> bool {
77+
fn at_least_one_stmt_is_expensive<'stmt>(stmts: impl Iterator<Item = &'stmt hir::Stmt<'tcx>>) -> bool
78+
where
79+
'tcx: 'stmt,
80+
{
6681
for stmt in stmts {
6782
match stmt.kind {
83+
hir::StmtKind::Expr(expr) if let hir::ExprKind::Path(_) = expr.kind => {}
6884
hir::StmtKind::Local(local) if let Some(expr) = local.init
6985
&& let hir::ExprKind::Path(_) = expr.kind => {},
7086
_ => return true
@@ -99,7 +115,7 @@ impl<'tcx> SignificantDropTightening<'tcx> {
99115
expr: &'tcx hir::Expr<'_>,
100116
idx: usize,
101117
sdap: &mut SigDropAuxParams,
102-
stmt: &'tcx hir::Stmt<'_>,
118+
stmt: &hir::Stmt<'_>,
103119
cb: impl Fn(&mut SigDropAuxParams),
104120
) {
105121
let mut sig_drop_finder = SigDropFinder::new(cx, &mut self.seen_types);
@@ -117,7 +133,7 @@ impl<'tcx> SignificantDropTightening<'tcx> {
117133
}
118134
}
119135

120-
/// Shows a generic overall message as well as specialized messages depending on the usage.
136+
/// Shows generic overall messages as well as specialized messages depending on the usage.
121137
fn set_suggestions(cx: &LateContext<'tcx>, block_span: Span, diag: &mut Diagnostic, sdap: &SigDropAuxParams) {
122138
match sdap.number_of_stmts {
123139
0 | 1 => {},
@@ -172,8 +188,13 @@ impl<'tcx> SignificantDropTightening<'tcx> {
172188

173189
impl<'tcx> LateLintPass<'tcx> for SignificantDropTightening<'tcx> {
174190
fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx hir::Block<'_>) {
191+
let dummy_ret_stmt = block.expr.map(|expr| hir::Stmt {
192+
hir_id: hir::HirId::INVALID,
193+
kind: hir::StmtKind::Expr(expr),
194+
span: DUMMY_SP,
195+
});
175196
let mut sdap = SigDropAuxParams::default();
176-
for (idx, stmt) in block.stmts.iter().enumerate() {
197+
for (idx, stmt) in Self::all_block_stmts(block.stmts, dummy_ret_stmt.as_ref()).enumerate() {
177198
match stmt.kind {
178199
hir::StmtKind::Expr(expr) => self.modify_sdap_if_sig_drop_exists(
179200
cx,
@@ -213,11 +234,9 @@ impl<'tcx> LateLintPass<'tcx> for SignificantDropTightening<'tcx> {
213234
_ => {}
214235
};
215236
}
216-
let stmts_after_last_use = sdap
217-
.last_use_stmt_idx
218-
.checked_add(1)
219-
.and_then(|idx| block.stmts.get(idx..))
220-
.unwrap_or_default();
237+
238+
let idx = sdap.last_use_stmt_idx.wrapping_add(1);
239+
let stmts_after_last_use = Self::all_block_stmts(block.stmts, dummy_ret_stmt.as_ref()).skip(idx);
221240
if sdap.number_of_stmts > 1 && Self::at_least_one_stmt_is_expensive(stmts_after_last_use) {
222241
span_lint_and_then(
223242
cx,

tests/ui/significant_drop_tightening.fixed

+20
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,26 @@
44

55
use std::sync::Mutex;
66

7+
pub fn complex_return_triggers_the_lint() -> i32 {
8+
fn foo() -> i32 {
9+
1
10+
}
11+
let mutex = Mutex::new(1);
12+
let lock = mutex.lock().unwrap();
13+
let _ = *lock;
14+
let _ = *lock;
15+
drop(lock);
16+
foo()
17+
}
18+
19+
pub fn path_return_can_be_ignored() -> i32 {
20+
let mutex = Mutex::new(1);
21+
let lock = mutex.lock().unwrap();
22+
let rslt = *lock;
23+
let _ = *lock;
24+
rslt
25+
}
26+
727
pub fn post_bindings_can_be_ignored() {
828
let mutex = Mutex::new(1);
929
let lock = mutex.lock().unwrap();

tests/ui/significant_drop_tightening.rs

+19
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,25 @@
44

55
use std::sync::Mutex;
66

7+
pub fn complex_return_triggers_the_lint() -> i32 {
8+
fn foo() -> i32 {
9+
1
10+
}
11+
let mutex = Mutex::new(1);
12+
let lock = mutex.lock().unwrap();
13+
let _ = *lock;
14+
let _ = *lock;
15+
foo()
16+
}
17+
18+
pub fn path_return_can_be_ignored() -> i32 {
19+
let mutex = Mutex::new(1);
20+
let lock = mutex.lock().unwrap();
21+
let rslt = *lock;
22+
let _ = *lock;
23+
rslt
24+
}
25+
726
pub fn post_bindings_can_be_ignored() {
827
let mutex = Mutex::new(1);
928
let lock = mutex.lock().unwrap();

tests/ui/significant_drop_tightening.stderr

+28-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,29 @@
11
error: temporary with significant `Drop` can be early dropped
2-
--> $DIR/significant_drop_tightening.rs:25:13
2+
--> $DIR/significant_drop_tightening.rs:12:9
3+
|
4+
LL | pub fn complex_return_triggers_the_lint() -> i32 {
5+
| __________________________________________________-
6+
LL | | fn foo() -> i32 {
7+
LL | | 1
8+
LL | | }
9+
LL | | let mutex = Mutex::new(1);
10+
LL | | let lock = mutex.lock().unwrap();
11+
| | ^^^^
12+
... |
13+
LL | | foo()
14+
LL | | }
15+
| |_- temporary `lock` is currently being dropped at the end of its contained scope
16+
|
17+
= note: this might lead to unnecessary resource contention
18+
= note: `-D clippy::significant-drop-tightening` implied by `-D warnings`
19+
help: drop the temporary after the end of its last usage
20+
|
21+
LL ~ let _ = *lock;
22+
LL + drop(lock);
23+
|
24+
25+
error: temporary with significant `Drop` can be early dropped
26+
--> $DIR/significant_drop_tightening.rs:44:13
327
|
428
LL | / {
529
LL | | let mutex = Mutex::new(1i32);
@@ -12,15 +36,14 @@ LL | | }
1236
| |_____- temporary `lock` is currently being dropped at the end of its contained scope
1337
|
1438
= note: this might lead to unnecessary resource contention
15-
= note: `-D clippy::significant-drop-tightening` implied by `-D warnings`
1639
help: drop the temporary after the end of its last usage
1740
|
1841
LL ~ let rslt1 = lock.is_positive();
1942
LL + drop(lock);
2043
|
2144

2245
error: temporary with significant `Drop` can be early dropped
23-
--> $DIR/significant_drop_tightening.rs:46:13
46+
--> $DIR/significant_drop_tightening.rs:65:13
2447
|
2548
LL | / {
2649
LL | | let mutex = Mutex::new(1i32);
@@ -44,7 +67,7 @@ LL +
4467
|
4568

4669
error: temporary with significant `Drop` can be early dropped
47-
--> $DIR/significant_drop_tightening.rs:52:17
70+
--> $DIR/significant_drop_tightening.rs:71:17
4871
|
4972
LL | / {
5073
LL | | let mutex = Mutex::new(vec![1i32]);
@@ -67,5 +90,5 @@ LL - lock.clear();
6790
LL +
6891
|
6992

70-
error: aborting due to 3 previous errors
93+
error: aborting due to 4 previous errors
7194

0 commit comments

Comments
 (0)