Skip to content

Commit 0cb3623

Browse files
Auto merge of #138961 - meithecatte:expr-use-visitor, r=<try>
Make closure capturing have consistent and correct behaviour around patterns
2 parents 518b428 + 9d031bc commit 0cb3623

40 files changed

+801
-342
lines changed

compiler/rustc_hir_typeck/src/expr_use_visitor.rs

Lines changed: 118 additions & 158 deletions
Large diffs are not rendered by default.

compiler/rustc_hir_typeck/src/upvar.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -761,6 +761,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
761761
/// ],
762762
/// }
763763
/// ```
764+
#[instrument(level = "debug", skip(self))]
764765
fn compute_min_captures(
765766
&self,
766767
closure_def_id: LocalDefId,
@@ -2030,6 +2031,7 @@ struct InferBorrowKind<'tcx> {
20302031
}
20312032

20322033
impl<'tcx> euv::Delegate<'tcx> for InferBorrowKind<'tcx> {
2034+
#[instrument(skip(self), level = "debug")]
20332035
fn fake_read(
20342036
&mut self,
20352037
place_with_id: &PlaceWithHirId<'tcx>,
@@ -2120,6 +2122,7 @@ impl<'tcx> euv::Delegate<'tcx> for InferBorrowKind<'tcx> {
21202122
}
21212123

