summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_borrowck/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_borrowck/src/lib.rs')
-rw-r--r--compiler/rustc_borrowck/src/lib.rs102
1 files changed, 37 insertions, 65 deletions
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 0f591460e..a4b285a34 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -1,12 +1,11 @@
//! This query borrow-checks the MIR to (further) ensure it is not broken.
-#![allow(rustc::potential_query_instability)]
#![feature(associated_type_bounds)]
#![feature(box_patterns)]
#![feature(let_chains)]
#![feature(min_specialization)]
#![feature(never_type)]
-#![feature(once_cell)]
+#![feature(lazy_cell)]
#![feature(rustc_attrs)]
#![feature(stmt_expr_attributes)]
#![feature(trusted_step)]
@@ -18,14 +17,13 @@ extern crate rustc_middle;
#[macro_use]
extern crate tracing;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_data_structures::graph::dominators::Dominators;
-use rustc_data_structures::vec_map::VecMap;
use rustc_errors::{Diagnostic, DiagnosticBuilder, DiagnosticMessage, SubdiagnosticMessage};
use rustc_hir as hir;
use rustc_hir::def_id::LocalDefId;
use rustc_index::bit_set::ChunkedBitSet;
-use rustc_index::vec::IndexVec;
+use rustc_index::vec::{IndexSlice, IndexVec};
use rustc_infer::infer::{
DefiningAnchor, InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin, TyCtxtInferExt,
};
@@ -35,12 +33,13 @@ use rustc_middle::mir::{
Place, PlaceElem, PlaceRef, VarDebugInfoContents,
};
use rustc_middle::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind};
-use rustc_middle::mir::{Field, ProjectionElem, Promoted, Rvalue, Statement, StatementKind};
use rustc_middle::mir::{InlineAsmOperand, Terminator, TerminatorKind};
+use rustc_middle::mir::{ProjectionElem, Promoted, Rvalue, Statement, StatementKind};
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, CapturedPlace, ParamEnv, RegionVid, TyCtxt};
use rustc_session::lint::builtin::UNUSED_MUT;
use rustc_span::{Span, Symbol};
+use rustc_target::abi::FieldIdx;
use either::Either;
use smallvec::SmallVec;
@@ -95,13 +94,13 @@ pub mod consumers;
use borrow_set::{BorrowData, BorrowSet};
use dataflow::{BorrowIndex, BorrowckFlowState as Flows, BorrowckResults, Borrows};
-use nll::{PoloniusOutput, ToRegionVid};
+use nll::PoloniusOutput;
use place_ext::PlaceExt;
use places_conflict::{places_conflict, PlaceConflictBias};
use region_infer::RegionInferenceContext;
use renumber::RegionCtxt;
-fluent_messages! { "../locales/en-US.ftl" }
+fluent_messages! { "../messages.ftl" }
// FIXME(eddyb) perhaps move this somewhere more centrally.
#[derive(Debug)]
@@ -142,7 +141,7 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> &Bor
debug!("Skipping borrowck because of injected body");
// Let's make up a borrowck result! Fun times!
let result = BorrowCheckResult {
- concrete_opaque_types: VecMap::new(),
+ concrete_opaque_types: FxIndexMap::default(),
closure_requirements: None,
used_mut_upvars: SmallVec::new(),
tainted_by_errors: None,
@@ -155,7 +154,7 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> &Bor
let infcx =
tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(hir_owner.def_id)).build();
let input_body: &Body<'_> = &input_body.borrow();
- let promoted: &IndexVec<_, _> = &promoted.borrow();
+ let promoted: &IndexSlice<_, _> = &promoted.borrow();
let opt_closure_req = do_mir_borrowck(&infcx, input_body, promoted, false).0;
debug!("mir_borrowck done");
@@ -171,7 +170,7 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> &Bor
fn do_mir_borrowck<'tcx>(
infcx: &InferCtxt<'tcx>,
input_body: &Body<'tcx>,
- input_promoted: &IndexVec<Promoted, Body<'tcx>>,
+ input_promoted: &IndexSlice<Promoted, Body<'tcx>>,
return_body_with_facts: bool,
) -> (BorrowCheckResult<'tcx>, Option<Box<BodyWithBorrowckFacts<'tcx>>>) {
let def = input_body.source.with_opt_param().as_local().unwrap();
@@ -224,7 +223,7 @@ fn do_mir_borrowck<'tcx>(
// be modified (in place) to contain non-lexical lifetimes. It
// will have a lifetime tied to the inference context.
let mut body_owned = input_body.clone();
- let mut promoted = input_promoted.clone();
+ let mut promoted = input_promoted.to_owned();
let free_regions =
nll::replace_regions_in_mir(&infcx, param_env, &mut body_owned, &mut promoted);
let body = &body_owned; // no further changes
@@ -404,7 +403,7 @@ fn do_mir_borrowck<'tcx>(
// Note that this set is expected to be small - only upvars from closures
// would have a chance of erroneously adding non-user-defined mutable vars
// to the set.
- let temporary_used_locals: FxHashSet<Local> = mbcx
+ let temporary_used_locals: FxIndexSet<Local> = mbcx
.used_mut
.iter()
.filter(|&local| !mbcx.body.local_decls[*local].is_user_variable())
@@ -491,7 +490,7 @@ pub struct BodyWithBorrowckFacts<'tcx> {
pub struct BorrowckInferCtxt<'cx, 'tcx> {
pub(crate) infcx: &'cx InferCtxt<'tcx>,
- pub(crate) reg_var_to_origin: RefCell<FxHashMap<ty::RegionVid, RegionCtxt>>,
+ pub(crate) reg_var_to_origin: RefCell<FxIndexMap<ty::RegionVid, RegionCtxt>>,
}
impl<'cx, 'tcx> BorrowckInferCtxt<'cx, 'tcx> {
@@ -508,20 +507,13 @@ impl<'cx, 'tcx> BorrowckInferCtxt<'cx, 'tcx> {
F: Fn() -> RegionCtxt,
{
let next_region = self.infcx.next_region_var(origin);
- let vid = next_region
- .as_var()
- .unwrap_or_else(|| bug!("expected RegionKind::RegionVar on {:?}", next_region));
+ let vid = next_region.as_var();
- if cfg!(debug_assertions) {
+ if cfg!(debug_assertions) && !self.inside_canonicalization_ctxt() {
debug!("inserting vid {:?} with origin {:?} into var_to_origin", vid, origin);
let ctxt = get_ctxt_fn();
let mut var_to_origin = self.reg_var_to_origin.borrow_mut();
- let prev = var_to_origin.insert(vid, ctxt);
-
- // This only makes sense if not called in a canonicalization context. If this
- // ever changes we either want to get rid of `BorrowckInferContext::reg_var_to_origin`
- // or modify how we track nll region vars for that map.
- assert!(matches!(prev, None));
+ var_to_origin.insert(vid, ctxt);
}
next_region
@@ -537,20 +529,13 @@ impl<'cx, 'tcx> BorrowckInferCtxt<'cx, 'tcx> {
F: Fn() -> RegionCtxt,
{
let next_region = self.infcx.next_nll_region_var(origin.clone());
- let vid = next_region
- .as_var()
- .unwrap_or_else(|| bug!("expected RegionKind::RegionVar on {:?}", next_region));
+ let vid = next_region.as_var();
- if cfg!(debug_assertions) {
+ if cfg!(debug_assertions) && !self.inside_canonicalization_ctxt() {
debug!("inserting vid {:?} with origin {:?} into var_to_origin", vid, origin);
let ctxt = get_ctxt_fn();
let mut var_to_origin = self.reg_var_to_origin.borrow_mut();
- let prev = var_to_origin.insert(vid, ctxt);
-
- // This only makes sense if not called in a canonicalization context. If this
- // ever changes we either want to get rid of `BorrowckInferContext::reg_var_to_origin`
- // or modify how we track nll region vars for that map.
- assert!(matches!(prev, None));
+ var_to_origin.insert(vid, ctxt);
}
next_region
@@ -588,7 +573,7 @@ struct MirBorrowckCtxt<'cx, 'tcx> {
/// borrow errors that is handled by the `reservation_error_reported` field as the inclusion
/// of the `Span` type (while required to mute some errors) stops the muting of the reservation
/// errors.
- access_place_error_reported: FxHashSet<(Place<'tcx>, Span)>,
+ access_place_error_reported: FxIndexSet<(Place<'tcx>, Span)>,
/// This field keeps track of when borrow conflict errors are reported
/// for reservations, so that we don't report seemingly duplicate
/// errors for corresponding activations.
@@ -596,20 +581,20 @@ struct MirBorrowckCtxt<'cx, 'tcx> {
// FIXME: ideally this would be a set of `BorrowIndex`, not `Place`s,
// but it is currently inconvenient to track down the `BorrowIndex`
// at the time we detect and report a reservation error.
- reservation_error_reported: FxHashSet<Place<'tcx>>,
+ reservation_error_reported: FxIndexSet<Place<'tcx>>,
/// This fields keeps track of the `Span`s that we have
/// used to report extra information for `FnSelfUse`, to avoid
/// unnecessarily verbose errors.
- fn_self_span_reported: FxHashSet<Span>,
+ fn_self_span_reported: FxIndexSet<Span>,
/// This field keeps track of errors reported in the checking of uninitialized variables,
/// so that we don't report seemingly duplicate errors.
- uninitialized_error_reported: FxHashSet<PlaceRef<'tcx>>,
+ uninitialized_error_reported: FxIndexSet<PlaceRef<'tcx>>,
/// This field keeps track of all the local variables that are declared mut and are mutated.
/// Used for the warning issued by an unused mutable local variable.
- used_mut: FxHashSet<Local>,
+ used_mut: FxIndexSet<Local>,
/// If the function we're checking is a closure, then we'll need to report back the list of
/// mutable upvars that have been used. This field keeps track of them.
- used_mut_upvars: SmallVec<[Field; 8]>,
+ used_mut_upvars: SmallVec<[FieldIdx; 8]>,
/// Region inference context. This contains the results from region inference and lets us e.g.
/// find out which CFG points are contained in each borrow region.
regioncx: Rc<RegionInferenceContext<'tcx>>,
@@ -628,7 +613,7 @@ struct MirBorrowckCtxt<'cx, 'tcx> {
/// Record the region names generated for each region in the given
/// MIR def so that we can reuse them later in help/error messages.
- region_names: RefCell<FxHashMap<RegionVid, RegionName>>,
+ region_names: RefCell<FxIndexMap<RegionVid, RegionName>>,
/// The counter for generating new region names.
next_region_name: RefCell<usize>,
@@ -691,6 +676,8 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
}
// Only relevant for mir typeck
StatementKind::AscribeUserType(..)
+ // Only relevant for unsafeck
+ | StatementKind::PlaceMention(..)
// Doesn't have any language semantics
| StatementKind::Coverage(..)
// These do not actually affect borrowck
@@ -744,21 +731,12 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
flow_state,
);
}
- TerminatorKind::DropAndReplace {
- place: drop_place,
- value: new_value,
- target: _,
- unwind: _,
- } => {
- self.mutate_place(loc, (*drop_place, span), Deep, flow_state);
- self.consume_operand(loc, (new_value, span), flow_state);
- }
TerminatorKind::Call {
func,
args,
destination,
target: _,
- cleanup: _,
+ unwind: _,
from_hir_call: _,
fn_span: _,
} => {
@@ -768,7 +746,7 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
}
self.mutate_place(loc, (*destination, span), Deep, flow_state);
}
- TerminatorKind::Assert { cond, expected: _, msg, target: _, cleanup: _ } => {
+ TerminatorKind::Assert { cond, expected: _, msg, target: _, unwind: _ } => {
self.consume_operand(loc, (cond, span), flow_state);
use rustc_middle::mir::AssertKind;
if let AssertKind::BoundsCheck { len, index } = msg {
@@ -788,7 +766,7 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
options: _,
line_spans: _,
destination: _,
- cleanup: _,
+ unwind: _,
} => {
for op in operands {
match op {
@@ -819,7 +797,7 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
}
TerminatorKind::Goto { target: _ }
- | TerminatorKind::Abort
+ | TerminatorKind::Terminate
| TerminatorKind::Unreachable
| TerminatorKind::Resume
| TerminatorKind::Return
@@ -863,11 +841,10 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
}
}
- TerminatorKind::Abort
+ TerminatorKind::Terminate
| TerminatorKind::Assert { .. }
| TerminatorKind::Call { .. }
| TerminatorKind::Drop { .. }
- | TerminatorKind::DropAndReplace { .. }
| TerminatorKind::FalseEdge { real_target: _, imaginary_target: _ }
| TerminatorKind::FalseUnwind { real_target: _, unwind: _ }
| TerminatorKind::Goto { .. }
@@ -1185,12 +1162,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
this.buffer_error(err);
}
WriteKind::StorageDeadOrDrop => this
- .report_borrowed_value_does_not_live_long_enough(
- location,
- borrow,
- place_span,
- Some(kind),
- ),
+ .report_storage_dead_or_drop_of_borrowed(location, place_span, borrow),
WriteKind::Mutate => {
this.report_illegal_mutation_of_borrowed(location, place_span, borrow)
}
@@ -1367,7 +1339,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
self.infcx.tcx.mir_borrowck(def_id);
debug!("{:?} used_mut_upvars={:?}", def_id, used_mut_upvars);
for field in used_mut_upvars {
- self.propagate_closure_used_mut_upvar(&operands[field.index()]);
+ self.propagate_closure_used_mut_upvar(&operands[*field]);
}
}
AggregateKind::Adt(..)
@@ -2302,7 +2274,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
/// then returns the index of the field being projected. Note that this closure will always
/// be `self` in the current MIR, because that is the only time we directly access the fields
/// of a closure type.
- fn is_upvar_field_projection(&self, place_ref: PlaceRef<'tcx>) -> Option<Field> {
+ fn is_upvar_field_projection(&self, place_ref: PlaceRef<'tcx>) -> Option<FieldIdx> {
path_utils::is_upvar_field_projection(self.infcx.tcx, &self.upvars, place_ref, self.body())
}
@@ -2334,7 +2306,7 @@ mod error {
/// same primary span come out in a consistent order.
buffered_move_errors:
BTreeMap<Vec<MoveOutIndex>, (PlaceRef<'tcx>, DiagnosticBuilder<'tcx, ErrorGuaranteed>)>,
- buffered_mut_errors: FxHashMap<Span, (DiagnosticBuilder<'tcx, ErrorGuaranteed>, usize)>,
+ buffered_mut_errors: FxIndexMap<Span, (DiagnosticBuilder<'tcx, ErrorGuaranteed>, usize)>,
/// Diagnostics to be reported buffer.
buffered: Vec<Diagnostic>,
/// Set to Some if we emit an error during borrowck