|
1 | | -use rustc_middle::mir::{self, Local}; |
2 | | -use rustc_middle::ty::{self as mir_ty, TyCtxt}; |
| 1 | +mod reborrow; |
| 2 | +mod rust_call; |
3 | 3 |
|
4 | | -use crate::analyze::ReplacePlacesVisitor; |
5 | | - |
6 | | -pub struct ReborrowVisitor<'a, 'tcx, 'ctx> { |
7 | | - tcx: TyCtxt<'tcx>, |
8 | | - analyzer: &'a mut super::Analyzer<'tcx, 'ctx>, |
9 | | -} |
10 | | - |
11 | | -impl<'tcx> ReborrowVisitor<'_, 'tcx, '_> { |
12 | | - fn insert_borrow(&mut self, place: mir::Place<'tcx>, inner_ty: mir_ty::Ty<'tcx>) -> Local { |
13 | | - let r = mir_ty::Region::new_from_kind(self.tcx, mir_ty::RegionKind::ReErased); |
14 | | - let ty = mir_ty::Ty::new_mut_ref(self.tcx, r, inner_ty); |
15 | | - let decl = mir::LocalDecl::new(ty, Default::default()).immutable(); |
16 | | - let new_local = self.analyzer.local_decls.push(decl); |
17 | | - let new_local_ty = self.analyzer.borrow_place_(place, inner_ty); |
18 | | - self.analyzer.bind_local(new_local, new_local_ty); |
19 | | - tracing::info!(old_place = ?place, ?new_local, "implicitly borrowed"); |
20 | | - new_local |
21 | | - } |
22 | | - |
23 | | - fn insert_reborrow(&mut self, place: mir::Place<'tcx>, inner_ty: mir_ty::Ty<'tcx>) -> Local { |
24 | | - let r = mir_ty::Region::new_from_kind(self.tcx, mir_ty::RegionKind::ReErased); |
25 | | - let ty = mir_ty::Ty::new_mut_ref(self.tcx, r, inner_ty); |
26 | | - let decl = mir::LocalDecl::new(ty, Default::default()).immutable(); |
27 | | - let new_local = self.analyzer.local_decls.push(decl); |
28 | | - let new_local_ty = self.analyzer.borrow_place_(place, inner_ty); |
29 | | - self.analyzer.bind_local(new_local, new_local_ty); |
30 | | - tracing::info!(old_place = ?place, ?new_local, "implicitly reborrowed"); |
31 | | - new_local |
32 | | - } |
33 | | -} |
34 | | - |
35 | | -impl<'a, 'tcx, 'ctx> mir::visit::MutVisitor<'tcx> for ReborrowVisitor<'a, 'tcx, 'ctx> { |
36 | | - fn tcx(&self) -> TyCtxt<'tcx> { |
37 | | - self.tcx |
38 | | - } |
39 | | - |
40 | | - fn visit_assign( |
41 | | - &mut self, |
42 | | - place: &mut mir::Place<'tcx>, |
43 | | - rvalue: &mut mir::Rvalue<'tcx>, |
44 | | - location: mir::Location, |
45 | | - ) { |
46 | | - if !self.analyzer.is_defined(place.local) { |
47 | | - self.super_assign(place, rvalue, location); |
48 | | - return; |
49 | | - } |
50 | | - |
51 | | - if place.projection.is_empty() && self.analyzer.is_mut_local(place.local) { |
52 | | - let ty = self.analyzer.local_decls[place.local].ty; |
53 | | - let new_local = self.insert_borrow(place.local.into(), ty); |
54 | | - let new_place = self.tcx.mk_place_deref(new_local.into()); |
55 | | - ReplacePlacesVisitor::with_replacement(self.tcx, place.local.into(), new_place) |
56 | | - .visit_rvalue(rvalue, location); |
57 | | - *place = new_place; |
58 | | - self.super_assign(place, rvalue, location); |
59 | | - return; |
60 | | - } |
61 | | - |
62 | | - let inner_place = if place.projection.last() == Some(&mir::PlaceElem::Deref) { |
63 | | - // *m = *m + 1 => m1 = &mut m; *m1 = *m + 1 |
64 | | - let mut projection = place.projection.as_ref().to_vec(); |
65 | | - projection.pop(); |
66 | | - mir::Place { |
67 | | - local: place.local, |
68 | | - projection: self.tcx.mk_place_elems(&projection), |
69 | | - } |
70 | | - } else { |
71 | | - // s.0 = s.0 + 1 => m1 = &mut s.0; *m1 = *m1 + 1 |
72 | | - *place |
73 | | - }; |
74 | | - |
75 | | - let ty = inner_place.ty(&self.analyzer.local_decls, self.tcx).ty; |
76 | | - let (new_local, new_place) = match ty.kind() { |
77 | | - mir_ty::TyKind::Ref(_, inner_ty, m) if m.is_mut() => { |
78 | | - let new_local = self.insert_reborrow(*place, *inner_ty); |
79 | | - (new_local, new_local.into()) |
80 | | - } |
81 | | - mir_ty::TyKind::Adt(adt, args) if adt.is_box() => { |
82 | | - let inner_ty = args.type_at(0); |
83 | | - let new_local = self.insert_borrow(*place, inner_ty); |
84 | | - (new_local, new_local.into()) |
85 | | - } |
86 | | - _ => { |
87 | | - let new_local = self.insert_borrow(*place, ty); |
88 | | - (new_local, self.tcx.mk_place_deref(new_local.into())) |
89 | | - } |
90 | | - }; |
91 | | - |
92 | | - ReplacePlacesVisitor::with_replacement(self.tcx, inner_place, new_place) |
93 | | - .visit_rvalue(rvalue, location); |
94 | | - *place = self.tcx.mk_place_deref(new_local.into()); |
95 | | - self.super_assign(place, rvalue, location); |
96 | | - } |
97 | | - |
98 | | - // TODO: is it always true that the operand is not referred again in rvalue |
99 | | - fn visit_operand(&mut self, operand: &mut mir::Operand<'tcx>, location: mir::Location) { |
100 | | - let Some(p) = operand.place() else { |
101 | | - self.super_operand(operand, location); |
102 | | - return; |
103 | | - }; |
104 | | - |
105 | | - let mir_ty::TyKind::Ref(_, inner_ty, m) = |
106 | | - p.ty(&self.analyzer.local_decls, self.tcx).ty.kind() |
107 | | - else { |
108 | | - self.super_operand(operand, location); |
109 | | - return; |
110 | | - }; |
111 | | - |
112 | | - if m.is_mut() { |
113 | | - let new_local = self.insert_reborrow(self.tcx.mk_place_deref(p), *inner_ty); |
114 | | - *operand = mir::Operand::Move(new_local.into()); |
115 | | - } |
116 | | - |
117 | | - self.super_operand(operand, location); |
118 | | - } |
119 | | -} |
120 | | - |
121 | | -impl<'a, 'tcx, 'ctx> ReborrowVisitor<'a, 'tcx, 'ctx> { |
122 | | - pub fn new(analyzer: &'a mut super::Analyzer<'tcx, 'ctx>) -> Self { |
123 | | - let tcx = analyzer.tcx; |
124 | | - Self { analyzer, tcx } |
125 | | - } |
126 | | - |
127 | | - pub fn visit_statement(&mut self, stmt: &mut mir::Statement<'tcx>) { |
128 | | - // dummy location |
129 | | - mir::visit::MutVisitor::visit_statement(self, stmt, mir::Location::START); |
130 | | - } |
131 | | - |
132 | | - pub fn visit_terminator(&mut self, term: &mut mir::Terminator<'tcx>) { |
133 | | - // dummy location |
134 | | - mir::visit::MutVisitor::visit_terminator(self, term, mir::Location::START); |
135 | | - } |
136 | | -} |
| 4 | +pub use reborrow::ReborrowVisitor; |
| 5 | +pub use rust_call::RustCallVisitor; |
0 commit comments