rapx/check/opt/data_collection/suboptimal/
participant.rs1use annotate_snippets::Level;
2
3use crate::{analysis::dataflow::*, check::opt::OptCheck};
4use rustc_middle::ty::TyCtxt;
5use rustc_span::Span;
6
7use crate::check::opt::check_utils::node_matches_any_call;
8use crate::check::opt::report::OptReport;
9
10crate::def_paths! {
11 hashset_new: "std::collections::HashSet::new",
12 hashset_with_capacity: "std::collections::HashSet::with_capacity",
13 hashmap_new: "std::collections::HashMap::new",
14 hashmap_with_capacity: "std::collections::HashMap::with_capacity",
15 btreeset_new: "std::collections::BTreeSet::new",
16 btreemap_new: "std::collections::BTreeMap::new",
17}
18
19pub struct ParticipantCheck {
20 record: Vec<Span>, }
22
23impl OptCheck for ParticipantCheck {
24 fn new() -> Self {
25 Self { record: vec![] }
26 }
27
28 fn check(&mut self, graph: &Graph, tcx: &TyCtxt) {
29 let def_paths = &DEFPATHS.get_or_init(|| DefPaths::new(tcx));
30 for node in graph.nodes.iter() {
31 if node_matches_any_call(node, |id| {
32 id == def_paths.hashset_new.last_def_id()
33 || id == def_paths.hashmap_new.last_def_id()
34 || id == def_paths.btreemap_new.last_def_id()
35 || id == def_paths.btreeset_new.last_def_id()
36 || id == def_paths.hashmap_with_capacity.last_def_id()
37 || id == def_paths.hashset_with_capacity.last_def_id()
38 }) {
39 self.record.push(node.span);
40 }
41 }
42 }
43
44 fn report(&self, graph: &Graph) {
45 for span in self.record.iter() {
46 report_participant(graph, *span);
47 }
48 }
49
50 fn cnt(&self) -> usize {
51 self.record.len()
52 }
53}
54
55fn report_participant(graph: &Graph, span: Span) {
56 OptReport::from_graph(graph)
57 .file_name(span)
58 .title("Suboptimal data collection detected")
59 .annotate(Level::Error, span, "Data collection created here")
60 .footer("Use faster data collection or hash operators instead. Static container is also a choice")
61 .emit();
62}