rapx/check/opt/data_collection/suboptimal/
slice_contains.rs1use annotate_snippets::Level;
2
3
4use crate::{
5 analysis::dataflow::Graph,
6 check::opt::OptCheck,
7 check::opt::loop_visitors::MethodCallFinder,
8};
9use rustc_hir::intravisit;
10use rustc_middle::ty::TyCtxt;
11use rustc_span::Span;
12
13use crate::check::opt::report::OptReport;
14
15crate::def_paths! {
16 slice_contains: "slice::contains",
17}
18
19
20pub struct SliceContainsCheck {
21 record: Vec<Span>,
22}
23
24impl OptCheck for SliceContainsCheck {
25 fn new() -> Self {
26 Self { record: Vec::new() }
27 }
28
29 fn check(&mut self, graph: &Graph, tcx: &TyCtxt) {
30 let _ = &DEFPATHS.get_or_init(|| DefPaths::new(tcx));
31 let def_id = graph.def_id;
32 let body = tcx.hir_body_owned_by(def_id.as_local().unwrap());
33 let typeck_results = tcx.typeck(def_id.as_local().unwrap());
34 let target_def_id = DEFPATHS.get().unwrap().slice_contains.last_def_id();
35 let mut finder = MethodCallFinder::new(typeck_results, target_def_id);
36 intravisit::walk_body(&mut finder, body);
37 self.record = finder.into_record();
38 }
39
40 fn report(&self, graph: &Graph) {
41 for contains_span in self.record.iter() {
42 report_slice_contains_bug(graph, *contains_span);
43 }
44 }
45
46 fn cnt(&self) -> usize {
47 self.record.len()
48 }
49}
50
51fn report_slice_contains_bug(graph: &Graph, contains_span: Span) {
52 OptReport::from_graph(graph)
53 .title("Improper data collection detected")
54 .annotate(Level::Error, contains_span, "Slice contains happens here.")
55 .footer("Use Set instead of Slice.")
56 .emit();
57}