Skip to main content

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

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