]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_typeck/src/check/generator_interior/drop_ranges/record_consumed_borrow.rs
Do not suggest using a const parameter when there are bounds on an unused type parameter
[rust.git] / compiler / rustc_typeck / src / check / generator_interior / drop_ranges / record_consumed_borrow.rs
1 use super::TrackedValue;
2 use crate::{
3     check::FnCtxt,
4     expr_use_visitor::{self, ExprUseVisitor},
5 };
6 use hir::{def_id::DefId, Body, HirId, HirIdMap};
7 use rustc_data_structures::stable_set::FxHashSet;
8 use rustc_hir as hir;
9 use rustc_middle::hir::map::Map;
10
11 pub(super) fn find_consumed_and_borrowed<'a, 'tcx>(
12     fcx: &'a FnCtxt<'a, 'tcx>,
13     def_id: DefId,
14     body: &'tcx Body<'tcx>,
15 ) -> ConsumedAndBorrowedPlaces {
16     let mut expr_use_visitor = ExprUseDelegate::new(fcx.tcx.hir());
17     expr_use_visitor.consume_body(fcx, def_id, body);
18     expr_use_visitor.places
19 }
20
21 pub(super) struct ConsumedAndBorrowedPlaces {
22     /// Records the variables/expressions that are dropped by a given expression.
23     ///
24     /// The key is the hir-id of the expression, and the value is a set or hir-ids for variables
25     /// or values that are consumed by that expression.
26     ///
27     /// Note that this set excludes "partial drops" -- for example, a statement like `drop(x.y)` is
28     /// not considered a drop of `x`, although it would be a drop of `x.y`.
29     pub(super) consumed: HirIdMap<FxHashSet<TrackedValue>>,
30     /// A set of hir-ids of values or variables that are borrowed at some point within the body.
31     pub(super) borrowed: FxHashSet<TrackedValue>,
32 }
33
34 /// Works with ExprUseVisitor to find interesting values for the drop range analysis.
35 ///
36 /// Interesting values are those that are either dropped or borrowed. For dropped values, we also
37 /// record the parent expression, which is the point where the drop actually takes place.
38 struct ExprUseDelegate<'tcx> {
39     hir: Map<'tcx>,
40     places: ConsumedAndBorrowedPlaces,
41 }
42
43 impl<'tcx> ExprUseDelegate<'tcx> {
44     fn new(hir: Map<'tcx>) -> Self {
45         Self {
46             hir,
47             places: ConsumedAndBorrowedPlaces {
48                 consumed: <_>::default(),
49                 borrowed: <_>::default(),
50             },
51         }
52     }
53
54     fn consume_body(&mut self, fcx: &'_ FnCtxt<'_, 'tcx>, def_id: DefId, body: &'tcx Body<'tcx>) {
55         // Run ExprUseVisitor to find where values are consumed.
56         ExprUseVisitor::new(
57             self,
58             &fcx.infcx,
59             def_id.expect_local(),
60             fcx.param_env,
61             &fcx.typeck_results.borrow(),
62         )
63         .consume_body(body);
64     }
65
66     fn mark_consumed(&mut self, consumer: HirId, target: TrackedValue) {
67         if !self.places.consumed.contains_key(&consumer) {
68             self.places.consumed.insert(consumer, <_>::default());
69         }
70         self.places.consumed.get_mut(&consumer).map(|places| places.insert(target));
71     }
72 }
73
74 impl<'tcx> expr_use_visitor::Delegate<'tcx> for ExprUseDelegate<'tcx> {
75     fn consume(
76         &mut self,
77         place_with_id: &expr_use_visitor::PlaceWithHirId<'tcx>,
78         diag_expr_id: HirId,
79     ) {
80         let parent = match self.hir.find_parent_node(place_with_id.hir_id) {
81             Some(parent) => parent,
82             None => place_with_id.hir_id,
83         };
84         debug!(
85             "consume {:?}; diag_expr_id={:?}, using parent {:?}",
86             place_with_id, diag_expr_id, parent
87         );
88         place_with_id
89             .try_into()
90             .map_or((), |tracked_value| self.mark_consumed(parent, tracked_value));
91     }
92
93     fn borrow(
94         &mut self,
95         place_with_id: &expr_use_visitor::PlaceWithHirId<'tcx>,
96         _diag_expr_id: HirId,
97         _bk: rustc_middle::ty::BorrowKind,
98     ) {
99         self.places
100             .borrowed
101             .insert(TrackedValue::from_place_with_projections_allowed(place_with_id));
102     }
103
104     fn mutate(
105         &mut self,
106         _assignee_place: &expr_use_visitor::PlaceWithHirId<'tcx>,
107         _diag_expr_id: HirId,
108     ) {
109     }
110
111     fn fake_read(
112         &mut self,
113         _place: expr_use_visitor::Place<'tcx>,
114         _cause: rustc_middle::mir::FakeReadCause,
115         _diag_expr_id: HirId,
116     ) {
117     }
118 }