Skip to content

Commit 65c8fda

Browse files
Add support for UseDefChain in rustc_peek
1 parent 53fa5a4 commit 65c8fda

File tree

2 files changed

+82
-6
lines changed

2 files changed

+82
-6
lines changed

src/librustc_mir/transform/rustc_peek.rs

Lines changed: 81 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ use crate::dataflow::{self, do_dataflow, DebugFormatted};
1313
use crate::dataflow::MoveDataParamEnv;
1414
use crate::dataflow::BitDenotation;
1515
use crate::dataflow::DataflowResults;
16+
use crate::dataflow::HaveBeenBorrowedLocals;
17+
use crate::dataflow::{ReachingDefinitions, UseDefChain};
1618
use crate::dataflow::{
1719
DefinitelyInitializedPlaces, MaybeInitializedPlaces, MaybeUninitializedPlaces
1820
};
@@ -51,6 +53,17 @@ impl MirPass for SanityCheck {
5153
DefinitelyInitializedPlaces::new(tcx, body, &mdpe),
5254
|bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]));
5355

56+
let flow_borrowed_locals =
57+
do_dataflow(tcx, body, def_id, &attributes, &dead_unwinds,
58+
HaveBeenBorrowedLocals::new(body),
59+
|_bd, i| DebugFormatted::new(&i));
60+
let flow_reaching_defs =
61+
do_dataflow(tcx, body, def_id, &attributes, &dead_unwinds,
62+
ReachingDefinitions::new(body),
63+
|bd, i| DebugFormatted::new(&bd.get(i).location));
64+
let flow_use_def_chain =
65+
UseDefChain::new(body, &flow_reaching_defs, &flow_borrowed_locals);
66+
5467
if has_rustc_mir_with(&attributes, sym::rustc_peek_maybe_init).is_some() {
5568
sanity_check_via_rustc_peek(tcx, body, def_id, &attributes, &flow_inits);
5669
}
@@ -60,6 +73,9 @@ impl MirPass for SanityCheck {
6073
if has_rustc_mir_with(&attributes, sym::rustc_peek_definite_init).is_some() {
6174
sanity_check_via_rustc_peek(tcx, body, def_id, &attributes, &flow_def_inits);
6275
}
76+
if has_rustc_mir_with(&attributes, sym::rustc_peek_use_def_chain).is_some() {
77+
sanity_check_via_rustc_peek(tcx, body, def_id, &attributes, &flow_use_def_chain);
78+
}
6379
if has_rustc_mir_with(&attributes, sym::stop_after_dataflow).is_some() {
6480
tcx.sess.fatal("stop_after_dataflow ended compilation");
6581
}
@@ -87,7 +103,7 @@ pub fn sanity_check_via_rustc_peek<'tcx, O>(
87103
body: &Body<'tcx>,
88104
def_id: DefId,
89105
_attributes: &[ast::Attribute],
90-
results: &DataflowResults<'tcx, O>,
106+
results: &O,
91107
) where O: RustcPeekAt<'tcx> {
92108
debug!("sanity_check_via_rustc_peek def_id: {:?}", def_id);
93109

@@ -214,27 +230,32 @@ impl PeekCall {
214230
}
215231
}
216232

217-
pub trait RustcPeekAt<'tcx>: BitDenotation<'tcx> {
233+
pub trait RustcPeekAt<'tcx> {
218234
fn peek_at(
219235
&self,
220236
tcx: TyCtxt<'tcx>,
237+
body: &mir::Body<'tcx>,
221238
place: &mir::Place<'tcx>,
222-
flow_state: &BitSet<Self::Idx>,
239+
location: Location,
223240
call: PeekCall,
224241
);
225242
}
226243

227-
impl<'tcx, O> RustcPeekAt<'tcx> for O
244+
impl<'tcx, O> RustcPeekAt<'tcx> for DataflowResults<'tcx, O>
228245
where O: BitDenotation<'tcx, Idx = MovePathIndex> + HasMoveData<'tcx>,
229246
{
230247
fn peek_at(
231248
&self,
232249
tcx: TyCtxt<'tcx>,
250+
body: &mir::Body<'tcx>,
233251
place: &mir::Place<'tcx>,
234-
flow_state: &BitSet<Self::Idx>,
252+
location: Location,
235253
call: PeekCall,
236254
) {
237-
match self.move_data().rev_lookup.find(place) {
255+
let operator = self.operator();
256+
let flow_state = dataflow::state_for_location(location, operator, self, body);
257+
258+
match operator.move_data().rev_lookup.find(place) {
238259
LookupResult::Exact(peek_mpi) => {
239260
let bit_state = flow_state.contains(peek_mpi);
240261
debug!("rustc_peek({:?} = &{:?}) bit_state: {}",
@@ -249,3 +270,57 @@ impl<'tcx, O> RustcPeekAt<'tcx> for O
249270
}
250271
}
251272
}
273+
274+
impl<'tcx> RustcPeekAt<'tcx> for UseDefChain<'_, 'tcx> {
275+
fn peek_at(
276+
&self,
277+
tcx: TyCtxt<'tcx>,
278+
body: &mir::Body<'tcx>,
279+
place: &mir::Place<'tcx>,
280+
location: Location,
281+
call: PeekCall,
282+
) {
283+
284+
let base_local = place
285+
.base_direct()
286+
.expect("Deref in argument to `rustc_peek`")
287+
.local()
288+
.expect("Argument to `rustc_peek` must be a local variable");
289+
290+
let mut defs: Vec<_> = self
291+
.defs_for_use(base_local, location)
292+
.map(|def| {
293+
let span = def
294+
.location
295+
.map(|loc| {
296+
let block = &body.basic_blocks()[loc.block];
297+
block.statements
298+
.get(loc.statement_index)
299+
.map(|stmt| stmt.source_info)
300+
.unwrap_or(block.terminator().source_info)
301+
.span
302+
})
303+
.unwrap_or_else(|| {
304+
// `def` represents the value of a parameter on function entry.
305+
let local = def.kind.direct().unwrap();
306+
body.local_decls[local].source_info.span
307+
});
308+
309+
let src = tcx.sess.source_map();
310+
let snippet = src.span_to_snippet(span).unwrap();
311+
let line_index = src.span_to_lines(span).unwrap().lines[0].line_index;
312+
let line_no = line_index + 1;
313+
314+
(line_no, snippet)
315+
})
316+
.collect();
317+
318+
defs.sort_by_key(|(line_no, _)| *line_no);
319+
let defs: Vec<_> = defs.into_iter()
320+
.map(|(line_no, snippet)| format!("{}: \"{}\"", line_no, snippet))
321+
.collect();
322+
323+
let msg = format!("rustc_peek: [{}]", defs.join(", "));
324+
tcx.sess.span_err(call.span, &msg);
325+
}
326+
}

src/libsyntax_pos/symbol.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,7 @@ symbols! {
593593
rustc_peek_definite_init,
594594
rustc_peek_maybe_init,
595595
rustc_peek_maybe_uninit,
596+
rustc_peek_use_def_chain,
596597
rustc_private,
597598
rustc_proc_macro_decls,
598599
rustc_promotable,

0 commit comments

Comments
 (0)