From 373fc932aa7adecb9c2e78455835cb6341b73552 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 30 Aug 2018 18:54:32 -0300 Subject: [PATCH 1/2] Make move out computation lazy --- src/librustc/mir/mod.rs | 22 +++ .../borrow_check/error_reporting.rs | 90 ++++++++++-- src/librustc_mir/borrow_check/flows.rs | 18 +-- src/librustc_mir/borrow_check/mod.rs | 16 +-- src/librustc_mir/dataflow/impls/mod.rs | 129 +----------------- src/librustc_mir/dataflow/mod.rs | 16 +-- src/test/ui/hygiene/fields-move.nll.stderr | 8 -- 7 files changed, 110 insertions(+), 189 deletions(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 0840f333c876b..c9374b6bfc7ce 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -203,6 +203,28 @@ impl<'tcx> Mir<'tcx> { ReadGuard::map(self.predecessors(), |p| &p[bb]) } + #[inline] + pub fn predecessor_locations(&self, loc: Location) -> impl Iterator + '_ { + let if_zero_locations = if loc.statement_index == 0 { + let predecessor_blocks = self.predecessors_for(loc.block); + let num_predecessor_blocks = predecessor_blocks.len(); + Some((0 .. num_predecessor_blocks) + .map(move |i| predecessor_blocks[i]) + .map(move |bb| self.terminator_loc(bb)) + ) + } else { + None + }; + + let if_not_zero_locations = if loc.statement_index == 0 { + None + } else { + Some(Location { block: loc.block, statement_index: loc.statement_index - 1 }) + }; + + if_zero_locations.into_iter().flatten().chain(if_not_zero_locations) + } + #[inline] pub fn dominators(&self) -> Dominators { dominators(self) diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index f1df135f7ee83..efd804983067a 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -15,6 +15,7 @@ use rustc::mir::{BindingForm, BorrowKind, ClearCrossCrate, Field, Local}; use rustc::mir::{LocalDecl, LocalKind, Location, Operand, Place}; use rustc::mir::{ProjectionElem, Rvalue, Statement, StatementKind}; use rustc::ty; +use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::indexed_vec::Idx; use rustc_data_structures::sync::Lrc; use rustc_errors::DiagnosticBuilder; @@ -24,8 +25,9 @@ use super::borrow_set::BorrowData; use super::{Context, MirBorrowckCtxt}; use super::{InitializationRequiringAction, PrefixSet}; +use dataflow::drop_flag_effects; use dataflow::move_paths::MovePathIndex; -use dataflow::{FlowAtLocation, MovingOutStatements}; +use dataflow::move_paths::indexes::MoveOutIndex; use util::borrowck_errors::{BorrowckErrors, Origin}; impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { @@ -35,17 +37,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { desired_action: InitializationRequiringAction, (place, span): (&Place<'tcx>, Span), mpi: MovePathIndex, - curr_move_out: &FlowAtLocation>, ) { let use_spans = self .move_spans(place, context.loc) .or_else(|| self.borrow_spans(span, context.loc)); let span = use_spans.args_or_use(); - let mois = self.move_data.path_map[mpi] - .iter() - .filter(|moi| curr_move_out.contains(moi)) - .collect::>(); + let mois = self.get_moved_indexes(context, mpi); + debug!("report_use_of_moved_or_uninitialized: mois={:?}", mois); if mois.is_empty() { let root_place = self.prefixes(&place, PrefixSet::All).last().unwrap(); @@ -93,7 +92,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { let mut is_loop_move = false; for moi in &mois { - let move_out = self.move_data.moves[**moi]; + let move_out = self.move_data.moves[*moi]; let moved_place = &self.move_data.move_paths[move_out.path].place; let move_spans = self.move_spans(moved_place, move_out.source); @@ -148,7 +147,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { }; if needs_note { - let mpi = self.move_data.moves[*mois[0]].path; + let mpi = self.move_data.moves[mois[0]].path; let place = &self.move_data.move_paths[mpi].place; if let Some(ty) = self.retrieve_type_for_place(place) { @@ -521,6 +520,81 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { err } + fn get_moved_indexes( + &mut self, + context: Context, + mpi: MovePathIndex, + ) -> Vec { + let mir = self.mir; + + let mut stack = Vec::new(); + stack.extend(mir.predecessor_locations(context.loc)); + + let mut visited = FxHashSet(); + let mut result = vec![]; + + 'dfs: + while let Some(l) = stack.pop() { + debug!("report_use_of_moved_or_uninitialized: current_location={:?}", l); + + if !visited.insert(l) { + continue; + } + + // check for moves + let stmt_kind = mir[l.block].statements.get(l.statement_index).map(|s| &s.kind); + if let Some(StatementKind::StorageDead(..)) = stmt_kind { + // this analysis only tries to find moves explicitly + // written by the user, so we ignore the move-outs + // created by `StorageDead` and at the beginning + // of a function. + } else { + for moi in &self.move_data.loc_map[l] { + debug!("report_use_of_moved_or_uninitialized: moi={:?}", moi); + if self.move_data.moves[*moi].path == mpi { + debug!("report_use_of_moved_or_uninitialized: found"); + result.push(*moi); + + // Strictly speaking, we could continue our DFS here. There may be + // other moves that can reach the point of error. But it is kind of + // confusing to highlight them. + // + // Example: + // + // ``` + // let a = vec![]; + // let b = a; + // let c = a; + // drop(a); // <-- current point of error + // ``` + // + // Because we stop the DFS here, we only highlight `let c = a`, + // and not `let b = a`. We will of course also report an error at + // `let c = a` which highlights `let b = a` as the move. + continue 'dfs; + } + } + } + + // check for inits + let mut any_match = false; + drop_flag_effects::for_location_inits( + self.tcx, + self.mir, + self.move_data, + l, + |m| if m == mpi { any_match = true; }, + ); + if any_match { + continue 'dfs; + } + + stack.extend(mir.predecessor_locations(l)); + } + + result + } + pub(super) fn report_illegal_mutation_of_borrowed( &mut self, context: Context, diff --git a/src/librustc_mir/borrow_check/flows.rs b/src/librustc_mir/borrow_check/flows.rs index 192fa2b9eeaf7..6b964fec74fdd 100644 --- a/src/librustc_mir/borrow_check/flows.rs +++ b/src/librustc_mir/borrow_check/flows.rs @@ -24,7 +24,7 @@ use polonius_engine::Output; use dataflow::move_paths::indexes::BorrowIndex; use dataflow::move_paths::HasMoveData; use dataflow::Borrows; -use dataflow::{EverInitializedPlaces, MovingOutStatements}; +use dataflow::EverInitializedPlaces; use dataflow::{FlowAtLocation, FlowsAtLocation}; use dataflow::MaybeUninitializedPlaces; use either::Either; @@ -35,7 +35,6 @@ use std::rc::Rc; crate struct Flows<'b, 'gcx: 'tcx, 'tcx: 'b> { borrows: FlowAtLocation>, pub uninits: FlowAtLocation>, - pub move_outs: FlowAtLocation>, pub ever_inits: FlowAtLocation>, /// Polonius Output @@ -46,14 +45,12 @@ impl<'b, 'gcx, 'tcx> Flows<'b, 'gcx, 'tcx> { crate fn new( borrows: FlowAtLocation>, uninits: FlowAtLocation>, - move_outs: FlowAtLocation>, ever_inits: FlowAtLocation>, polonius_output: Option>>, ) -> Self { Flows { borrows, uninits, - move_outs, ever_inits, polonius_output, } @@ -79,7 +76,6 @@ macro_rules! each_flow { ($this:ident, $meth:ident($arg:ident)) => { FlowAtLocation::$meth(&mut $this.borrows, $arg); FlowAtLocation::$meth(&mut $this.uninits, $arg); - FlowAtLocation::$meth(&mut $this.move_outs, $arg); FlowAtLocation::$meth(&mut $this.ever_inits, $arg); }; } @@ -146,18 +142,6 @@ impl<'b, 'gcx, 'tcx> fmt::Display for Flows<'b, 'gcx, 'tcx> { }); s.push_str("] "); - s.push_str("move_out: ["); - let mut saw_one = false; - self.move_outs.each_state_bit(|mpi_move_out| { - if saw_one { - s.push_str(", "); - }; - saw_one = true; - let move_out = &self.move_outs.operator().move_data().moves[mpi_move_out]; - s.push_str(&format!("{:?}", move_out)); - }); - s.push_str("] "); - s.push_str("ever_init: ["); let mut saw_one = false; self.ever_inits.each_state_bit(|mpi_ever_init| { diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 16d34082642bd..3536947b25ebf 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -43,7 +43,7 @@ use dataflow::DataflowResultsConsumer; use dataflow::FlowAtLocation; use dataflow::MoveDataParamEnv; use dataflow::{do_dataflow, DebugFormatted}; -use dataflow::{EverInitializedPlaces, MovingOutStatements}; +use dataflow::EverInitializedPlaces; use dataflow::{MaybeInitializedPlaces, MaybeUninitializedPlaces}; use util::borrowck_errors::{BorrowckErrors, Origin}; @@ -186,15 +186,6 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( MaybeUninitializedPlaces::new(tcx, mir, &mdpe), |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]), )); - let flow_move_outs = FlowAtLocation::new(do_dataflow( - tcx, - mir, - id, - &attributes, - &dead_unwinds, - MovingOutStatements::new(tcx, mir, &mdpe), - |bd, i| DebugFormatted::new(&bd.move_data().moves[i]), - )); let flow_ever_inits = FlowAtLocation::new(do_dataflow( tcx, mir, @@ -268,7 +259,6 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( let mut state = Flows::new( flow_borrows, flow_uninits, - flow_move_outs, flow_ever_inits, polonius_output, ); @@ -1617,7 +1607,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { let place = self.base_path(place_span.0); let maybe_uninits = &flow_state.uninits; - let curr_move_outs = &flow_state.move_outs; // Bad scenarios: // @@ -1663,7 +1652,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { desired_action, place_span, mpi, - curr_move_outs, ); return; // don't bother finding other problems. } @@ -1691,7 +1679,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { let place = self.base_path(place_span.0); let maybe_uninits = &flow_state.uninits; - let curr_move_outs = &flow_state.move_outs; // Bad scenarios: // @@ -1727,7 +1714,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { desired_action, place_span, child_mpi, - curr_move_outs, ); return; // don't bother finding other problems. } diff --git a/src/librustc_mir/dataflow/impls/mod.rs b/src/librustc_mir/dataflow/impls/mod.rs index ee3bba840c67b..62c6018809f39 100644 --- a/src/librustc_mir/dataflow/impls/mod.rs +++ b/src/librustc_mir/dataflow/impls/mod.rs @@ -22,13 +22,13 @@ use super::MoveDataParamEnv; use util::elaborate_drops::DropFlagState; -use super::move_paths::{HasMoveData, MoveData, MoveOutIndex, MovePathIndex, InitIndex}; +use super::move_paths::{HasMoveData, MoveData, MovePathIndex, InitIndex}; use super::move_paths::{LookupResult, InitKind}; use super::{BitDenotation, BlockSets, InitialFlow}; use super::drop_flag_effects_for_function_entry; use super::drop_flag_effects_for_location; -use super::{on_lookup_result_bits, for_location_inits}; +use super::on_lookup_result_bits; mod storage_liveness; @@ -211,40 +211,6 @@ impl<'a, 'gcx, 'tcx: 'a> HasMoveData<'tcx> for DefinitelyInitializedPlaces<'a, ' fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data } } -/// `MovingOutStatements` tracks the statements that perform moves out -/// of particular places. More precisely, it tracks whether the -/// *effect* of such moves (namely, the uninitialization of the -/// place in question) can reach some point in the control-flow of -/// the function, or if that effect is "killed" by some intervening -/// operation reinitializing that place. -/// -/// The resulting dataflow is a more enriched version of -/// `MaybeUninitializedPlaces`. Both structures on their own only tell -/// you if a place *might* be uninitialized at a given point in the -/// control flow. But `MovingOutStatements` also includes the added -/// data of *which* particular statement causing the deinitialization -/// that the borrow checker's error message may need to report. -#[allow(dead_code)] -pub struct MovingOutStatements<'a, 'gcx: 'tcx, 'tcx: 'a> { - tcx: TyCtxt<'a, 'gcx, 'tcx>, - mir: &'a Mir<'tcx>, - mdpe: &'a MoveDataParamEnv<'gcx, 'tcx>, -} - -impl<'a, 'gcx: 'tcx, 'tcx: 'a> MovingOutStatements<'a, 'gcx, 'tcx> { - pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, - mir: &'a Mir<'tcx>, - mdpe: &'a MoveDataParamEnv<'gcx, 'tcx>) - -> Self - { - MovingOutStatements { tcx: tcx, mir: mir, mdpe: mdpe } - } -} - -impl<'a, 'gcx, 'tcx> HasMoveData<'tcx> for MovingOutStatements<'a, 'gcx, 'tcx> { - fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data } -} - /// `EverInitializedPlaces` tracks all places that might have ever been /// initialized upon reaching a particular point in the control flow /// for a function, without an intervening `Storage Dead`. @@ -488,83 +454,6 @@ impl<'a, 'gcx, 'tcx> BitDenotation for DefinitelyInitializedPlaces<'a, 'gcx, 'tc } } -impl<'a, 'gcx, 'tcx> BitDenotation for MovingOutStatements<'a, 'gcx, 'tcx> { - type Idx = MoveOutIndex; - fn name() -> &'static str { "moving_out" } - fn bits_per_block(&self) -> usize { - self.move_data().moves.len() - } - - fn start_block_effect(&self, _sets: &mut IdxSet) { - // no move-statements have been executed prior to function - // execution, so this method has no effect on `_sets`. - } - - fn statement_effect(&self, - sets: &mut BlockSets, - location: Location) { - let (tcx, mir, move_data) = (self.tcx, self.mir, self.move_data()); - let stmt = &mir[location.block].statements[location.statement_index]; - let loc_map = &move_data.loc_map; - let path_map = &move_data.path_map; - - match stmt.kind { - // this analysis only tries to find moves explicitly - // written by the user, so we ignore the move-outs - // created by `StorageDead` and at the beginning - // of a function. - mir::StatementKind::StorageDead(_) => {} - _ => { - debug!("stmt {:?} at loc {:?} moves out of move_indexes {:?}", - stmt, location, &loc_map[location]); - // Every path deinitialized by a *particular move* - // has corresponding bit, "gen'ed" (i.e. set) - // here, in dataflow vector - sets.gen_all_and_assert_dead(&loc_map[location]); - } - } - - for_location_inits(tcx, mir, move_data, location, - |mpi| sets.kill_all(&path_map[mpi])); - } - - fn terminator_effect(&self, - sets: &mut BlockSets, - location: Location) - { - let (tcx, mir, move_data) = (self.tcx, self.mir, self.move_data()); - let term = mir[location.block].terminator(); - let loc_map = &move_data.loc_map; - let path_map = &move_data.path_map; - - debug!("terminator {:?} at loc {:?} moves out of move_indexes {:?}", - term, location, &loc_map[location]); - sets.gen_all_and_assert_dead(&loc_map[location]); - - for_location_inits(tcx, mir, move_data, location, - |mpi| sets.kill_all(&path_map[mpi])); - } - - fn propagate_call_return(&self, - in_out: &mut IdxSet, - _call_bb: mir::BasicBlock, - _dest_bb: mir::BasicBlock, - dest_place: &mir::Place) { - let move_data = self.move_data(); - let bits_per_block = self.bits_per_block(); - - let path_map = &move_data.path_map; - on_lookup_result_bits(self.tcx, - self.mir, - move_data, - move_data.rev_lookup.find(dest_place), - |mpi| for moi in &path_map[mpi] { - assert!(moi.index() < bits_per_block); - in_out.remove(&moi); - }); - } -} - impl<'a, 'gcx, 'tcx> BitDenotation for EverInitializedPlaces<'a, 'gcx, 'tcx> { type Idx = InitIndex; fn name() -> &'static str { "ever_init" } @@ -682,13 +571,6 @@ impl<'a, 'gcx, 'tcx> BitwiseOperator for DefinitelyInitializedPlaces<'a, 'gcx, ' } } -impl<'a, 'gcx, 'tcx> BitwiseOperator for MovingOutStatements<'a, 'gcx, 'tcx> { - #[inline] - fn join(&self, pred1: Word, pred2: Word) -> Word { - pred1 | pred2 // moves from both preds are in scope - } -} - impl<'a, 'gcx, 'tcx> BitwiseOperator for EverInitializedPlaces<'a, 'gcx, 'tcx> { #[inline] fn join(&self, pred1: Word, pred2: Word) -> Word { @@ -727,13 +609,6 @@ impl<'a, 'gcx, 'tcx> InitialFlow for DefinitelyInitializedPlaces<'a, 'gcx, 'tcx> } } -impl<'a, 'gcx, 'tcx> InitialFlow for MovingOutStatements<'a, 'gcx, 'tcx> { - #[inline] - fn bottom_value() -> bool { - false // bottom = no loans in scope by default - } -} - impl<'a, 'gcx, 'tcx> InitialFlow for EverInitializedPlaces<'a, 'gcx, 'tcx> { #[inline] fn bottom_value() -> bool { diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs index fd6569feb5c20..bee7d443c8540 100644 --- a/src/librustc_mir/dataflow/mod.rs +++ b/src/librustc_mir/dataflow/mod.rs @@ -28,7 +28,7 @@ use std::usize; pub use self::impls::{MaybeStorageLive}; pub use self::impls::{MaybeInitializedPlaces, MaybeUninitializedPlaces}; -pub use self::impls::{DefinitelyInitializedPlaces, MovingOutStatements}; +pub use self::impls::DefinitelyInitializedPlaces; pub use self::impls::EverInitializedPlaces; pub use self::impls::borrows::Borrows; pub use self::impls::HaveBeenBorrowedLocals; @@ -38,7 +38,7 @@ pub(crate) use self::drop_flag_effects::*; use self::move_paths::MoveData; mod at_location; -mod drop_flag_effects; +pub mod drop_flag_effects; mod graphviz; mod impls; pub mod move_paths; @@ -511,18 +511,6 @@ impl<'a, E:Idx> BlockSets<'a, E> { } } - fn gen_all_and_assert_dead(&mut self, i: I) - where I: IntoIterator, - I::Item: Borrow - { - for j in i { - let j = j.borrow(); - let retval = self.gen_set.add(j); - self.kill_set.remove(j); - assert!(retval); - } - } - fn kill(&mut self, e: &E) { self.gen_set.remove(e); self.kill_set.add(e); diff --git a/src/test/ui/hygiene/fields-move.nll.stderr b/src/test/ui/hygiene/fields-move.nll.stderr index 56b77714991ca..9b25a865f921e 100644 --- a/src/test/ui/hygiene/fields-move.nll.stderr +++ b/src/test/ui/hygiene/fields-move.nll.stderr @@ -1,9 +1,6 @@ error[E0382]: use of moved value: `foo.x` --> $DIR/fields-move.rs:28:9 | -LL | $foo.x - | ------ value moved here -... LL | $foo.x //~ ERROR use of moved value: `foo.x` | ^^^^^^ value used here after move ... @@ -28,14 +25,9 @@ LL | assert_two_copies(copy_modern!(foo), foo.x); //~ ERROR use of moved val error[E0382]: use of moved value: `foo.x` --> $DIR/fields-move.rs:39:42 | -LL | $foo.x - | ------ value moved here -... LL | $foo.x //~ ERROR use of moved value: `foo.x` | ------ value moved here ... -LL | assert_two_copies(copy_modern!(foo), foo.x); //~ ERROR use of moved value: `foo.x` - | ----- value moved here LL | assert_two_copies(copy_legacy!(foo), foo.x); //~ ERROR use of moved value: `foo.x` | ^^^^^ value used here after move | From a6aa5ddf56a42f547224f616c4f37d490d5e9b88 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 30 Aug 2018 15:06:27 -0300 Subject: [PATCH 2/2] Run rustfmt --- src/librustc/mir/mod.rs | 79 +++++++++++-------- .../borrow_check/error_reporting.rs | 72 +++++++++-------- 2 files changed, 84 insertions(+), 67 deletions(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index c9374b6bfc7ce..3ef8cdfd1044d 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -17,17 +17,17 @@ use hir::def::CtorKind; use hir::def_id::DefId; use hir::{self, HirId, InlineAsm}; use middle::region; -use mir::interpret::{EvalErrorKind, Scalar, ScalarMaybeUndef, ConstValue}; +use mir::interpret::{ConstValue, EvalErrorKind, Scalar, ScalarMaybeUndef}; use mir::visit::MirVisitable; use rustc_apfloat::ieee::{Double, Single}; use rustc_apfloat::Float; use rustc_data_structures::graph::dominators::{dominators, Dominators}; use rustc_data_structures::graph::{self, GraphPredecessors, GraphSuccessors}; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; -use smallvec::SmallVec; use rustc_data_structures::sync::Lrc; use rustc_data_structures::sync::ReadGuard; use rustc_serialize as serialize; +use smallvec::SmallVec; use std::borrow::Cow; use std::fmt::{self, Debug, Formatter, Write}; use std::ops::{Index, IndexMut}; @@ -208,9 +208,10 @@ impl<'tcx> Mir<'tcx> { let if_zero_locations = if loc.statement_index == 0 { let predecessor_blocks = self.predecessors_for(loc.block); let num_predecessor_blocks = predecessor_blocks.len(); - Some((0 .. num_predecessor_blocks) - .map(move |i| predecessor_blocks[i]) - .map(move |bb| self.terminator_loc(bb)) + Some( + (0..num_predecessor_blocks) + .map(move |i| predecessor_blocks[i]) + .map(move |bb| self.terminator_loc(bb)), ) } else { None @@ -219,10 +220,16 @@ impl<'tcx> Mir<'tcx> { let if_not_zero_locations = if loc.statement_index == 0 { None } else { - Some(Location { block: loc.block, statement_index: loc.statement_index - 1 }) + Some(Location { + block: loc.block, + statement_index: loc.statement_index - 1, + }) }; - if_zero_locations.into_iter().flatten().chain(if_not_zero_locations) + if_zero_locations + .into_iter() + .flatten() + .chain(if_not_zero_locations) } #[inline] @@ -577,13 +584,15 @@ impl_stable_hash_for!(struct self::VarBindingForm<'tcx> { }); mod binding_form_impl { - use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult}; use ich::StableHashingContext; + use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult}; impl<'a, 'tcx> HashStable> for super::BindingForm<'tcx> { - fn hash_stable(&self, - hcx: &mut StableHashingContext<'a>, - hasher: &mut StableHasher) { + fn hash_stable( + &self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher, + ) { use super::BindingForm::*; ::std::mem::discriminant(self).hash_stable(hcx, hasher); @@ -1500,16 +1509,17 @@ impl<'tcx> TerminatorKind<'tcx> { .map(|&u| { let mut s = String::new(); let c = ty::Const { - val: ConstValue::Scalar(Scalar::Bits { + val: ConstValue::Scalar( + Scalar::Bits { bits: u, size: size.bytes() as u8, - }.into()), + }.into(), + ), ty: switch_ty, }; fmt_const_val(&mut s, &c).unwrap(); s.into() - }) - .chain(iter::once(String::from("otherwise").into())) + }).chain(iter::once(String::from("otherwise").into())) .collect() } Call { @@ -2039,7 +2049,13 @@ pub enum AggregateKind<'tcx> { /// active field number and is present only for union expressions /// -- e.g. for a union expression `SomeUnion { c: .. }`, the /// active field index would identity the field `c` - Adt(&'tcx AdtDef, usize, &'tcx Substs<'tcx>, Option>, Option), + Adt( + &'tcx AdtDef, + usize, + &'tcx Substs<'tcx>, + Option>, + Option, + ), Closure(DefId, ClosureSubsts<'tcx>), Generator(DefId, GeneratorSubsts<'tcx>, hir::GeneratorMovability), @@ -2289,7 +2305,7 @@ pub fn fmt_const_val(f: &mut impl Write, const_val: &ty::Const) -> fmt::Result { return write!(f, "{:?}{}", ((bits as i128) << shift) >> shift, i); } Char => return write!(f, "{:?}", ::std::char::from_u32(bits as u32).unwrap()), - _ => {}, + _ => {} } } // print function definitons @@ -2305,14 +2321,12 @@ pub fn fmt_const_val(f: &mut impl Write, const_val: &ty::Const) -> fmt::Result { let alloc = tcx.alloc_map.lock().get(ptr.alloc_id); if let Some(interpret::AllocType::Memory(alloc)) = alloc { assert_eq!(len as usize as u128, len); - let slice = &alloc - .bytes - [(ptr.offset.bytes() as usize)..] - [..(len as usize)]; + let slice = + &alloc.bytes[(ptr.offset.bytes() as usize)..][..(len as usize)]; let s = ::std::str::from_utf8(slice).expect("non utf8 str from miri"); write!(f, "{:?}", s) } else { - write!(f, "pointer to erroneous constant {:?}, {:?}", ptr, len) + write!(f, "pointer to erroneous constant {:?}, {:?}", ptr, len) } }); } @@ -2843,15 +2857,13 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> { let kind = box match **kind { AggregateKind::Array(ty) => AggregateKind::Array(ty.fold_with(folder)), AggregateKind::Tuple => AggregateKind::Tuple, - AggregateKind::Adt(def, v, substs, user_ty, n) => { - AggregateKind::Adt( - def, - v, - substs.fold_with(folder), - user_ty.fold_with(folder), - n, - ) - } + AggregateKind::Adt(def, v, substs, user_ty, n) => AggregateKind::Adt( + def, + v, + substs.fold_with(folder), + user_ty.fold_with(folder), + n, + ), AggregateKind::Closure(id, substs) => { AggregateKind::Closure(id, substs.fold_with(folder)) } @@ -2882,8 +2894,9 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> { (match **kind { AggregateKind::Array(ty) => ty.visit_with(visitor), AggregateKind::Tuple => false, - AggregateKind::Adt(_, _, substs, user_ty, _) => - substs.visit_with(visitor) || user_ty.visit_with(visitor), + AggregateKind::Adt(_, _, substs, user_ty, _) => { + substs.visit_with(visitor) || user_ty.visit_with(visitor) + } AggregateKind::Closure(_, substs) => substs.visit_with(visitor), AggregateKind::Generator(_, substs, _) => substs.visit_with(visitor), }) || fields.visit_with(visitor) diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index efd804983067a..a0b0aabf73e02 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -26,8 +26,8 @@ use super::{Context, MirBorrowckCtxt}; use super::{InitializationRequiringAction, PrefixSet}; use dataflow::drop_flag_effects; -use dataflow::move_paths::MovePathIndex; use dataflow::move_paths::indexes::MoveOutIndex; +use dataflow::move_paths::MovePathIndex; use util::borrowck_errors::{BorrowckErrors, Origin}; impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { @@ -347,10 +347,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { if issued_spans == borrow_spans { borrow_spans.var_span_label( &mut err, - format!( - "borrows occur due to use of `{}` in closure", - desc_place - ), + format!("borrows occur due to use of `{}` in closure", desc_place), ); } else { let borrow_place = &issued_borrow.borrowed_place; @@ -365,7 +362,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { borrow_spans.var_span_label( &mut err, - format!("second borrow occurs due to use of `{}` in closure", desc_place), + format!( + "second borrow occurs due to use of `{}` in closure", + desc_place + ), ); } @@ -412,10 +412,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { let mut err = match &self.describe_place(&borrow.borrowed_place) { Some(_) if self.is_place_thread_local(root_place) => { - self.report_thread_local_value_does_not_live_long_enough( - drop_span, - borrow_span, - ) + self.report_thread_local_value_does_not_live_long_enough(drop_span, borrow_span) } Some(name) => self.report_local_value_does_not_live_long_enough( context, @@ -461,7 +458,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { ); let mut err = self.tcx.path_does_not_live_long_enough( - borrow_span, &format!("`{}`", name), Origin::Mir); + borrow_span, + &format!("`{}`", name), + Origin::Mir, + ); err.span_label(borrow_span, "borrowed value does not live long enough"); err.span_label( @@ -485,11 +485,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { drop_span, borrow_span ); - let mut err = self.tcx.thread_local_value_does_not_live_long_enough( - borrow_span, Origin::Mir); + let mut err = self + .tcx + .thread_local_value_does_not_live_long_enough(borrow_span, Origin::Mir); - err.span_label(borrow_span, - "thread-local variables cannot be borrowed beyond the end of the function"); + err.span_label( + borrow_span, + "thread-local variables cannot be borrowed beyond the end of the function", + ); err.span_label(drop_span, "end of enclosing function is here"); err } @@ -520,11 +523,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { err } - fn get_moved_indexes( - &mut self, - context: Context, - mpi: MovePathIndex, - ) -> Vec { + fn get_moved_indexes(&mut self, context: Context, mpi: MovePathIndex) -> Vec { let mir = self.mir; let mut stack = Vec::new(); @@ -533,16 +532,21 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { let mut visited = FxHashSet(); let mut result = vec![]; - 'dfs: - while let Some(l) = stack.pop() { - debug!("report_use_of_moved_or_uninitialized: current_location={:?}", l); + 'dfs: while let Some(l) = stack.pop() { + debug!( + "report_use_of_moved_or_uninitialized: current_location={:?}", + l + ); if !visited.insert(l) { continue; } // check for moves - let stmt_kind = mir[l.block].statements.get(l.statement_index).map(|s| &s.kind); + let stmt_kind = mir[l.block] + .statements + .get(l.statement_index) + .map(|s| &s.kind); if let Some(StatementKind::StorageDead(..)) = stmt_kind { // this analysis only tries to find moves explicitly // written by the user, so we ignore the move-outs @@ -578,13 +582,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // check for inits let mut any_match = false; - drop_flag_effects::for_location_inits( - self.tcx, - self.mir, - self.move_data, - l, - |m| if m == mpi { any_match = true; }, - ); + drop_flag_effects::for_location_inits(self.tcx, self.mir, self.move_data, l, |m| { + if m == mpi { + any_match = true; + } + }); if any_match { continue 'dfs; } @@ -964,8 +966,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { let attrs = self.tcx.get_attrs(statik.def_id); let is_thread_local = attrs.iter().any(|attr| attr.check_name("thread_local")); - debug!("is_place_thread_local: attrs={:?} is_thread_local={:?}", - attrs, is_thread_local); + debug!( + "is_place_thread_local: attrs={:?} is_thread_local={:?}", + attrs, is_thread_local + ); is_thread_local } else { debug!("is_place_thread_local: no"); @@ -983,7 +987,7 @@ pub(super) enum UseSpans { // it's present. args_span: Span, // The span of the first use of the captured variable inside the closure. - var_span: Span + var_span: Span, }, // This access has a single span associated to it: common case. OtherUse(Span),