Skip to main content

rustc_borrowck/polonius/legacy/
accesses.rs

1use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor};
2use rustc_middle::mir::{Body, Local, Location, Place};
3use rustc_middle::ty::TyCtxt;
4use rustc_mir_dataflow::move_paths::{LookupResult, MoveData};
5use tracing::debug;
6
7use super::{LocationIndex, PoloniusFacts, PoloniusLocationTable};
8use crate::def_use::{self, DefUse};
9use crate::universal_regions::UniversalRegions;
10
11/// Emit polonius facts for variable defs, uses, drops, and path accesses.
12pub(crate) fn emit_access_facts<'tcx>(
13    tcx: TyCtxt<'tcx>,
14    facts: &mut PoloniusFacts,
15    body: &Body<'tcx>,
16    location_table: &PoloniusLocationTable,
17    move_data: &MoveData<'tcx>,
18    universal_regions: &UniversalRegions<'tcx>,
19) {
20    let mut extractor = AccessFactsExtractor { facts, move_data, location_table };
21    extractor.visit_body(body);
22
23    for (local, local_decl) in body.local_decls.iter_enumerated() {
24        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_borrowck/src/polonius/legacy/accesses.rs:24",
                        "rustc_borrowck::polonius::legacy::accesses",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_borrowck/src/polonius/legacy/accesses.rs"),
                        ::tracing_core::__macro_support::Option::Some(24u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_borrowck::polonius::legacy::accesses"),
                        ::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};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("add use_of_var_derefs_origin facts - local={0:?}, type={1:?}",
                                                    local, local_decl.ty) as &dyn Value))])
            });
    } else { ; }
};debug!("add use_of_var_derefs_origin facts - local={:?}, type={:?}", local, local_decl.ty);
25        tcx.for_each_free_region(&local_decl.ty, |region| {
26            let region_vid = universal_regions.to_region_vid(region);
27            facts.use_of_var_derefs_origin.push((local, region_vid.into()));
28        });
29    }
30}
31
32/// MIR visitor extracting point-wise facts about accesses.
33struct AccessFactsExtractor<'a, 'tcx> {
34    facts: &'a mut PoloniusFacts,
35    move_data: &'a MoveData<'tcx>,
36    location_table: &'a PoloniusLocationTable,
37}
38
39impl<'tcx> AccessFactsExtractor<'_, 'tcx> {
40    fn location_to_index(&self, location: Location) -> LocationIndex {
41        self.location_table.mid_index(location)
42    }
43}
44
45impl<'a, 'tcx> Visitor<'tcx> for AccessFactsExtractor<'a, 'tcx> {
46    fn visit_local(&mut self, local: Local, context: PlaceContext, location: Location) {
47        match def_use::categorize(context) {
48            Some(DefUse::Def) => {
49                {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_borrowck/src/polonius/legacy/accesses.rs:49",
                        "rustc_borrowck::polonius::legacy::accesses",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_borrowck/src/polonius/legacy/accesses.rs"),
                        ::tracing_core::__macro_support::Option::Some(49u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_borrowck::polonius::legacy::accesses"),
                        ::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};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("AccessFactsExtractor - emit def")
                                            as &dyn Value))])
            });
    } else { ; }
};debug!("AccessFactsExtractor - emit def");
50                self.facts.var_defined_at.push((local, self.location_to_index(location)));
51            }
52            Some(DefUse::Use) => {
53                {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_borrowck/src/polonius/legacy/accesses.rs:53",
                        "rustc_borrowck::polonius::legacy::accesses",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_borrowck/src/polonius/legacy/accesses.rs"),
                        ::tracing_core::__macro_support::Option::Some(53u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_borrowck::polonius::legacy::accesses"),
                        ::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};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("AccessFactsExtractor - emit use")
                                            as &dyn Value))])
            });
    } else { ; }
};debug!("AccessFactsExtractor - emit use");
54                self.facts.var_used_at.push((local, self.location_to_index(location)));
55            }
56            Some(DefUse::Drop) => {
57                {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_borrowck/src/polonius/legacy/accesses.rs:57",
                        "rustc_borrowck::polonius::legacy::accesses",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_borrowck/src/polonius/legacy/accesses.rs"),
                        ::tracing_core::__macro_support::Option::Some(57u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_borrowck::polonius::legacy::accesses"),
                        ::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};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("AccessFactsExtractor - emit drop")
                                            as &dyn Value))])
            });
    } else { ; }
};debug!("AccessFactsExtractor - emit drop");
58                self.facts.var_dropped_at.push((local, self.location_to_index(location)));
59            }
60            _ => (),
61        }
62    }
63
64    fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) {
65        self.super_place(place, context, location);
66
67        match context {
68            PlaceContext::NonMutatingUse(_)
69            | PlaceContext::MutatingUse(MutatingUseContext::Borrow) => {
70                let (LookupResult::Exact(path) | LookupResult::Parent(Some(path))) =
71                    self.move_data.rev_lookup.find(place.as_ref())
72                else {
73                    // There's no path access to emit.
74                    return;
75                };
76                {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_borrowck/src/polonius/legacy/accesses.rs:76",
                        "rustc_borrowck::polonius::legacy::accesses",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_borrowck/src/polonius/legacy/accesses.rs"),
                        ::tracing_core::__macro_support::Option::Some(76u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_borrowck::polonius::legacy::accesses"),
                        ::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};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("AccessFactsExtractor - emit path access ({0:?}, {1:?})",
                                                    path, location) as &dyn Value))])
            });
    } else { ; }
};debug!("AccessFactsExtractor - emit path access ({path:?}, {location:?})");
77                self.facts.path_accessed_at_base.push((path, self.location_to_index(location)));
78            }
79
80            _ => {}
81        }
82    }
83}