Skip to content

Commit bcefe60

Browse files
refactor(clippy_utils::mir::visit_local_usage): use const generics (rust-lang#16637)
Encodes the direct relationship between the lengths of `locals` and the returned list, making the code more type-safe changelog: none
2 parents 625bd55 + c91298a commit bcefe60

File tree

3 files changed

+38
-34
lines changed

3 files changed

+38
-34
lines changed

clippy_lints/src/methods/readonly_write_lock.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,14 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, receiver
3838
.local_decls
3939
.iter_enumerated()
4040
.find(|(_, decl)| local.span.contains(decl.source_info.span))
41-
&& let Some(usages) = visit_local_usage(
42-
&[local],
41+
&& let Some([usage]) = visit_local_usage(
42+
[local],
4343
mir,
4444
Location {
4545
block: START_BLOCK,
4646
statement_index: 0,
4747
},
4848
)
49-
&& let [usage] = usages.as_slice()
5049
{
5150
let writer_never_mutated = usage.local_consume_or_mutate_locs.is_empty();
5251

clippy_lints/src/redundant_clone.rs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -368,25 +368,25 @@ struct CloneUsage {
368368
}
369369

370370
fn visit_clone_usage(cloned: mir::Local, clone: mir::Local, mir: &mir::Body<'_>, bb: mir::BasicBlock) -> CloneUsage {
371-
if let Some((
372-
LocalUsage {
373-
local_use_locs: cloned_use_locs,
374-
local_consume_or_mutate_locs: cloned_consume_or_mutate_locs,
375-
},
376-
LocalUsage {
377-
local_use_locs: _,
378-
local_consume_or_mutate_locs: clone_consume_or_mutate_locs,
379-
},
380-
)) = visit_local_usage(
381-
&[cloned, clone],
371+
if let Some(
372+
[
373+
LocalUsage {
374+
local_use_locs: cloned_use_locs,
375+
local_consume_or_mutate_locs: cloned_consume_or_mutate_locs,
376+
},
377+
LocalUsage {
378+
local_use_locs: _,
379+
local_consume_or_mutate_locs: clone_consume_or_mutate_locs,
380+
},
381+
],
382+
) = visit_local_usage(
383+
[cloned, clone],
382384
mir,
383385
mir::Location {
384386
block: bb,
385387
statement_index: mir.basic_blocks[bb].statements.len(),
386388
},
387-
)
388-
.map(|mut vec| (vec.remove(0), vec.remove(0)))
389-
{
389+
) {
390390
CloneUsage {
391391
cloned_use_loc: cloned_use_locs.first().copied().into(),
392392
cloned_consume_or_mutate_loc: cloned_consume_or_mutate_locs.first().copied(),

clippy_utils/src/mir/mod.rs

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::iter;
2+
13
use rustc_data_structures::either::Either;
24
use rustc_hir::{Expr, HirId};
35
use rustc_index::bit_set::DenseBitSet;
@@ -22,14 +24,17 @@ pub struct LocalUsage {
2224
pub local_consume_or_mutate_locs: Vec<Location>,
2325
}
2426

25-
pub fn visit_local_usage(locals: &[Local], mir: &Body<'_>, location: Location) -> Option<Vec<LocalUsage>> {
26-
let init = vec![
27+
pub fn visit_local_usage<const N: usize>(
28+
locals: [Local; N],
29+
mir: &Body<'_>,
30+
location: Location,
31+
) -> Option<[LocalUsage; N]> {
32+
let init = [const {
2733
LocalUsage {
2834
local_use_locs: Vec::new(),
2935
local_consume_or_mutate_locs: Vec::new(),
30-
};
31-
locals.len()
32-
];
36+
}
37+
}; N];
3338

3439
traversal::Postorder::new(&mir.basic_blocks, location.block, None)
3540
.collect::<Vec<_>>()
@@ -44,7 +49,7 @@ pub fn visit_local_usage(locals: &[Local], mir: &Body<'_>, location: Location) -
4449
}
4550

4651
let mut v = V {
47-
locals,
52+
locals: &locals,
4853
location,
4954
results: usage,
5055
};
@@ -53,34 +58,34 @@ pub fn visit_local_usage(locals: &[Local], mir: &Body<'_>, location: Location) -
5358
})
5459
}
5560

56-
struct V<'a> {
57-
locals: &'a [Local],
61+
struct V<'a, const N: usize> {
62+
locals: &'a [Local; N],
5863
location: Location,
59-
results: Vec<LocalUsage>,
64+
results: [LocalUsage; N],
6065
}
6166

62-
impl<'tcx> Visitor<'tcx> for V<'_> {
67+
impl<'tcx, const N: usize> Visitor<'tcx> for V<'_, N> {
6368
fn visit_place(&mut self, place: &Place<'tcx>, ctx: PlaceContext, loc: Location) {
6469
if loc.block == self.location.block && loc.statement_index <= self.location.statement_index {
6570
return;
6671
}
6772

6873
let local = place.local;
6974

70-
for (i, self_local) in self.locals.iter().enumerate() {
75+
for (self_local, result) in iter::zip(self.locals, &mut self.results) {
7176
if local == *self_local {
7277
if !matches!(
7378
ctx,
7479
PlaceContext::MutatingUse(MutatingUseContext::Drop) | PlaceContext::NonUse(_)
7580
) {
76-
self.results[i].local_use_locs.push(loc);
81+
result.local_use_locs.push(loc);
7782
}
7883
if matches!(
7984
ctx,
8085
PlaceContext::NonMutatingUse(NonMutatingUseContext::Move | NonMutatingUseContext::Inspect)
8186
| PlaceContext::MutatingUse(MutatingUseContext::Borrow)
8287
) {
83-
self.results[i].local_consume_or_mutate_locs.push(loc);
88+
result.local_consume_or_mutate_locs.push(loc);
8489
}
8590
}
8691
}
@@ -114,16 +119,16 @@ pub fn block_in_cycle(body: &Body<'_>, block: BasicBlock) -> bool {
114119
/// Convenience wrapper around `visit_local_usage`.
115120
pub fn used_exactly_once(mir: &Body<'_>, local: Local) -> Option<bool> {
116121
visit_local_usage(
117-
&[local],
122+
[local],
118123
mir,
119124
Location {
120125
block: START_BLOCK,
121126
statement_index: 0,
122127
},
123128
)
124-
.map(|mut vec| {
125-
let LocalUsage { local_use_locs, .. } = vec.remove(0);
126-
let mut locations = local_use_locs
129+
.map(|[local_usage]| {
130+
let mut locations = local_usage
131+
.local_use_locs
127132
.into_iter()
128133
.filter(|&location| !is_local_assignment(mir, local, location));
129134
if let Some(location) = locations.next() {

0 commit comments

Comments
 (0)