Skip to content

Commit b4161b2

Browse files
committed
now can handle iter_mut
1 parent d30f467 commit b4161b2

File tree

9 files changed

+49
-88
lines changed

9 files changed

+49
-88
lines changed

Cargo.lock

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "mate"
3-
version = "0.1.2"
3+
version = "0.1.3"
44
authors = [
55
"Cameron Low <cameron.low.2018@bristol.ac.uk>",
66
"Luca Carlig <luca.carlig@huawei.com",

lints/par_iter/src/lib.rs

+21-2
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ impl<'tcx> LateLintPass<'tcx> for ParIter {
7272

7373
let mut top_expr = *recv;
7474
let mut found_iter_method = false;
75+
let mut is_mut = false;
7576

7677
while let Some(parent_expr) = get_parent_expr(cx, top_expr) {
7778
match parent_expr.kind {
@@ -86,6 +87,9 @@ impl<'tcx> LateLintPass<'tcx> for ParIter {
8687
// Mark that we've found an iteration method
8788
found_iter_method = true;
8889
}
90+
if method_name.ident.as_str() == "iter_mut" {
91+
is_mut = true;
92+
}
8993

9094
if !allowed_methods.contains(method_name.ident.as_str()) {
9195
return;
@@ -109,7 +113,11 @@ impl<'tcx> LateLintPass<'tcx> for ParIter {
109113
return;
110114
}
111115

112-
let mut validator = Validator { cx, is_valid: true };
116+
let mut validator = Validator {
117+
cx,
118+
is_valid: true,
119+
is_mut,
120+
};
113121
validator.visit_expr(top_expr);
114122
if !validator.is_valid {
115123
return;
@@ -135,6 +143,7 @@ impl<'tcx> LateLintPass<'tcx> for ParIter {
135143
struct Validator<'a, 'tcx> {
136144
cx: &'a LateContext<'tcx>,
137145
is_valid: bool,
146+
is_mut: bool,
138147
}
139148

140149
impl<'a, 'tcx> hir::intravisit::Visitor<'_> for Validator<'a, 'tcx> {
@@ -148,8 +157,18 @@ impl<'a, 'tcx> hir::intravisit::Visitor<'_> for Validator<'a, 'tcx> {
148157

149158
for arg in args {
150159
if let hir::ExprKind::Closure(closure) = arg.kind {
160+
let mut mut_params = hir::HirIdSet::default();
151161
let body = self.cx.tcx.hir().body(closure.body);
152-
self.is_valid &= check_variables(self.cx, closure.def_id, body);
162+
163+
if self.is_mut {
164+
for param in body.params {
165+
if let hir::PatKind::Binding(_, hir_id, _, _) = param.pat.kind {
166+
mut_params.insert(hir_id);
167+
}
168+
}
169+
}
170+
171+
self.is_valid &= check_variables(self.cx, closure.def_id, body, &mut_params);
153172
}
154173
}
155174
}

lints/par_iter/src/variable_check.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,10 @@ pub(crate) fn check_variables<'tcx>(
3333
cx: &LateContext<'tcx>,
3434
body_owner: hir::def_id::LocalDefId,
3535
body: &hir::Body<'tcx>,
36+
mut_params: &hir::HirIdSet,
3637
) -> bool {
3738
let MutablyUsedVariablesCtxt {
38-
mutably_used_vars,
39+
mut mutably_used_vars,
3940
all_vars,
4041
..
4142
} = {
@@ -77,7 +78,10 @@ pub(crate) fn check_variables<'tcx>(
7778
for ty in all_vars {
7879
res &= is_type_valid(cx, ty);
7980
}
81+
mutably_used_vars.retain(|&item| !mut_params.contains(&item));
82+
8083
res &= mutably_used_vars.is_empty();
84+
8185
res
8286
}
8387

lints/par_iter/ui/main.fixed

+7
Original file line numberDiff line numberDiff line change
@@ -457,3 +457,10 @@ fn multiple_iter_one_chain() {
457457

458458
println!("{:?}", names_over_30);
459459
}
460+
461+
// should parallelize
462+
fn simple_iter_mut() {
463+
let mut numbers = vec![1, 2, 3, 4, 5];
464+
numbers.par_iter_mut().for_each(|num| *num *= 2); // Double each number
465+
println!("{:?}", numbers);
466+
}

lints/par_iter/ui/main.rs

+7
Original file line numberDiff line numberDiff line change
@@ -457,3 +457,10 @@ fn multiple_iter_one_chain() {
457457

458458
println!("{:?}", names_over_30);
459459
}
460+
461+
// should parallelize
462+
fn simple_iter_mut() {
463+
let mut numbers = vec![1, 2, 3, 4, 5];
464+
numbers.iter_mut().for_each(|num| *num *= 2); // Double each number
465+
println!("{:?}", numbers);
466+
}

lints/par_iter/ui/main.stderr

+7-1
Original file line numberDiff line numberDiff line change
@@ -103,5 +103,11 @@ LL ~ let names_over_30: Vec<String> = people
103103
LL + .par_iter()
104104
|
105105

106-
warning: 12 warnings emitted
106+
warning: found iterator that can be parallelized
107+
--> $DIR/main.rs:464:5
108+
|
109+
LL | numbers.iter_mut().for_each(|num| *num *= 2); // Double each number
110+
| ^^^^^^^^^^^^^^^^^^ help: try using a parallel iterator: `numbers.par_iter_mut()`
111+
112+
warning: 13 warnings emitted
107113

lints/par_iter/ui/main2.fixed

-41
Original file line numberDiff line numberDiff line change
@@ -10,40 +10,6 @@ use std::rc::Rc;
1010

1111
fn main() {}
1212

13-
// // 1st should parallelize, 2nd no
14-
// fn multiple_iter_one_chain() {
15-
// let people = vec![
16-
// Person {
17-
// name: "Alice".to_string(),
18-
// age: 25,
19-
// },
20-
// Person {
21-
// name: "Bob".to_string(),
22-
// age: 35,
23-
// },
24-
// Person {
25-
// name: "Carol".to_string(),
26-
// age: 32,
27-
// },
28-
// ];
29-
30-
// let mut counter = 0;
31-
32-
// let names_over_30: Vec<String> = people
33-
// .iter()
34-
// .filter(|p| p.age > 30)
35-
// .map(|p| p.name.clone())
36-
// .collect::<Vec<String>>()
37-
// .into_iter()
38-
// .map(|name| {
39-
// counter += 1;
40-
// format!("{}: {}", counter, name)
41-
// })
42-
// .collect();
43-
44-
// println!("{:?}", names_over_30);
45-
// }
46-
4713
// // no
4814
// pub fn complex_long_chain_no_par() {
4915
// let words = vec!["apple", "banana", "cherry", "date"];
@@ -68,13 +34,6 @@ fn main() {}
6834
// });
6935
// }
7036

71-
// // should parallelize
72-
// fn simple_iter_mut() {
73-
// let mut numbers = vec![1, 2, 3, 4, 5];
74-
// numbers.iter_mut().for_each(|num| *num *= 2); // Double each number
75-
// println!("{:?}", numbers);
76-
// }
77-
7837
// // should parallelize
7938
// fn no_iter_keywords() {
8039
// (0..100).for_each(|x| println!("{x}"));

lints/par_iter/ui/main2.rs

-41
Original file line numberDiff line numberDiff line change
@@ -10,40 +10,6 @@ use std::rc::Rc;
1010

1111
fn main() {}
1212

13-
// // 1st should parallelize, 2nd no
14-
// fn multiple_iter_one_chain() {
15-
// let people = vec![
16-
// Person {
17-
// name: "Alice".to_string(),
18-
// age: 25,
19-
// },
20-
// Person {
21-
// name: "Bob".to_string(),
22-
// age: 35,
23-
// },
24-
// Person {
25-
// name: "Carol".to_string(),
26-
// age: 32,
27-
// },
28-
// ];
29-
30-
// let mut counter = 0;
31-
32-
// let names_over_30: Vec<String> = people
33-
// .iter()
34-
// .filter(|p| p.age > 30)
35-
// .map(|p| p.name.clone())
36-
// .collect::<Vec<String>>()
37-
// .into_iter()
38-
// .map(|name| {
39-
// counter += 1;
40-
// format!("{}: {}", counter, name)
41-
// })
42-
// .collect();
43-
44-
// println!("{:?}", names_over_30);
45-
// }
46-
4713
// // no
4814
// pub fn complex_long_chain_no_par() {
4915
// let words = vec!["apple", "banana", "cherry", "date"];
@@ -68,13 +34,6 @@ fn main() {}
6834
// });
6935
// }
7036

71-
// // should parallelize
72-
// fn simple_iter_mut() {
73-
// let mut numbers = vec![1, 2, 3, 4, 5];
74-
// numbers.iter_mut().for_each(|num| *num *= 2); // Double each number
75-
// println!("{:?}", numbers);
76-
// }
77-
7837
// // should parallelize
7938
// fn no_iter_keywords() {
8039
// (0..100).for_each(|x| println!("{x}"));

0 commit comments

Comments
 (0)