From 2adb246b5c6bfcaae09971c9d54810cb7d58d43e Mon Sep 17 00:00:00 2001 From: Albin Stjerna Date: Thu, 18 Jul 2019 12:32:06 +0200 Subject: [PATCH 1/8] NLL: New Polonius version --- Cargo.lock | 4 ++-- src/librustc/Cargo.toml | 2 +- src/librustc_mir/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e0d30647809a9..6a5d4ebc1ecdb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2324,9 +2324,9 @@ checksum = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" [[package]] name = "polonius-engine" -version = "0.9.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6b8a5defa2aef9ba4999aaa745fbc01c622ecea35964a306adc3e44be4f3b5b" +checksum = "50fa9dbfd0d3d60594da338cfe6f94028433eecae4b11b7e83fd99759227bbfe" dependencies = [ "datafrog", "log", diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml index 0222a3dde7ab9..a479fabafc014 100644 --- a/src/librustc/Cargo.toml +++ b/src/librustc/Cargo.toml @@ -21,7 +21,7 @@ scoped-tls = "1.0" log = { version = "0.4", features = ["release_max_level_info", "std"] } rustc-rayon = "0.2.0" rustc-rayon-core = "0.2.0" -polonius-engine = "0.9.0" +polonius-engine = "0.10.0" rustc_apfloat = { path = "../librustc_apfloat" } rustc_target = { path = "../librustc_target" } rustc_macros = { path = "../librustc_macros" } diff --git a/src/librustc_mir/Cargo.toml b/src/librustc_mir/Cargo.toml index 21008c737289f..1c0b0b63c0bbd 100644 --- a/src/librustc_mir/Cargo.toml +++ b/src/librustc_mir/Cargo.toml @@ -15,7 +15,7 @@ either = "1.5.0" dot = { path = "../libgraphviz", package = "graphviz" } log = "0.4" log_settings = "0.1.1" -polonius-engine = "0.9.0" +polonius-engine = "0.10.0" rustc = { path = "../librustc" } rustc_target = { path = "../librustc_target" } rustc_data_structures = { path = "../librustc_data_structures" } From 996ba932ccd03f2372c5c25eaf5f5025d397a73c Mon Sep 17 00:00:00 2001 From: Albin Stjerna Date: Thu, 18 Jul 2019 12:38:32 +0200 Subject: [PATCH 2/8] NLL: Adapt to the new Polonius types --- src/librustc_mir/borrow_check/flows.rs | 4 ++-- src/librustc_mir/borrow_check/nll/facts.rs | 16 +++++++++++++--- src/librustc_mir/borrow_check/nll/mod.rs | 4 ++-- .../nll/type_check/liveness/trace.rs | 14 +++++++------- 4 files changed, 24 insertions(+), 14 deletions(-) diff --git a/src/librustc_mir/borrow_check/flows.rs b/src/librustc_mir/borrow_check/flows.rs index bb217a1f965e2..4400e0c8395a2 100644 --- a/src/librustc_mir/borrow_check/flows.rs +++ b/src/librustc_mir/borrow_check/flows.rs @@ -12,7 +12,7 @@ use crate::borrow_check::location::LocationIndex; use polonius_engine::Output; use crate::dataflow::indexes::BorrowIndex; -use crate::dataflow::move_paths::HasMoveData; +use crate::dataflow::move_paths::{HasMoveData, MovePathIndex}; use crate::dataflow::Borrows; use crate::dataflow::EverInitializedPlaces; use crate::dataflow::MaybeUninitializedPlaces; @@ -21,7 +21,7 @@ use either::Either; use std::fmt; use std::rc::Rc; -crate type PoloniusOutput = Output; +crate type PoloniusOutput = Output; // (forced to be `pub` due to its use as an associated type below.) crate struct Flows<'b, 'tcx> { diff --git a/src/librustc_mir/borrow_check/nll/facts.rs b/src/librustc_mir/borrow_check/nll/facts.rs index 05451cdfb83d8..10ce3a099cf2b 100644 --- a/src/librustc_mir/borrow_check/nll/facts.rs +++ b/src/librustc_mir/borrow_check/nll/facts.rs @@ -1,5 +1,5 @@ use crate::borrow_check::location::{LocationIndex, LocationTable}; -use crate::dataflow::indexes::BorrowIndex; +use crate::dataflow::indexes::{BorrowIndex, MovePathIndex}; use polonius_engine::AllFacts as PoloniusAllFacts; use polonius_engine::Atom; use rustc::mir::Local; @@ -11,7 +11,7 @@ use std::fs::{self, File}; use std::io::Write; use std::path::Path; -crate type AllFacts = PoloniusAllFacts; +crate type AllFacts = PoloniusAllFacts; crate trait AllFactsExt { /// Returns `true` if there is a need to gather `AllFacts` given the @@ -65,7 +65,11 @@ impl AllFactsExt for AllFacts { var_drop_used, var_uses_region, var_drops_region, - var_initialized_on_exit, + var_maybe_initialized_on_exit, + parent, + var_starts_path, + initialized_at, + moved_out_at, ]) } Ok(()) @@ -84,6 +88,12 @@ impl Atom for LocationIndex { } } +impl Atom for MovePathIndex { + fn index(self) -> usize { + Idx::index(self) + } +} + struct FactWriter<'w> { location_table: &'w LocationTable, dir: &'w Path, diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs index 11ec154e5b5c1..19a3d0eb03d56 100644 --- a/src/librustc_mir/borrow_check/nll/mod.rs +++ b/src/librustc_mir/borrow_check/nll/mod.rs @@ -4,7 +4,7 @@ use crate::borrow_check::nll::facts::AllFactsExt; use crate::borrow_check::nll::type_check::{MirTypeckResults, MirTypeckRegionConstraints}; use crate::borrow_check::nll::region_infer::values::RegionValueElements; use crate::dataflow::indexes::BorrowIndex; -use crate::dataflow::move_paths::MoveData; +use crate::dataflow::move_paths::{MoveData, MovePathIndex}; use crate::dataflow::FlowAtLocation; use crate::dataflow::MaybeInitializedPlaces; use crate::transform::MirSource; @@ -87,7 +87,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( errors_buffer: &mut Vec, ) -> ( RegionInferenceContext<'tcx>, - Option>>, + Option>>, Option>, ) { let mut all_facts = if AllFacts::enabled(infcx.tcx) { diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs index 039ed939ada7c..de085fc480a0e 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs @@ -134,7 +134,7 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> { // FIXME: this is temporary until we can generate our own initialization if self.cx.typeck.borrowck_context.all_facts.is_some() { - self.add_polonius_var_initialized_on_exit_for(local) + self.add_polonius_var_maybe_initialized_on_exit_for(local) } self.compute_use_live_points_for(local); @@ -161,14 +161,14 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> { // // FIXME: this analysis (the initialization tracking) should be // done in Polonius, but isn't yet. - fn add_polonius_var_initialized_on_exit_for(&mut self, local: Local) { + fn add_polonius_var_maybe_initialized_on_exit_for(&mut self, local: Local) { let move_path = self.cx.move_data.rev_lookup.find_local(local); let facts = self.cx.typeck.borrowck_context.all_facts.as_mut().unwrap(); for block in self.cx.body.basic_blocks().indices() { debug!("polonius: generating initialization facts for {:?} in {:?}", local, block); // iterate through the block, applying the effects of each statement - // up to and including location, and populate `var_initialized_on_exit` + // up to and including location, and populate `var_maybe_initialized_on_exit` self.cx.flow_inits.reset_to_entry_of(block); let start_location = Location { block, statement_index: 0 }; self.cx.flow_inits.apply_local_effect(start_location); @@ -181,7 +181,7 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> { // statement has not yet taken effect: if self.cx.flow_inits.has_any_child_of(move_path).is_some() { facts - .var_initialized_on_exit + .var_maybe_initialized_on_exit .push((local, self.cx.location_table.start_index(current_location))); } @@ -190,7 +190,7 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> { if self.cx.flow_inits.has_any_child_of(move_path).is_some() { facts - .var_initialized_on_exit + .var_maybe_initialized_on_exit .push((local, self.cx.location_table.mid_index(current_location))); } } @@ -199,7 +199,7 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> { if self.cx.flow_inits.has_any_child_of(move_path).is_some() { facts - .var_initialized_on_exit + .var_maybe_initialized_on_exit .push((local, self.cx.location_table.start_index(terminator_location))); } @@ -208,7 +208,7 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> { if self.cx.flow_inits.has_any_child_of(move_path).is_some() { facts - .var_initialized_on_exit + .var_maybe_initialized_on_exit .push((local, self.cx.location_table.mid_index(terminator_location))); } } From 6b09477e91ba7cb6b657b87a51ebd0b127e5ca67 Mon Sep 17 00:00:00 2001 From: Albin Stjerna Date: Fri, 19 Jul 2019 15:38:54 +0200 Subject: [PATCH 3/8] Polonius: emit initialization/move tracking facts - var_starts_path - parent - initialized_at - moved_out_at This also switches to the intended emission of `var_drop_used` fact emission, where that fact is always emitted on a drop-use of a variable, regardless of its initialization status, as Polonius now handles that. --- src/librustc_mir/borrow_check/nll/mod.rs | 60 ++++++++++++++++++- .../nll/type_check/liveness/polonius.rs | 9 ++- .../nll/type_check/liveness/trace.rs | 5 -- src/librustc_mir/dataflow/move_paths/mod.rs | 9 ++- 4 files changed, 74 insertions(+), 9 deletions(-) diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs index 19a3d0eb03d56..9b920eb15599d 100644 --- a/src/librustc_mir/borrow_check/nll/mod.rs +++ b/src/librustc_mir/borrow_check/nll/mod.rs @@ -4,14 +4,14 @@ use crate::borrow_check::nll::facts::AllFactsExt; use crate::borrow_check::nll::type_check::{MirTypeckResults, MirTypeckRegionConstraints}; use crate::borrow_check::nll::region_infer::values::RegionValueElements; use crate::dataflow::indexes::BorrowIndex; -use crate::dataflow::move_paths::{MoveData, MovePathIndex}; +use crate::dataflow::move_paths::{InitLocation, MoveData, MovePathIndex, InitKind}; use crate::dataflow::FlowAtLocation; use crate::dataflow::MaybeInitializedPlaces; use crate::transform::MirSource; use crate::borrow_check::Upvar; use rustc::hir::def_id::DefId; use rustc::infer::InferCtxt; -use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, Local, Body, Promoted}; +use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, Local, Location, Body, LocalKind, BasicBlock, Promoted}; use rustc::ty::{self, RegionKind, RegionVid}; use rustc_data_structures::indexed_vec::IndexVec; use rustc_errors::Diagnostic; @@ -69,6 +69,61 @@ pub(in crate::borrow_check) fn replace_regions_in_mir<'cx, 'tcx>( universal_regions } + +// This function populates an AllFacts instance with base facts related to +// MovePaths and needed for the move analysis. +fn populate_polonius_move_facts(all_facts: &mut AllFacts, move_data: &MoveData<'_>, location_table: &LocationTable, body: &Body<'_>) { + all_facts.var_starts_path.extend(move_data.rev_lookup.iter_locals_enumerated().map(|(v, &m)| (v, m))); + + for (idx, move_path) in move_data.move_paths.iter_enumerated() { + all_facts.parent.extend(move_path.parents(&move_data.move_paths).iter().map(|&parent| (parent, idx))); + } + + // initialized_at + for init in move_data.inits.iter() { + + match init.location { + InitLocation::Statement(location) => { + let block_data = &body[location.block]; + let is_terminator = location.statement_index == block_data.statements.len(); + + if is_terminator && init.kind == InitKind::NonPanicPathOnly { + // We are at the terminator of an init that has a panic path, + // and where the init should not happen on panic + + for &successor in block_data.terminator().successors() { + if body[successor].is_cleanup { + continue; + } + + // The initialization happened in (or rather, when arriving at) + // the successors, but not in the unwind block. + let first_statement = Location { block: successor, statement_index: 0}; + all_facts.initialized_at.push((init.path, location_table.start_index(first_statement))); + } + + } else { + // In all other cases, the initialization just happens at the + // midpoint, like any other effect. + all_facts.initialized_at.push((init.path, location_table.mid_index(location))); + } + }, + // Arguments are initialized on function entry + InitLocation::Argument(local) => { + assert!(body.local_kind(local) == LocalKind::Arg); + let fn_entry = Location {block: BasicBlock::from_u32(0u32), statement_index: 0 }; + all_facts.initialized_at.push((init.path, location_table.start_index(fn_entry))); + + } + } + } + + + // moved_out_at + // deinitialisation is assumed to always happen! + all_facts.moved_out_at.extend(move_data.moves.iter().map(|mo| (mo.path, location_table.mid_index(mo.source)))); +} + /// Computes the (non-lexical) regions from the input MIR. /// /// This may result in errors being reported. @@ -123,6 +178,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( all_facts .universal_region .extend(universal_regions.universal_regions()); + populate_polonius_move_facts(all_facts, move_data, location_table, body); } // Create the region inference context, taking ownership of the diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs index 20d7ec55e3e84..dcdacbbe5be06 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs @@ -13,6 +13,7 @@ struct LivenessPointFactsExtractor<'me> { var_defined: &'me mut VarPointRelations, var_used: &'me mut VarPointRelations, location_table: &'me LocationTable, + var_drop_used: &'me mut VarPointRelations, } // A Visitor to walk through the MIR and extract point-wise facts @@ -30,6 +31,11 @@ impl LivenessPointFactsExtractor<'_> { debug!("LivenessFactsExtractor::insert_use()"); self.var_used.push((local, self.location_to_index(location))); } + + fn insert_drop_use(&mut self, local: Local, location: Location) { + debug!("LivenessFactsExtractor::insert_drop_use()"); + self.var_drop_used.push((local, self.location_to_index(location))); + } } impl Visitor<'tcx> for LivenessPointFactsExtractor<'_> { @@ -37,8 +43,8 @@ impl Visitor<'tcx> for LivenessPointFactsExtractor<'_> { match categorize(context) { Some(DefUse::Def) => self.insert_def(local, location), Some(DefUse::Use) => self.insert_use(local, location), + Some(DefUse::Drop) => self.insert_drop_use(local, location), _ => (), - // NOTE: Drop handling is now done in trace() } } } @@ -65,6 +71,7 @@ pub(super) fn populate_var_liveness_facts( LivenessPointFactsExtractor { var_defined: &mut facts.var_defined, var_used: &mut facts.var_used, + var_drop_used: &mut facts.var_drop_used, location_table, } .visit_body(mir); diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs index de085fc480a0e..1e1768a8e4601 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs @@ -273,11 +273,6 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> { debug_assert_eq!(self.cx.body.terminator_loc(location.block), location,); if self.cx.initialized_at_terminator(location.block, mpi) { - // FIXME: this analysis (the initialization tracking) should be - // done in Polonius, but isn't yet. - if let Some(facts) = self.cx.typeck.borrowck_context.all_facts { - facts.var_drop_used.push((local, self.cx.location_table.mid_index(location))); - } if self.drop_live_at.insert(drop_point) { self.drop_locations.push(location); self.stack.push(drop_point); diff --git a/src/librustc_mir/dataflow/move_paths/mod.rs b/src/librustc_mir/dataflow/move_paths/mod.rs index e5a19572170a7..07b9b662a07aa 100644 --- a/src/librustc_mir/dataflow/move_paths/mod.rs +++ b/src/librustc_mir/dataflow/move_paths/mod.rs @@ -1,9 +1,10 @@ use rustc::ty::{Ty, TyCtxt}; use rustc::mir::*; use rustc::util::nodemap::FxHashMap; -use rustc_data_structures::indexed_vec::{Idx, IndexVec}; +use rustc_data_structures::indexed_vec::{Idx, IndexVec, Enumerated}; use smallvec::SmallVec; use syntax_pos::{Span}; +use core::slice::Iter; use std::fmt; use std::ops::{Index, IndexMut}; @@ -262,6 +263,12 @@ impl MovePathLookup { pub fn find_local(&self, local: Local) -> MovePathIndex { self.locals[local] } + + /// An enumerated iterator of `local`s and their associated + /// `MovePathIndex`es. + pub fn iter_locals_enumerated(&self) -> Enumerated> { + self.locals.iter_enumerated() + } } #[derive(Debug)] From 9f39e001df1f665ce4f2bdbc38576f5fcc02f898 Mon Sep 17 00:00:00 2001 From: Albin Stjerna Date: Tue, 6 Aug 2019 12:12:36 +0200 Subject: [PATCH 4/8] Polonius: Rename `parent` and `var_starts_path` --- src/librustc_mir/borrow_check/nll/facts.rs | 5 ++--- src/librustc_mir/borrow_check/nll/mod.rs | 6 +++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/librustc_mir/borrow_check/nll/facts.rs b/src/librustc_mir/borrow_check/nll/facts.rs index 10ce3a099cf2b..9458b24f07d90 100644 --- a/src/librustc_mir/borrow_check/nll/facts.rs +++ b/src/librustc_mir/borrow_check/nll/facts.rs @@ -65,9 +65,8 @@ impl AllFactsExt for AllFacts { var_drop_used, var_uses_region, var_drops_region, - var_maybe_initialized_on_exit, - parent, - var_starts_path, + child, + path_belongs_to_var, initialized_at, moved_out_at, ]) diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs index 9b920eb15599d..4c76d14bdbbbb 100644 --- a/src/librustc_mir/borrow_check/nll/mod.rs +++ b/src/librustc_mir/borrow_check/nll/mod.rs @@ -73,10 +73,10 @@ pub(in crate::borrow_check) fn replace_regions_in_mir<'cx, 'tcx>( // This function populates an AllFacts instance with base facts related to // MovePaths and needed for the move analysis. fn populate_polonius_move_facts(all_facts: &mut AllFacts, move_data: &MoveData<'_>, location_table: &LocationTable, body: &Body<'_>) { - all_facts.var_starts_path.extend(move_data.rev_lookup.iter_locals_enumerated().map(|(v, &m)| (v, m))); + all_facts.path_belongs_to_var.extend(move_data.rev_lookup.iter_locals_enumerated().map(|(v, &m)| (m, v))); - for (idx, move_path) in move_data.move_paths.iter_enumerated() { - all_facts.parent.extend(move_path.parents(&move_data.move_paths).iter().map(|&parent| (parent, idx))); + for (child, move_path) in move_data.move_paths.iter_enumerated() { + all_facts.child.extend(move_path.parents(&move_data.move_paths).iter().map(|&parent| (child, parent))); } // initialized_at From 6568b086a27c750c9ac69a00f5146a3b51881fb7 Mon Sep 17 00:00:00 2001 From: Albin Stjerna Date: Fri, 16 Aug 2019 15:39:17 +0200 Subject: [PATCH 5/8] Polonius: don't emit `var_maybe_initialized_on_exit` --- .../nll/type_check/liveness/trace.rs | 63 ------------------- 1 file changed, 63 deletions(-) diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs index 1e1768a8e4601..0990074c990d0 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs @@ -131,12 +131,6 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> { for local in live_locals { self.reset_local_state(); self.add_defs_for(local); - - // FIXME: this is temporary until we can generate our own initialization - if self.cx.typeck.borrowck_context.all_facts.is_some() { - self.add_polonius_var_maybe_initialized_on_exit_for(local) - } - self.compute_use_live_points_for(local); self.compute_drop_live_points_for(local); @@ -157,63 +151,6 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> { } } - // WARNING: panics if self.cx.typeck.borrowck_context.all_facts != None - // - // FIXME: this analysis (the initialization tracking) should be - // done in Polonius, but isn't yet. - fn add_polonius_var_maybe_initialized_on_exit_for(&mut self, local: Local) { - let move_path = self.cx.move_data.rev_lookup.find_local(local); - let facts = self.cx.typeck.borrowck_context.all_facts.as_mut().unwrap(); - for block in self.cx.body.basic_blocks().indices() { - debug!("polonius: generating initialization facts for {:?} in {:?}", local, block); - - // iterate through the block, applying the effects of each statement - // up to and including location, and populate `var_maybe_initialized_on_exit` - self.cx.flow_inits.reset_to_entry_of(block); - let start_location = Location { block, statement_index: 0 }; - self.cx.flow_inits.apply_local_effect(start_location); - - for statement_index in 0..self.cx.body[block].statements.len() { - let current_location = Location { block, statement_index }; - - self.cx.flow_inits.reconstruct_statement_effect(current_location); - - // statement has not yet taken effect: - if self.cx.flow_inits.has_any_child_of(move_path).is_some() { - facts - .var_maybe_initialized_on_exit - .push((local, self.cx.location_table.start_index(current_location))); - } - - // statement has now taken effect - self.cx.flow_inits.apply_local_effect(current_location); - - if self.cx.flow_inits.has_any_child_of(move_path).is_some() { - facts - .var_maybe_initialized_on_exit - .push((local, self.cx.location_table.mid_index(current_location))); - } - } - - let terminator_location = self.cx.body.terminator_loc(block); - - if self.cx.flow_inits.has_any_child_of(move_path).is_some() { - facts - .var_maybe_initialized_on_exit - .push((local, self.cx.location_table.start_index(terminator_location))); - } - - // apply the effects of the terminator and push it if needed - self.cx.flow_inits.reset_to_exit_of(block); - - if self.cx.flow_inits.has_any_child_of(move_path).is_some() { - facts - .var_maybe_initialized_on_exit - .push((local, self.cx.location_table.mid_index(terminator_location))); - } - } - } - /// Clear the value of fields that are "per local variable". fn reset_local_state(&mut self) { self.defs.clear(); From 9cd1a1157199b8303bc4fb5af3ae0fab6b91e786 Mon Sep 17 00:00:00 2001 From: Albin Stjerna Date: Fri, 16 Aug 2019 15:42:22 +0200 Subject: [PATCH 6/8] Polonius: don't emit `region_live_at` --- src/librustc_mir/borrow_check/nll/facts.rs | 1 - .../nll/type_check/liveness/mod.rs | 2 +- .../nll/type_check/liveness/trace.rs | 18 ------------------ 3 files changed, 1 insertion(+), 20 deletions(-) diff --git a/src/librustc_mir/borrow_check/nll/facts.rs b/src/librustc_mir/borrow_check/nll/facts.rs index 9458b24f07d90..b11e5e7a85d0e 100644 --- a/src/librustc_mir/borrow_check/nll/facts.rs +++ b/src/librustc_mir/borrow_check/nll/facts.rs @@ -58,7 +58,6 @@ impl AllFactsExt for AllFacts { cfg_edge, killed, outlives, - region_live_at, invalidates, var_used, var_defined, diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs index 8970009b6ee9f..25d7985653c0e 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs @@ -58,7 +58,7 @@ pub(super) fn generate<'tcx>( }; if !live_locals.is_empty() { - trace::trace(typeck, body, elements, flow_inits, move_data, live_locals, location_table); + trace::trace(typeck, body, elements, flow_inits, move_data, live_locals); polonius::populate_var_liveness_facts(typeck, body, location_table); } diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs index 0990074c990d0..eba52ae3384b0 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs @@ -1,4 +1,3 @@ -use crate::borrow_check::location::LocationTable; use crate::borrow_check::nll::region_infer::values::{self, PointIndex, RegionValueElements}; use crate::borrow_check::nll::type_check::liveness::local_use_map::LocalUseMap; use crate::borrow_check::nll::type_check::liveness::polonius; @@ -38,7 +37,6 @@ pub(super) fn trace( flow_inits: &mut FlowAtLocation<'tcx, MaybeInitializedPlaces<'_, 'tcx>>, move_data: &MoveData<'tcx>, live_locals: Vec, - location_table: &LocationTable, ) { debug!("trace()"); @@ -52,7 +50,6 @@ pub(super) fn trace( local_use_map, move_data, drop_data: FxHashMap::default(), - location_table, }; LivenessResults::new(cx).compute_for_all_locals(live_locals); @@ -82,9 +79,6 @@ struct LivenessContext<'me, 'typeck, 'flow, 'tcx> { /// Index indicating where each variable is assigned, used, or /// dropped. local_use_map: &'me LocalUseMap, - - /// Maps between a MIR Location and a LocationIndex - location_table: &'me LocationTable, } struct DropData<'tcx> { @@ -405,7 +399,6 @@ impl LivenessContext<'_, '_, '_, 'tcx> { &mut self.typeck, value, live_at, - self.location_table, ) } @@ -462,7 +455,6 @@ impl LivenessContext<'_, '_, '_, 'tcx> { &mut self.typeck, kind, live_at, - self.location_table, ); polonius::add_var_drops_regions(&mut self.typeck, dropped_local, &kind); @@ -474,7 +466,6 @@ impl LivenessContext<'_, '_, '_, 'tcx> { typeck: &mut TypeChecker<'_, 'tcx>, value: impl TypeFoldable<'tcx>, live_at: &HybridBitSet, - location_table: &LocationTable, ) { debug!("make_all_regions_live(value={:?})", value); debug!( @@ -491,15 +482,6 @@ impl LivenessContext<'_, '_, '_, 'tcx> { .constraints .liveness_constraints .add_elements(live_region_vid, live_at); - - // FIXME: remove this when we can generate our own region-live-at reliably - if let Some(facts) = typeck.borrowck_context.all_facts { - for point in live_at.iter() { - let loc = elements.to_location(point); - facts.region_live_at.push((live_region_vid, location_table.start_index(loc))); - facts.region_live_at.push((live_region_vid, location_table.mid_index(loc))); - } - } }); } From 560ef6d7103f18581b1dcc57de480247ba638677 Mon Sep 17 00:00:00 2001 From: Albin Stjerna Date: Wed, 7 Aug 2019 17:44:35 +0200 Subject: [PATCH 7/8] Polonius: emit variable access facts --- src/librustc_mir/borrow_check/nll/facts.rs | 1 + .../nll/type_check/liveness/mod.rs | 2 +- .../nll/type_check/liveness/polonius.rs | 58 +++++++++++++++---- 3 files changed, 50 insertions(+), 11 deletions(-) diff --git a/src/librustc_mir/borrow_check/nll/facts.rs b/src/librustc_mir/borrow_check/nll/facts.rs index b11e5e7a85d0e..f0beb4d3ae32d 100644 --- a/src/librustc_mir/borrow_check/nll/facts.rs +++ b/src/librustc_mir/borrow_check/nll/facts.rs @@ -68,6 +68,7 @@ impl AllFactsExt for AllFacts { path_belongs_to_var, initialized_at, moved_out_at, + path_accessed_at, ]) } Ok(()) diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs index 25d7985653c0e..3f2ec1ba97017 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs @@ -60,7 +60,7 @@ pub(super) fn generate<'tcx>( if !live_locals.is_empty() { trace::trace(typeck, body, elements, flow_inits, move_data, live_locals); - polonius::populate_var_liveness_facts(typeck, body, location_table); + polonius::populate_access_facts(typeck, body, location_table, move_data); } } diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs index dcdacbbe5be06..d61464b3f387d 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs @@ -1,23 +1,28 @@ use crate::borrow_check::location::{LocationIndex, LocationTable}; +use crate::dataflow::indexes::MovePathIndex; +use crate::dataflow::move_paths::{LookupResult, MoveData}; use crate::util::liveness::{categorize, DefUse}; -use rustc::mir::visit::{PlaceContext, Visitor}; -use rustc::mir::{Body, Local, Location}; +use rustc::mir::visit::{MutatingUseContext, PlaceContext, Visitor}; +use rustc::mir::{Body, Local, Location, Place}; use rustc::ty::subst::Kind; use rustc::ty::Ty; use super::TypeChecker; type VarPointRelations = Vec<(Local, LocationIndex)>; +type MovePathPointRelations = Vec<(MovePathIndex, LocationIndex)>; -struct LivenessPointFactsExtractor<'me> { +struct UseFactsExtractor<'me> { var_defined: &'me mut VarPointRelations, var_used: &'me mut VarPointRelations, location_table: &'me LocationTable, var_drop_used: &'me mut VarPointRelations, + move_data: &'me MoveData<'me>, + path_accessed_at: &'me mut MovePathPointRelations, } // A Visitor to walk through the MIR and extract point-wise facts -impl LivenessPointFactsExtractor<'_> { +impl UseFactsExtractor<'_> { fn location_to_index(&self, location: Location) -> LocationIndex { self.location_table.mid_index(location) } @@ -36,9 +41,21 @@ impl LivenessPointFactsExtractor<'_> { debug!("LivenessFactsExtractor::insert_drop_use()"); self.var_drop_used.push((local, self.location_to_index(location))); } + + fn insert_path_access(&mut self, path: MovePathIndex, location: Location) { + debug!("LivenessFactsExtractor::insert_path_access({:?}, {:?})", path, location); + self.path_accessed_at.push((path, self.location_to_index(location))); + } + + fn place_to_mpi(&self, place: &Place<'_>) -> Option { + match self.move_data.rev_lookup.find(place.as_ref()) { + LookupResult::Exact(mpi) => Some(mpi), + LookupResult::Parent(mmpi) => mmpi, + } + } } -impl Visitor<'tcx> for LivenessPointFactsExtractor<'_> { +impl Visitor<'tcx> for UseFactsExtractor<'_> { fn visit_local(&mut self, &local: &Local, context: PlaceContext, location: Location) { match categorize(context) { Some(DefUse::Def) => self.insert_def(local, location), @@ -47,6 +64,24 @@ impl Visitor<'tcx> for LivenessPointFactsExtractor<'_> { _ => (), } } + + fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) { + self.super_place(place, context, location); + match context { + PlaceContext::NonMutatingUse(_) => { + if let Some(mpi) = self.place_to_mpi(place) { + self.insert_path_access(mpi, location); + } + } + + PlaceContext::MutatingUse(MutatingUseContext::Borrow) => { + if let Some(mpi) = self.place_to_mpi(place) { + self.insert_path_access(mpi, location); + } + } + _ => (), + } + } } fn add_var_uses_regions(typeck: &mut TypeChecker<'_, 'tcx>, local: Local, ty: Ty<'tcx>) { @@ -60,24 +95,27 @@ fn add_var_uses_regions(typeck: &mut TypeChecker<'_, 'tcx>, local: Local, ty: Ty }); } -pub(super) fn populate_var_liveness_facts( +pub(super) fn populate_access_facts( typeck: &mut TypeChecker<'_, 'tcx>, - mir: &Body<'tcx>, + body: &Body<'tcx>, location_table: &LocationTable, + move_data: &MoveData<'_>, ) { debug!("populate_var_liveness_facts()"); if let Some(facts) = typeck.borrowck_context.all_facts.as_mut() { - LivenessPointFactsExtractor { + UseFactsExtractor { var_defined: &mut facts.var_defined, var_used: &mut facts.var_used, var_drop_used: &mut facts.var_drop_used, + path_accessed_at: &mut facts.path_accessed_at, location_table, + move_data, } - .visit_body(mir); + .visit_body(body); } - for (local, local_decl) in mir.local_decls.iter_enumerated() { + for (local, local_decl) in body.local_decls.iter_enumerated() { add_var_uses_regions(typeck, local, local_decl.ty); } } From 28312b5b0604444b5806cfb42ea11a1be14098ac Mon Sep 17 00:00:00 2001 From: Albin Stjerna Date: Mon, 19 Aug 2019 15:56:16 +0200 Subject: [PATCH 8/8] Rustfmt the files I touched --- src/librustc_mir/borrow_check/nll/mod.rs | 37 +++- .../nll/type_check/liveness/local_use_map.rs | 22 +- .../nll/type_check/liveness/trace.rs | 14 +- .../dataflow/move_paths/abs_domain.rs | 40 ++-- .../dataflow/move_paths/builder.rs | 200 +++++++++--------- src/librustc_mir/dataflow/move_paths/mod.rs | 42 ++-- 6 files changed, 187 insertions(+), 168 deletions(-) diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs index 4c76d14bdbbbb..1ff3228afa376 100644 --- a/src/librustc_mir/borrow_check/nll/mod.rs +++ b/src/librustc_mir/borrow_check/nll/mod.rs @@ -11,7 +11,8 @@ use crate::transform::MirSource; use crate::borrow_check::Upvar; use rustc::hir::def_id::DefId; use rustc::infer::InferCtxt; -use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, Local, Location, Body, LocalKind, BasicBlock, Promoted}; +use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, + Local, Location, Body, LocalKind, BasicBlock, Promoted}; use rustc::ty::{self, RegionKind, RegionVid}; use rustc_data_structures::indexed_vec::IndexVec; use rustc_errors::Diagnostic; @@ -72,11 +73,27 @@ pub(in crate::borrow_check) fn replace_regions_in_mir<'cx, 'tcx>( // This function populates an AllFacts instance with base facts related to // MovePaths and needed for the move analysis. -fn populate_polonius_move_facts(all_facts: &mut AllFacts, move_data: &MoveData<'_>, location_table: &LocationTable, body: &Body<'_>) { - all_facts.path_belongs_to_var.extend(move_data.rev_lookup.iter_locals_enumerated().map(|(v, &m)| (m, v))); +fn populate_polonius_move_facts( + all_facts: &mut AllFacts, + move_data: &MoveData<'_>, + location_table: &LocationTable, + body: &Body<'_>) { + all_facts + .path_belongs_to_var + .extend( + move_data + .rev_lookup + .iter_locals_enumerated() + .map(|(v, &m)| (m, v))); for (child, move_path) in move_data.move_paths.iter_enumerated() { - all_facts.child.extend(move_path.parents(&move_data.move_paths).iter().map(|&parent| (child, parent))); + all_facts + .child + .extend( + move_path + .parents(&move_data.move_paths) + .iter() + .map(|&parent| (child, parent))); } // initialized_at @@ -99,7 +116,9 @@ fn populate_polonius_move_facts(all_facts: &mut AllFacts, move_data: &MoveData<' // The initialization happened in (or rather, when arriving at) // the successors, but not in the unwind block. let first_statement = Location { block: successor, statement_index: 0}; - all_facts.initialized_at.push((init.path, location_table.start_index(first_statement))); + all_facts + .initialized_at + .push((init.path, location_table.start_index(first_statement))); } } else { @@ -121,7 +140,13 @@ fn populate_polonius_move_facts(all_facts: &mut AllFacts, move_data: &MoveData<' // moved_out_at // deinitialisation is assumed to always happen! - all_facts.moved_out_at.extend(move_data.moves.iter().map(|mo| (mo.path, location_table.mid_index(mo.source)))); + all_facts + .moved_out_at + .extend( + move_data + .moves + .iter() + .map(|mo| (mo.path, location_table.mid_index(mo.source)))); } /// Computes the (non-lexical) regions from the input MIR. diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs index 2a066538cc234..049d83bb22f1b 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/local_use_map.rs @@ -1,7 +1,7 @@ use crate::borrow_check::nll::region_infer::values::{PointIndex, RegionValueElements}; use crate::util::liveness::{categorize, DefUse}; use rustc::mir::visit::{PlaceContext, Visitor}; -use rustc::mir::{Local, Location, Body}; +use rustc::mir::{Body, Local, Location}; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use rustc_data_structures::vec_linked_list as vll; @@ -72,16 +72,10 @@ impl LocalUseMap { let mut locals_with_use_data: IndexVec = IndexVec::from_elem_n(false, body.local_decls.len()); - live_locals - .iter() - .for_each(|&local| locals_with_use_data[local] = true); - - LocalUseMapBuild { - local_use_map: &mut local_use_map, - elements, - locals_with_use_data, - } - .visit_body(body); + live_locals.iter().for_each(|&local| locals_with_use_data[local] = true); + + LocalUseMapBuild { local_use_map: &mut local_use_map, elements, locals_with_use_data } + .visit_body(body); local_use_map } @@ -151,10 +145,8 @@ impl LocalUseMapBuild<'_> { location: Location, ) { let point_index = elements.point_from_location(location); - let appearance_index = appearances.push(Appearance { - point_index, - next: *first_appearance, - }); + let appearance_index = + appearances.push(Appearance { point_index, next: *first_appearance }); *first_appearance = Some(appearance_index); } } diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs index eba52ae3384b0..9b55881cb1b10 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/trace.rs @@ -394,12 +394,7 @@ impl LivenessContext<'_, '_, '_, 'tcx> { ) { debug!("add_use_live_facts_for(value={:?})", value); - Self::make_all_regions_live( - self.elements, - &mut self.typeck, - value, - live_at, - ) + Self::make_all_regions_live(self.elements, &mut self.typeck, value, live_at) } /// Some variable with type `live_ty` is "drop live" at `location` @@ -450,12 +445,7 @@ impl LivenessContext<'_, '_, '_, 'tcx> { // All things in the `outlives` array may be touched by // the destructor and must be live at this point. for &kind in &drop_data.dropck_result.kinds { - Self::make_all_regions_live( - self.elements, - &mut self.typeck, - kind, - live_at, - ); + Self::make_all_regions_live(self.elements, &mut self.typeck, kind, live_at); polonius::add_var_drops_regions(&mut self.typeck, dropped_local, &kind); } diff --git a/src/librustc_mir/dataflow/move_paths/abs_domain.rs b/src/librustc_mir/dataflow/move_paths/abs_domain.rs index b26547c4ff77e..d97f3b7417286 100644 --- a/src/librustc_mir/dataflow/move_paths/abs_domain.rs +++ b/src/librustc_mir/dataflow/move_paths/abs_domain.rs @@ -11,7 +11,7 @@ //! `a[x]` would still overlap them both. But that is not this //! representation does today.) -use rustc::mir::{Local, PlaceElem, Operand, ProjectionElem}; +use rustc::mir::{Local, Operand, PlaceElem, ProjectionElem}; use rustc::ty::Ty; #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] @@ -26,36 +26,36 @@ pub trait Lift { } impl<'tcx> Lift for Operand<'tcx> { type Abstract = AbstractOperand; - fn lift(&self) -> Self::Abstract { AbstractOperand } + fn lift(&self) -> Self::Abstract { + AbstractOperand + } } impl Lift for Local { type Abstract = AbstractOperand; - fn lift(&self) -> Self::Abstract { AbstractOperand } + fn lift(&self) -> Self::Abstract { + AbstractOperand + } } impl<'tcx> Lift for Ty<'tcx> { type Abstract = AbstractType; - fn lift(&self) -> Self::Abstract { AbstractType } + fn lift(&self) -> Self::Abstract { + AbstractType + } } impl<'tcx> Lift for PlaceElem<'tcx> { type Abstract = AbstractElem; fn lift(&self) -> Self::Abstract { match *self { - ProjectionElem::Deref => - ProjectionElem::Deref, - ProjectionElem::Field(ref f, ty) => - ProjectionElem::Field(f.clone(), ty.lift()), - ProjectionElem::Index(ref i) => - ProjectionElem::Index(i.lift()), - ProjectionElem::Subslice {from, to} => - ProjectionElem::Subslice { from: from, to: to }, - ProjectionElem::ConstantIndex {offset,min_length,from_end} => - ProjectionElem::ConstantIndex { - offset, - min_length, - from_end, - }, - ProjectionElem::Downcast(a, u) => - ProjectionElem::Downcast(a, u.clone()), + ProjectionElem::Deref => ProjectionElem::Deref, + ProjectionElem::Field(ref f, ty) => ProjectionElem::Field(f.clone(), ty.lift()), + ProjectionElem::Index(ref i) => ProjectionElem::Index(i.lift()), + ProjectionElem::Subslice { from, to } => { + ProjectionElem::Subslice { from: from, to: to } + } + ProjectionElem::ConstantIndex { offset, min_length, from_end } => { + ProjectionElem::ConstantIndex { offset, min_length, from_end } + } + ProjectionElem::Downcast(a, u) => ProjectionElem::Downcast(a, u.clone()), } } } diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs index 366b96b53b423..81451c2500c47 100644 --- a/src/librustc_mir/dataflow/move_paths/builder.rs +++ b/src/librustc_mir/dataflow/move_paths/builder.rs @@ -1,16 +1,18 @@ -use rustc::ty::{self, TyCtxt}; -use rustc::mir::*; use rustc::mir::tcx::RvalueInitializationState; -use rustc_data_structures::indexed_vec::{IndexVec}; -use smallvec::{SmallVec, smallvec}; +use rustc::mir::*; +use rustc::ty::{self, TyCtxt}; +use rustc_data_structures::indexed_vec::IndexVec; +use smallvec::{smallvec, SmallVec}; use std::collections::hash_map::Entry; use std::mem; use super::abs_domain::Lift; -use super::{LocationMap, MoveData, MovePath, MovePathLookup, MovePathIndex, MoveOut, MoveOutIndex}; -use super::{MoveError, InitIndex, Init, InitLocation, LookupResult, InitKind}; use super::IllegalMoveOriginKind::*; +use super::{Init, InitIndex, InitKind, InitLocation, LookupResult, MoveError}; +use super::{ + LocationMap, MoveData, MoveOut, MoveOutIndex, MovePath, MovePathIndex, MovePathLookup, +}; struct MoveDataBuilder<'a, 'tcx> { body: &'a Body<'tcx>, @@ -33,15 +35,19 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> { moves: IndexVec::new(), loc_map: LocationMap::new(body), rev_lookup: MovePathLookup { - locals: body.local_decls.indices().map(|i| { - Self::new_move_path( - &mut move_paths, - &mut path_map, - &mut init_path_map, - None, - Place::from(i), - ) - }).collect(), + locals: body + .local_decls + .indices() + .map(|i| { + Self::new_move_path( + &mut move_paths, + &mut path_map, + &mut init_path_map, + None, + Place::from(i), + ) + }) + .collect(), projections: Default::default(), }, move_paths, @@ -49,27 +55,22 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> { inits: IndexVec::new(), init_loc_map: LocationMap::new(body), init_path_map, - } + }, } } - fn new_move_path(move_paths: &mut IndexVec>, - path_map: &mut IndexVec>, - init_path_map: &mut IndexVec>, - parent: Option, - place: Place<'tcx>) - -> MovePathIndex - { - let move_path = move_paths.push(MovePath { - next_sibling: None, - first_child: None, - parent, - place, - }); + fn new_move_path( + move_paths: &mut IndexVec>, + path_map: &mut IndexVec>, + init_path_map: &mut IndexVec>, + parent: Option, + place: Place<'tcx>, + ) -> MovePathIndex { + let move_path = + move_paths.push(MovePath { next_sibling: None, first_child: None, parent, place }); if let Some(parent) = parent { - let next_sibling = - mem::replace(&mut move_paths[parent].first_child, Some(move_path)); + let next_sibling = mem::replace(&mut move_paths[parent].first_child, Some(move_path)); move_paths[move_path].next_sibling = next_sibling; } @@ -91,9 +92,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { /// problematic for borrowck. /// /// Maybe we should have separate "borrowck" and "moveck" modes. - fn move_path_for(&mut self, place: &Place<'tcx>) - -> Result> - { + fn move_path_for(&mut self, place: &Place<'tcx>) -> Result> { debug!("lookup({:?})", place); place.iterate(|place_base, place_projection| { let mut base = match place_base { @@ -108,39 +107,46 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { let tcx = self.builder.tcx; let place_ty = Place::ty_from(place_base, &proj.base, body, tcx).ty; match place_ty.sty { - ty::Ref(..) | ty::RawPtr(..) => + ty::Ref(..) | ty::RawPtr(..) => { return Err(MoveError::cannot_move_out_of( self.loc, BorrowedContent { target_place: Place { base: place_base.clone(), projection: Some(Box::new(proj.clone())), - } - })), - ty::Adt(adt, _) if adt.has_dtor(tcx) && !adt.is_box() => - return Err(MoveError::cannot_move_out_of(self.loc, - InteriorOfTypeWithDestructor { - container_ty: place_ty - })), + }, + }, + )); + } + ty::Adt(adt, _) if adt.has_dtor(tcx) && !adt.is_box() => { + return Err(MoveError::cannot_move_out_of( + self.loc, + InteriorOfTypeWithDestructor { container_ty: place_ty }, + )); + } // move out of union - always move the entire union - ty::Adt(adt, _) if adt.is_union() => - return Err(MoveError::UnionMove { path: base }), - ty::Slice(_) => + ty::Adt(adt, _) if adt.is_union() => { + return Err(MoveError::UnionMove { path: base }); + } + ty::Slice(_) => { return Err(MoveError::cannot_move_out_of( self.loc, InteriorOfSliceOrArray { - ty: place_ty, is_index: match proj.elem { + ty: place_ty, + is_index: match proj.elem { ProjectionElem::Index(..) => true, - _ => false + _ => false, }, - })), + }, + )); + } ty::Array(..) => match proj.elem { - ProjectionElem::Index(..) => + ProjectionElem::Index(..) => { return Err(MoveError::cannot_move_out_of( self.loc, - InteriorOfSliceOrArray { - ty: place_ty, is_index: true - })), + InteriorOfSliceOrArray { ty: place_ty, is_index: true }, + )); + } _ => { // FIXME: still badly broken } @@ -186,7 +192,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> { fn finalize( - self + self, ) -> Result, (MoveData<'tcx>, Vec<(Place<'tcx>, MoveError<'tcx>)>)> { debug!("{}", { debug!("moves for {:?}:", self.body.span); @@ -200,11 +206,7 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> { "done dumping moves" }); - if !self.errors.is_empty() { - Err((self.data, self.errors)) - } else { - Ok(self.data) - } + if !self.errors.is_empty() { Err((self.data, self.errors)) } else { Ok(self.data) } } } @@ -222,10 +224,7 @@ pub(super) fn gather_moves<'tcx>( builder.gather_statement(source, stmt); } - let terminator_loc = Location { - block: bb, - statement_index: block.statements.len() - }; + let terminator_loc = Location { block: bb, statement_index: block.statements.len() }; builder.gather_terminator(terminator_loc, block.terminator()); } @@ -238,11 +237,12 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> { let path = self.data.rev_lookup.locals[arg]; let init = self.data.inits.push(Init { - path, kind: InitKind::Deep, location: InitLocation::Argument(arg), + path, + kind: InitKind::Deep, + location: InitLocation::Argument(arg), }); - debug!("gather_args: adding init {:?} of {:?} for argument {:?}", - init, path, arg); + debug!("gather_args: adding init {:?} of {:?} for argument {:?}", init, path, arg); self.data.init_path_map[path].push(init); } @@ -297,26 +297,26 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { StatementKind::StorageDead(local) => { self.gather_move(&Place::from(local)); } - StatementKind::SetDiscriminant{ .. } => { - span_bug!(stmt.source_info.span, - "SetDiscriminant should not exist during borrowck"); + StatementKind::SetDiscriminant { .. } => { + span_bug!( + stmt.source_info.span, + "SetDiscriminant should not exist during borrowck" + ); } - StatementKind::Retag { .. } | - StatementKind::AscribeUserType(..) | - StatementKind::Nop => {} + StatementKind::Retag { .. } + | StatementKind::AscribeUserType(..) + | StatementKind::Nop => {} } } fn gather_rvalue(&mut self, rvalue: &Rvalue<'tcx>) { match *rvalue { - Rvalue::Use(ref operand) | - Rvalue::Repeat(ref operand, _) | - Rvalue::Cast(_, ref operand, _) | - Rvalue::UnaryOp(_, ref operand) => { - self.gather_operand(operand) - } - Rvalue::BinaryOp(ref _binop, ref lhs, ref rhs) | - Rvalue::CheckedBinaryOp(ref _binop, ref lhs, ref rhs) => { + Rvalue::Use(ref operand) + | Rvalue::Repeat(ref operand, _) + | Rvalue::Cast(_, ref operand, _) + | Rvalue::UnaryOp(_, ref operand) => self.gather_operand(operand), + Rvalue::BinaryOp(ref _binop, ref lhs, ref rhs) + | Rvalue::CheckedBinaryOp(ref _binop, ref lhs, ref rhs) => { self.gather_operand(lhs); self.gather_operand(rhs); } @@ -325,11 +325,11 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { self.gather_operand(operand); } } - Rvalue::Ref(..) | - Rvalue::Discriminant(..) | - Rvalue::Len(..) | - Rvalue::NullaryOp(NullOp::SizeOf, _) | - Rvalue::NullaryOp(NullOp::Box, _) => { + Rvalue::Ref(..) + | Rvalue::Discriminant(..) + | Rvalue::Len(..) + | Rvalue::NullaryOp(NullOp::SizeOf, _) + | Rvalue::NullaryOp(NullOp::Box, _) => { // This returns an rvalue with uninitialized contents. We can't // move out of it here because it is an rvalue - assignments always // completely initialize their place. @@ -346,13 +346,13 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { fn gather_terminator(&mut self, term: &Terminator<'tcx>) { match term.kind { - TerminatorKind::Goto { target: _ } | - TerminatorKind::Resume | - TerminatorKind::Abort | - TerminatorKind::GeneratorDrop | - TerminatorKind::FalseEdges { .. } | - TerminatorKind::FalseUnwind { .. } | - TerminatorKind::Unreachable => { } + TerminatorKind::Goto { target: _ } + | TerminatorKind::Resume + | TerminatorKind::Abort + | TerminatorKind::GeneratorDrop + | TerminatorKind::FalseEdges { .. } + | TerminatorKind::FalseUnwind { .. } + | TerminatorKind::Unreachable => {} TerminatorKind::Return => { self.gather_move(&Place::RETURN_PLACE); @@ -399,9 +399,9 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { fn gather_operand(&mut self, operand: &Operand<'tcx>) { match *operand { - Operand::Constant(..) | - Operand::Copy(..) => {} // not-a-move - Operand::Move(ref place) => { // a move + Operand::Constant(..) | Operand::Copy(..) => {} // not-a-move + Operand::Move(ref place) => { + // a move self.gather_move(place); } } @@ -419,8 +419,10 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { }; let move_out = self.builder.data.moves.push(MoveOut { path: path, source: self.loc }); - debug!("gather_move({:?}, {:?}): adding move {:?} of {:?}", - self.loc, place, move_out, path); + debug!( + "gather_move({:?}, {:?}): adding move {:?} of {:?}", + self.loc, place, move_out, path + ); self.builder.data.path_map[path].push(move_out); self.builder.data.loc_map[self.loc].push(move_out); @@ -452,8 +454,10 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { kind, }); - debug!("gather_init({:?}, {:?}): adding init {:?} of {:?}", - self.loc, place, init, path); + debug!( + "gather_init({:?}, {:?}): adding init {:?} of {:?}", + self.loc, place, init, path + ); self.builder.data.init_path_map[path].push(init); self.builder.data.init_loc_map[self.loc].push(init); diff --git a/src/librustc_mir/dataflow/move_paths/mod.rs b/src/librustc_mir/dataflow/move_paths/mod.rs index 07b9b662a07aa..5028e9650918c 100644 --- a/src/librustc_mir/dataflow/move_paths/mod.rs +++ b/src/librustc_mir/dataflow/move_paths/mod.rs @@ -1,10 +1,10 @@ -use rustc::ty::{Ty, TyCtxt}; +use core::slice::Iter; use rustc::mir::*; +use rustc::ty::{Ty, TyCtxt}; use rustc::util::nodemap::FxHashMap; -use rustc_data_structures::indexed_vec::{Idx, IndexVec, Enumerated}; +use rustc_data_structures::indexed_vec::{Enumerated, Idx, IndexVec}; use smallvec::SmallVec; -use syntax_pos::{Span}; -use core::slice::Iter; +use syntax_pos::Span; use std::fmt; use std::ops::{Index, IndexMut}; @@ -138,12 +138,17 @@ impl IndexMut for LocationMap { } } -impl LocationMap where T: Default + Clone { +impl LocationMap +where + T: Default + Clone, +{ fn new(body: &Body<'_>) -> Self { LocationMap { - map: body.basic_blocks().iter().map(|block| { - vec![T::default(); block.statements.len()+1] - }).collect() + map: body + .basic_blocks() + .iter() + .map(|block| vec![T::default(); block.statements.len() + 1]) + .collect(), } } } @@ -179,7 +184,6 @@ pub struct Init { pub kind: InitKind, } - /// Initializations can be from an argument or from a statement. Arguments /// do not have locations, in those cases the `Local` is kept.. #[derive(Copy, Clone, Debug, PartialEq, Eq)] @@ -225,7 +229,7 @@ pub struct MovePathLookup { /// subsequent search so that it is solely relative to that /// base-place). For the remaining lookup, we map the projection /// elem to the associated MovePathIndex. - projections: FxHashMap<(MovePathIndex, AbstractElem), MovePathIndex> + projections: FxHashMap<(MovePathIndex, AbstractElem), MovePathIndex>, } mod builder; @@ -233,7 +237,7 @@ mod builder; #[derive(Copy, Clone, Debug)] pub enum LookupResult { Exact(MovePathIndex), - Parent(Option) + Parent(Option), } impl MovePathLookup { @@ -296,7 +300,7 @@ pub(crate) enum IllegalMoveOriginKind<'tcx> { InteriorOfTypeWithDestructor { container_ty: Ty<'tcx> }, /// Illegal move due to attempt to move out of a slice or array. - InteriorOfSliceOrArray { ty: Ty<'tcx>, is_index: bool, }, + InteriorOfSliceOrArray { ty: Ty<'tcx>, is_index: bool }, } #[derive(Debug)] @@ -325,11 +329,15 @@ impl<'tcx> MoveData<'tcx> { pub fn base_local(&self, mut mpi: MovePathIndex) -> Option { loop { let path = &self.move_paths[mpi]; - if let Place { - base: PlaceBase::Local(l), - projection: None, - } = path.place { return Some(l); } - if let Some(parent) = path.parent { mpi = parent; continue } else { return None } + if let Place { base: PlaceBase::Local(l), projection: None } = path.place { + return Some(l); + } + if let Some(parent) = path.parent { + mpi = parent; + continue; + } else { + return None; + } } } }