21222124
/// Rust doesn't permit moving fields out of a type that implements drop
2125+
#[instrument(skip(fcx), ret, level = "debug")]
21232126
fn restrict_precision_for_drop_types<'a, 'tcx>(
21242127
fcx: &'a FnCtxt<'a, 'tcx>,
21252128
mut place: Place<'tcx>,
@@ -2180,6 +2183,7 @@ fn restrict_precision_for_unsafe(
21802183
/// - No unsafe block is required to capture `place`.
21812184
///
21822185
/// Returns the truncated place and updated capture mode.
2186+
#[instrument(ret, level = "debug")]
21832187
fn restrict_capture_precision(
21842188
place: Place<'_>,
21852189
curr_mode: ty::UpvarCapture,
@@ -2209,6 +2213,7 @@ fn restrict_capture_precision(
22092213
}
22102214

22112215
/// Truncate deref of any reference.
2216+
#[instrument(ret, level = "debug")]
22122217
fn adjust_for_move_closure(
22132218
mut place: Place<'_>,
22142219
mut kind: ty::UpvarCapture,
@@ -2223,6 +2228,7 @@ fn adjust_for_move_closure(
22232228
}
22242229

22252230
/// Truncate deref of any reference.
2231+
#[instrument(ret, level = "debug")]
22262232
fn adjust_for_use_closure(
22272233
mut place: Place<'_>,
22282234
mut kind: ty::UpvarCapture,
@@ -2238,6 +2244,7 @@ fn adjust_for_use_closure(
22382244

22392245
/// Adjust closure capture just that if taking ownership of data, only move data
22402246
/// from enclosing stack frame.
2247+
#[instrument(ret, level = "debug")]
22412248
fn adjust_for_non_move_closure(
22422249
mut place: Place<'_>,
22432250
mut kind: ty::UpvarCapture,
@@ -2560,6 +2567,7 @@ fn determine_place_ancestry_relation<'tcx>(
25602567
/// // it is constrained to `'a`
25612568
/// }
25622569
/// ```
2570+
#[instrument(ret, level = "debug")]
25632571
fn truncate_capture_for_optimization(
25642572
mut place: Place<'_>,
25652573
mut curr_mode: ty::UpvarCapture,

compiler/rustc_mir_build/src/builder/matches/match_pair.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,12 @@ impl<'tcx> MatchPairTree<'tcx> {
339339

340340
if let Some(test_case) = test_case {
341341
// This pattern is refutable, so push a new match-pair node.
342+
//
343+
// Note: unless test_case is TestCase::Or, place must not be None.
344+
// This means that the closure capture analysis in
345+
// rustc_hir_typeck::upvar, and in particular the pattern handling
346+
// code of ExprUseVisitor, must capture all of the places we'll use.
347+
// Make sure to keep these two parts in sync!
342348
match_pairs.push(MatchPairTree {
343349
place,
344350
test_case,

src/tools/clippy/clippy_lints/src/methods/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -888,7 +888,7 @@ declare_clippy_lint! {
888888
/// ```
889889
#[clippy::version = "pre 1.29.0"]
890890
pub SEARCH_IS_SOME,
891-
complexity,
891+
nursery,
892892
"using an iterator or string search followed by `is_some()` or `is_none()`, which is more succinctly expressed as a call to `any()` or `contains()` (with negation in case of `is_none()`)"
893893
}
894894

src/tools/clippy/tests/ui/crashes/ice-9041.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#![warn(clippy::search_is_some)]
12
pub struct Thing;
23
//@no-rustfix
34
pub fn has_thing(things: &[Thing]) -> bool {

src/tools/clippy/tests/ui/crashes/ice-9041.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: called `is_some()` after searching an `Iterator` with `find`
2-
--> tests/ui/crashes/ice-9041.rs:5:19
2+
--> tests/ui/crashes/ice-9041.rs:6:19
33
|
44
LL | things.iter().find(|p| is_thing_ready(p)).is_some()
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|p| is_thing_ready(&p))`

src/tools/clippy/tests/ui/search_is_some_fixable_some.fixed

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -311,19 +311,23 @@ mod issue9120 {
311311
}
312312
}
313313

314+
// skip this test due to rust-lang/rust-clippy#16086
315+
/*
314316
#[allow(clippy::match_like_matches_macro)]
315317
fn issue15102() {
316318
let values = [None, Some(3)];
317-
let has_even = values.iter().any(|v| matches!(&v, Some(x) if x % 2 == 0));
318-
//~^ search_is_some
319+
let has_even = values.iter().find(|v| matches!(v, Some(x) if x % 2 == 0)).is_some();
320+
~^ search_is_some
319321
println!("{has_even}");
320322

321323
let has_even = values
322324
.iter()
323-
.any(|v| match &v {
324-
//~^ search_is_some
325+
.find(|v| match v {
326+
~^ search_is_some
325327
Some(x) if x % 2 == 0 => true,
326328
_ => false,
327-
});
329+
})
330+
.is_some();
328331
println!("{has_even}");
329332
}
333+
*/

src/tools/clippy/tests/ui/search_is_some_fixable_some.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -322,20 +322,23 @@ mod issue9120 {
322322
}
323323
}
324324

325+
// skip this test due to rust-lang/rust-clippy#16086
326+
/*
325327
#[allow(clippy::match_like_matches_macro)]
326328
fn issue15102() {
327329
let values = [None, Some(3)];
328330
let has_even = values.iter().find(|v| matches!(v, Some(x) if x % 2 == 0)).is_some();
329-
//~^ search_is_some
331+
~^ search_is_some
330332
println!("{has_even}");
331333
332334
let has_even = values
333335
.iter()
334336
.find(|v| match v {
335-
//~^ search_is_some
337+
~^ search_is_some
336338
Some(x) if x % 2 == 0 => true,
337339
_ => false,
338340
})
339341
.is_some();
340342
println!("{has_even}");
341343
}
344+
*/

src/tools/clippy/tests/ui/search_is_some_fixable_some.stderr

Lines changed: 1 addition & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -346,32 +346,5 @@ error: called `is_some()` after searching an `Iterator` with `find`
346346
LL | let _ = v.iter().find(|x: &&u32| (*arg_no_deref_dyn)(x)).is_some();
347347
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|x: &u32| (*arg_no_deref_dyn)(&x))`
348348

349-
error: called `is_some()` after searching an `Iterator` with `find`
350-
--> tests/ui/search_is_some_fixable_some.rs:328:34
351-
|
352-
LL | let has_even = values.iter().find(|v| matches!(v, Some(x) if x % 2 == 0)).is_some();
353-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|v| matches!(&v, Some(x) if x % 2 == 0))`
354-
355-
error: called `is_some()` after searching an `Iterator` with `find`
356-
--> tests/ui/search_is_some_fixable_some.rs:334:10
357-
|
358-
LL | .find(|v| match v {
359-
| __________^
360-
LL | |
361-
LL | | Some(x) if x % 2 == 0 => true,
362-
LL | | _ => false,
363-
LL | | })
364-
LL | | .is_some();
365-
| |__________________^
366-
|
367-
help: consider using
368-
|
369-
LL ~ .any(|v| match &v {
370-
LL +
371-
LL + Some(x) if x % 2 == 0 => true,
372-
LL + _ => false,
373-
LL ~ });
374-
|
375-
376-
error: aborting due to 51 previous errors
349+
error: aborting due to 49 previous errors
377350

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// This test serves to document the change in semantics introduced by
2+
// rust-lang/rust#138961.
3+
//
4+
// A corollary of partial-pattern.rs: while the tuple access testcase makes
5+
// it clear why these semantics are useful, it is actually the dereference
6+
// being performed by the pattern that matters.
7+
8+
fn main() {
9+
// the inner reference is dangling
10+
let x: &&u32 = unsafe {
11+
let x: u32 = 42;
12+
&&* &raw const x
13+
};
14+
15+
let _ = || { //~ ERROR: encountered a dangling reference
16+
match x {
17+
&&_y => {},
18+
}
19+
};
20+
}

0 commit comments

Comments
 (0)