rustc_borrowck/polonius/legacy/
mod.rs1use std::iter;
7
8use either::Either;
9use rustc_middle::mir::{Body, Local, LocalKind, Location};
10use rustc_middle::ty::{GenericArg, TyCtxt};
11use rustc_mir_dataflow::move_paths::{InitKind, InitLocation, MoveData};
12use tracing::debug;
13
14use crate::borrow_set::BorrowSet;
15use crate::constraints::OutlivesConstraint;
16use crate::handle_placeholders::LoweredConstraints;
17use crate::type_check::free_region_relations::UniversalRegionRelations;
18use crate::universal_regions::UniversalRegions;
19
20mod accesses;
21mod loan_invalidations;
22mod loan_kills;
23mod location;
24pub use self::location::*;
25mod facts;
26pub use self::facts::*;
27
28pub(crate) fn emit_facts<'tcx>(
39 facts: &mut Option<PoloniusFacts>,
40 tcx: TyCtxt<'tcx>,
41 location_table: &PoloniusLocationTable,
42 body: &Body<'tcx>,
43 borrow_set: &BorrowSet<'tcx>,
44 move_data: &MoveData<'tcx>,
45 universal_region_relations: &UniversalRegionRelations<'tcx>,
46 constraints: &LoweredConstraints<'tcx>,
47) {
48 let Some(facts) = facts else {
49 return;
51 };
52 let _prof_timer = tcx.prof.generic_activity("polonius_fact_generation");
53 emit_move_facts(facts, body, location_table, move_data);
54 emit_universal_region_facts(facts, borrow_set, universal_region_relations);
55 loan_kills::emit_loan_kills(tcx, facts, body, location_table, borrow_set);
56 loan_invalidations::emit_loan_invalidations(tcx, facts, body, location_table, borrow_set);
57 accesses::emit_access_facts(
58 tcx,
59 facts,
60 body,
61 location_table,
62 move_data,
63 &universal_region_relations.universal_regions,
64 );
65 emit_outlives_facts(facts, location_table, constraints);
66}
67
68fn emit_move_facts(
70 facts: &mut PoloniusFacts,
71 body: &Body<'_>,
72 location_table: &PoloniusLocationTable,
73 move_data: &MoveData<'_>,
74) {
75 facts.path_is_var.extend(move_data.rev_lookup.iter_locals_enumerated().map(|(l, r)| (r, l)));
76
77 for (child, move_path) in move_data.move_paths.iter_enumerated() {
78 if let Some(parent) = move_path.parent {
79 facts.child_path.push((child, parent));
80 }
81 }
82
83 let fn_entry_start = location_table.start_index(Location::START);
84
85 for init in move_data.inits.iter() {
87 match init.location {
88 InitLocation::Statement(location) => {
89 let block_data = &body[location.block];
90 let is_terminator = location.statement_index == block_data.statements.len();
91
92 if is_terminator && init.kind == InitKind::NonPanicPathOnly {
93 for successor in block_data.terminator().successors() {
97 if body[successor].is_cleanup {
98 continue;
99 }
100
101 let first_statement = successor.start_location();
104 facts
105 .path_assigned_at_base
106 .push((init.path, location_table.start_index(first_statement)));
107 }
108 } else {
109 facts
112 .path_assigned_at_base
113 .push((init.path, location_table.mid_index(location)));
114 }
115 }
116 InitLocation::Argument(local) => {
118 if !(body.local_kind(local) == LocalKind::Arg) {
::core::panicking::panic("assertion failed: body.local_kind(local) == LocalKind::Arg")
};assert!(body.local_kind(local) == LocalKind::Arg);
119 facts.path_assigned_at_base.push((init.path, fn_entry_start));
120 }
121 }
122 }
123
124 for (local, path) in move_data.rev_lookup.iter_locals_enumerated() {
125 if body.local_kind(local) != LocalKind::Arg {
126 facts.path_moved_at_base.push((path, fn_entry_start));
129 }
130 }
131
132 facts.path_moved_at_base.extend(
135 move_data.move_outs.iter().map(|mo| (mo.path, location_table.mid_index(mo.source))),
136 );
137}
138
139fn emit_universal_region_facts(
141 facts: &mut PoloniusFacts,
142 borrow_set: &BorrowSet<'_>,
143 universal_region_relations: &UniversalRegionRelations<'_>,
144) {
145 let universal_regions = &universal_region_relations.universal_regions;
152 facts
153 .universal_region
154 .extend(universal_regions.universal_regions_iter().map(PoloniusRegionVid::from));
155 let borrow_count = borrow_set.len();
156 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/080cc27146389dbb5c8772c476b1937be9c6110f/compiler/rustc_borrowck/src/polonius/legacy/mod.rs:156",
"rustc_borrowck::polonius::legacy", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/080cc27146389dbb5c8772c476b1937be9c6110f/compiler/rustc_borrowck/src/polonius/legacy/mod.rs"),
::tracing_core::__macro_support::Option::Some(156u32),
::tracing_core::__macro_support::Option::Some("rustc_borrowck::polonius::legacy"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("emit_universal_region_facts: polonius placeholders, num_universals={0}, borrow_count={1}",
universal_regions.len(), borrow_count) as
&dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(
157 "emit_universal_region_facts: polonius placeholders, num_universals={}, borrow_count={}",
158 universal_regions.len(),
159 borrow_count
160 );
161
162 for universal_region in universal_regions.universal_regions_iter() {
163 let universal_region_idx = universal_region.index();
164 let placeholder_loan_idx = borrow_count + universal_region_idx;
165 facts.placeholder.push((universal_region.into(), placeholder_loan_idx.into()));
166 }
167
168 for (fr1, fr2) in universal_region_relations.known_outlives() {
171 if fr1 != fr2 {
172 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/080cc27146389dbb5c8772c476b1937be9c6110f/compiler/rustc_borrowck/src/polonius/legacy/mod.rs:172",
"rustc_borrowck::polonius::legacy", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/080cc27146389dbb5c8772c476b1937be9c6110f/compiler/rustc_borrowck/src/polonius/legacy/mod.rs"),
::tracing_core::__macro_support::Option::Some(172u32),
::tracing_core::__macro_support::Option::Some("rustc_borrowck::polonius::legacy"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("emit_universal_region_facts: emitting polonius `known_placeholder_subset` fr1={0:?}, fr2={1:?}",
fr1, fr2) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(
173 "emit_universal_region_facts: emitting polonius `known_placeholder_subset` \
174 fr1={:?}, fr2={:?}",
175 fr1, fr2
176 );
177 facts.known_placeholder_subset.push((fr1.into(), fr2.into()));
178 }
179 }
180}
181
182pub(crate) fn emit_drop_facts<'tcx>(
185 tcx: TyCtxt<'tcx>,
186 local: Local,
187 kind: &GenericArg<'tcx>,
188 universal_regions: &UniversalRegions<'tcx>,
189 facts: &mut Option<PoloniusFacts>,
190) {
191 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/080cc27146389dbb5c8772c476b1937be9c6110f/compiler/rustc_borrowck/src/polonius/legacy/mod.rs:191",
"rustc_borrowck::polonius::legacy", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/080cc27146389dbb5c8772c476b1937be9c6110f/compiler/rustc_borrowck/src/polonius/legacy/mod.rs"),
::tracing_core::__macro_support::Option::Some(191u32),
::tracing_core::__macro_support::Option::Some("rustc_borrowck::polonius::legacy"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("emit_drop_facts(local={0:?}, kind={1:?}",
local, kind) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("emit_drop_facts(local={:?}, kind={:?}", local, kind);
192 let Some(facts) = facts.as_mut() else { return };
193 let _prof_timer = tcx.prof.generic_activity("polonius_fact_generation");
194 tcx.for_each_free_region(&kind, |drop_live_region| {
195 let region_vid = universal_regions.to_region_vid(drop_live_region);
196 facts.drop_of_var_derefs_origin.push((local, region_vid.into()));
197 });
198}
199
200fn emit_outlives_facts<'tcx>(
203 facts: &mut PoloniusFacts,
204 location_table: &PoloniusLocationTable,
205 constraints: &LoweredConstraints<'tcx>,
206) {
207 facts.subset_base.extend(constraints.outlives_constraints.outlives().iter().flat_map(
208 |constraint: &OutlivesConstraint<'_>| {
209 if let Some(from_location) = constraint.locations.from_location() {
210 Either::Left(iter::once((
211 constraint.sup.into(),
212 constraint.sub.into(),
213 location_table.mid_index(from_location),
214 )))
215 } else {
216 Either::Right(
217 location_table.all_points().map(move |location| {
218 (constraint.sup.into(), constraint.sub.into(), location)
219 }),
220 )
221 }
222 },
223 ));
224}