Skip to main content

rapx/check/opt/data_collection/suboptimal/
slice_contains.rs

1use 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}