-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added tests and par_fold_hashmap lint
- Loading branch information
1 parent
6d628e1
commit 1cb81a8
Showing
9 changed files
with
247 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
use rustc_errors::Applicability; | ||
use rustc_hir::{Expr, ExprKind, StmtKind}; | ||
use rustc_lint::{LateContext, LateLintPass, LintContext}; | ||
use rustc_session::{declare_lint, declare_lint_pass}; | ||
use rustc_span::{sym, Symbol}; | ||
use utils::span_to_snippet_macro; | ||
|
||
declare_lint! { | ||
pub WARN_PAR_FOLD_HASHMAP, | ||
Warn, | ||
"suggest using parallel fold" | ||
} | ||
|
||
declare_lint_pass!(ParFoldHashMap => [WARN_PAR_FOLD_HASHMAP]); | ||
impl<'tcx> LateLintPass<'tcx> for ParFoldHashMap { | ||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { | ||
if let ExprKind::MethodCall(path, recv, args, _span) = &expr.kind | ||
&& path.ident.name == Symbol::intern("fold") | ||
{ | ||
assert_eq!(args.len(), 2); | ||
let id_expr = args[0]; | ||
let op_expr = args[1]; | ||
|
||
// Check the penultimate statement of the fold for a `c.push(v)` | ||
// Quite a specific target, can we be more general? | ||
let ExprKind::Closure(op_cls) = op_expr.kind else { | ||
return; | ||
}; | ||
let hir_map = cx.tcx.hir(); | ||
let cls_body = hir_map.body(op_cls.body); | ||
|
||
let Ok(StmtKind::Semi(fold_op)) = | ||
utils::get_penult_stmt(cls_body.value).map(|s| s.kind) | ||
else { | ||
return; | ||
}; | ||
|
||
let ExprKind::MethodCall(path, _, _, _) = fold_op.kind else { | ||
return; | ||
}; | ||
if path.ident.name != Symbol::intern("insert") { | ||
return; | ||
} | ||
|
||
// Check that this method is on a hashmap | ||
let base_ty = cx | ||
.tcx | ||
.typeck(expr.hir_id.owner.def_id) | ||
.node_type(id_expr.hir_id); | ||
let Some(adt) = base_ty.ty_adt_def() else { | ||
return; | ||
}; | ||
if !cx.tcx.is_diagnostic_item(sym::HashMap, adt.did()) { | ||
return; | ||
} | ||
|
||
// Assume that if we make it here, we can apply the pattern. | ||
let src_map = cx.sess().source_map(); | ||
let cls_snip = span_to_snippet_macro(src_map, op_expr.span); | ||
let recv_snip = span_to_snippet_macro(src_map, recv.span); | ||
let id_snip = span_to_snippet_macro(src_map, id_expr.span); | ||
|
||
let fold_snip = format!("fold(|| HashMap::new(), {cls_snip})"); | ||
let reduce_snip = "reduce(|| HashMap::new(), |mut a, b| { a.extend(b); a })"; | ||
let mut extend_snip = | ||
format!("{{ {id_snip}.extend({recv_snip}.{fold_snip}.{reduce_snip}); {id_snip} }}"); | ||
extend_snip = extend_snip.replace(".iter()", ".par_iter()"); | ||
extend_snip = extend_snip.replace(".iter_mut()", ".par_iter_mut()"); | ||
extend_snip = extend_snip.replace(".into_iter()", ".into_par_iter()"); | ||
|
||
cx.span_lint(WARN_PAR_FOLD_HASHMAP, expr.span, "sequential fold", |diag| { | ||
diag.span_suggestion( | ||
expr.span, | ||
"try using a parallel fold on the iterator", | ||
extend_snip, | ||
Applicability::MachineApplicable, | ||
); | ||
}); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
[toolchain] | ||
channel = "nightly-2024-02-22" | ||
components = ["llvm-tools-preview", "rustc-dev"] | ||
components = ["llvm-tools-preview", "rustc-dev"] |