Auto merge of #66815 - mark-i-m:simplify-borrow_check-errors, r=Dylan-DPC

Reorganize borrow check diagnostic code

Currently borrow checker diagnostics are split across many different modules in different places in the `librustc_mir` crate. This moves them all to a `diagnostics` module. This also reduces the nesting of the modules a bit (sooo much nesting).

I am also thinking of moving stuff out of the `nll` module since we only have one borrow checker now (🎉), and maybe it even makes sense to split out all of this stuff to a `librustc_borrow_check`, but those are for the future. Feel free to ping me here or on zulip and let me know what you think...

cc @nikomatsakis @matthewjasper @eddyb
This commit is contained in:
bors 2019-12-05 14:39:11 +00:00
commit a0312c156d
13 changed files with 130 additions and 110 deletions

View File

@ -14,18 +14,22 @@ use rustc_errors::{Applicability, DiagnosticBuilder};
use syntax_pos::Span;
use syntax::source_map::DesugaringKind;
use super::nll::explain_borrow::BorrowExplanation;
use super::nll::region_infer::{RegionName, RegionNameSource};
use super::prefixes::IsPrefixOf;
use super::WriteKind;
use super::borrow_set::BorrowData;
use super::MirBorrowckCtxt;
use super::{InitializationRequiringAction, PrefixSet};
use super::error_reporting::{IncludingDowncast, UseSpans};
use crate::dataflow::drop_flag_effects;
use crate::dataflow::indexes::{MovePathIndex, MoveOutIndex};
use crate::util::borrowck_errors;
use crate::borrow_check::{
prefixes::IsPrefixOf,
WriteKind,
borrow_set::BorrowData,
MirBorrowckCtxt, InitializationRequiringAction, PrefixSet
};
use super::{
IncludingDowncast, UseSpans, RegionName, RegionNameSource,
explain_borrow::BorrowExplanation,
};
#[derive(Debug)]
struct MoveSite {
/// Index of the "move out" that we found. The `MoveData` can
@ -46,7 +50,7 @@ enum StorageDeadOrDrop<'tcx> {
}
impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
pub(super) fn report_use_of_moved_or_uninitialized(
pub(in crate::borrow_check) fn report_use_of_moved_or_uninitialized(
&mut self,
location: Location,
desired_action: InitializationRequiringAction,
@ -269,7 +273,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
}
pub(super) fn report_move_out_while_borrowed(
pub(in crate::borrow_check) fn report_move_out_while_borrowed(
&mut self,
location: Location,
(place, span): (&Place<'tcx>, Span),
@ -326,7 +330,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
err.buffer(&mut self.errors_buffer);
}
pub(super) fn report_use_while_mutably_borrowed(
pub(in crate::borrow_check) fn report_use_while_mutably_borrowed(
&mut self,
location: Location,
(place, _span): (&Place<'tcx>, Span),
@ -368,7 +372,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
err
}
pub(super) fn report_conflicting_borrow(
pub(in crate::borrow_check) fn report_conflicting_borrow(
&mut self,
location: Location,
(place, span): (&Place<'tcx>, Span),
@ -614,7 +618,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
///
/// > cannot borrow `a.u` (via `a.u.z.c`) as immutable because it is also borrowed as
/// > mutable (via `a.u.s.b`) [E0502]
pub(super) fn describe_place_for_conflicting_borrow(
pub(in crate::borrow_check) fn describe_place_for_conflicting_borrow(
&self,
first_borrowed_place: &Place<'tcx>,
second_borrowed_place: &Place<'tcx>,
@ -722,7 +726,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
/// short a lifetime. (But sometimes it is more useful to report
/// it as a more direct conflict between the execution of a
/// `Drop::drop` with an aliasing borrow.)
pub(super) fn report_borrowed_value_does_not_live_long_enough(
pub(in crate::borrow_check) fn report_borrowed_value_does_not_live_long_enough(
&mut self,
location: Location,
borrow: &BorrowData<'tcx>,
@ -1478,7 +1482,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
result
}
pub(super) fn report_illegal_mutation_of_borrowed(
pub(in crate::borrow_check) fn report_illegal_mutation_of_borrowed(
&mut self,
location: Location,
(place, span): (&Place<'tcx>, Span),
@ -1537,7 +1541,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
/// assigned; `err_place` is a place providing a reason why
/// `place` is not mutable (e.g., the non-`mut` local `x` in an
/// assignment to `x.f`).
pub(super) fn report_illegal_reassignment(
pub(in crate::borrow_check) fn report_illegal_reassignment(
&mut self,
_location: Location,
(place, span): (&Place<'tcx>, Span),
@ -2080,7 +2084,7 @@ enum AnnotatedBorrowFnSignature<'tcx> {
impl<'tcx> AnnotatedBorrowFnSignature<'tcx> {
/// Annotate the provided diagnostic with information about borrow from the fn signature that
/// helps explain.
pub(super) fn emit(
pub(in crate::borrow_check) fn emit(
&self,
cx: &mut MirBorrowckCtxt<'_, 'tcx>,
diag: &mut DiagnosticBuilder<'_>,

View File

@ -1,8 +1,7 @@
use std::collections::VecDeque;
use crate::borrow_check::borrow_set::BorrowData;
use crate::borrow_check::error_reporting::UseSpans;
use crate::borrow_check::nll::region_infer::{Cause, RegionName};
use crate::borrow_check::nll::region_infer::Cause;
use crate::borrow_check::nll::ConstraintDescription;
use crate::borrow_check::{MirBorrowckCtxt, WriteKind};
use rustc::mir::{
@ -17,7 +16,7 @@ use rustc_errors::DiagnosticBuilder;
use syntax_pos::Span;
use syntax_pos::symbol::Symbol;
mod find_use;
use super::{UseSpans, find_use, RegionName};
#[derive(Debug)]
pub(in crate::borrow_check) enum BorrowExplanation {

View File

@ -1,3 +1,5 @@
//! Borrow checker diagnostics.
use rustc::hir;
use rustc::hir::def::Namespace;
use rustc::hir::def_id::DefId;
@ -17,6 +19,22 @@ use super::borrow_set::BorrowData;
use super::MirBorrowckCtxt;
use crate::dataflow::move_paths::{InitLocation, LookupResult};
mod find_use;
mod var_name;
mod region_name;
mod outlives_suggestion;
mod conflict_errors;
mod move_errors;
mod mutability_errors;
mod region_errors;
mod explain_borrow;
crate use mutability_errors::AccessKind;
crate use region_name::{RegionName, RegionNameSource, RegionErrorNamingCtx};
crate use region_errors::{ErrorReportingCtx, ErrorConstraintInfo};
crate use outlives_suggestion::OutlivesSuggestionBuilder;
pub(super) struct IncludingDowncast(pub(super) bool);
impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {

View File

@ -5,7 +5,7 @@ use syntax_pos::Span;
use crate::borrow_check::MirBorrowckCtxt;
use crate::borrow_check::prefixes::PrefixSet;
use crate::borrow_check::error_reporting::UseSpans;
use crate::borrow_check::diagnostics::UseSpans;
use crate::dataflow::move_paths::{
IllegalMoveOrigin, IllegalMoveOriginKind,
LookupResult, MoveError, MovePathIndex,

View File

@ -8,18 +8,18 @@ use syntax_pos::Span;
use syntax_pos::symbol::kw;
use crate::borrow_check::MirBorrowckCtxt;
use crate::borrow_check::error_reporting::BorrowedContentSource;
use crate::borrow_check::diagnostics::BorrowedContentSource;
use crate::util::collect_writes::FindAssignments;
use rustc_errors::Applicability;
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub(super) enum AccessKind {
pub(crate) enum AccessKind {
MutableBorrow,
Mutate,
}
impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
pub(super) fn report_mutability_error(
pub(crate) fn report_mutability_error(
&mut self,
access_place: &Place<'tcx>,
span: Span,

View File

@ -13,12 +13,10 @@ use syntax_pos::symbol::Symbol;
use smallvec::SmallVec;
use crate::borrow_check::nll::region_infer::{
error_reporting::{
region_name::{RegionName, RegionNameSource},
ErrorConstraintInfo, ErrorReportingCtx, RegionErrorNamingCtx,
},
RegionInferenceContext,
use crate::borrow_check::nll::region_infer::RegionInferenceContext;
use super::{
RegionName, RegionNameSource, ErrorConstraintInfo, ErrorReportingCtx, RegionErrorNamingCtx,
};
/// The different things we could suggest.

View File

@ -19,14 +19,7 @@ use syntax::symbol::kw;
use syntax_pos::Span;
use syntax_pos::symbol::Symbol;
use self::outlives_suggestion::OutlivesSuggestionBuilder;
pub mod outlives_suggestion;
mod region_name;
mod var_name;
crate use self::region_name::{RegionName, RegionNameSource, RegionErrorNamingCtx};
use super::{OutlivesSuggestionBuilder, RegionName, RegionNameSource, RegionErrorNamingCtx};
impl ConstraintDescription for ConstraintCategory {
fn description(&self) -> &'static str {
@ -61,36 +54,36 @@ enum Trace {
/// Various pieces of state used when reporting borrow checker errors.
pub struct ErrorReportingCtx<'a, 'b, 'tcx> {
/// The region inference context used for borrow chekcing this MIR body.
region_infcx: &'b RegionInferenceContext<'tcx>,
pub(super) region_infcx: &'b RegionInferenceContext<'tcx>,
/// The inference context used for type checking.
infcx: &'b InferCtxt<'a, 'tcx>,
pub(super) infcx: &'b InferCtxt<'a, 'tcx>,
/// The MIR def we are reporting errors on.
mir_def_id: DefId,
pub(super) mir_def_id: DefId,
/// The MIR body we are reporting errors on (for convenience).
body: &'b Body<'tcx>,
pub(super) body: &'b Body<'tcx>,
/// User variable names for MIR locals (where applicable).
local_names: &'b IndexVec<Local, Option<Symbol>>,
pub(super) local_names: &'b IndexVec<Local, Option<Symbol>>,
/// Any upvars for the MIR body we have kept track of during borrow checking.
upvars: &'b [Upvar],
pub(super) upvars: &'b [Upvar],
}
/// Information about the various region constraints involved in a borrow checker error.
#[derive(Clone, Debug)]
pub struct ErrorConstraintInfo {
// fr: outlived_fr
fr: RegionVid,
fr_is_local: bool,
outlived_fr: RegionVid,
outlived_fr_is_local: bool,
pub(super) fr: RegionVid,
pub(super) fr_is_local: bool,
pub(super) outlived_fr: RegionVid,
pub(super) outlived_fr_is_local: bool,
// Category and span for best blame constraint
category: ConstraintCategory,
span: Span,
pub(super) category: ConstraintCategory,
pub(super) span: Span,
}
impl<'tcx> RegionInferenceContext<'tcx> {
@ -368,7 +361,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// ```
///
/// Here we would be invoked with `fr = 'a` and `outlived_fr = `'b`.
pub(super) fn report_error<'a>(
pub(in crate::borrow_check) fn report_error<'a>(
&'a self,
body: &Body<'tcx>,
local_names: &IndexVec<Local, Option<Symbol>>,

View File

@ -1,12 +1,5 @@
use std::fmt::{self, Display};
use crate::borrow_check::nll::region_infer::{
RegionInferenceContext,
error_reporting::ErrorReportingCtx,
};
use crate::borrow_check::nll::universal_regions::DefiningTy;
use crate::borrow_check::nll::ToRegionVid;
use crate::borrow_check::Upvar;
use rustc::hir;
use rustc::hir::def::{Res, DefKind};
use rustc::hir::def_id::DefId;
@ -21,6 +14,15 @@ use syntax::symbol::kw;
use rustc_data_structures::fx::FxHashMap;
use syntax_pos::{Span, symbol::Symbol, DUMMY_SP};
use crate::borrow_check::{
nll::region_infer::RegionInferenceContext,
nll::universal_regions::DefiningTy,
nll::ToRegionVid,
Upvar,
};
use super::region_errors::ErrorReportingCtx;
/// A name for a particular region used in emitting diagnostics. This name could be a generated
/// name like `'1`, a name used by the user like `'a`, or a name like `'static`.
#[derive(Debug, Clone)]

View File

@ -46,17 +46,14 @@ use self::flows::Flows;
use self::location::LocationTable;
use self::prefixes::PrefixSet;
use self::MutateMode::{JustWrite, WriteAndRead};
use self::mutability_errors::AccessKind;
use self::diagnostics::AccessKind;
use self::path_utils::*;
crate mod borrow_set;
mod error_reporting;
mod diagnostics;
mod flows;
mod location;
mod conflict_errors;
mod move_errors;
mod mutability_errors;
mod path_utils;
crate mod place_ext;
crate mod places_conflict;

View File

@ -32,17 +32,17 @@ use crate::util as mir_util;
use crate::util::pretty;
mod constraint_generation;
pub mod explain_borrow;
mod facts;
mod invalidation;
crate mod region_infer;
mod renumber;
crate mod type_check;
mod universal_regions;
mod constraints;
mod member_constraints;
crate mod constraints;
crate mod universal_regions;
crate mod type_check;
crate mod region_infer;
use self::facts::AllFacts;
use self::region_infer::RegionInferenceContext;
use self::universal_regions::UniversalRegions;

View File

@ -1,21 +1,5 @@
use std::rc::Rc;
use crate::borrow_check::nll::{
constraints::{
graph::NormalConstraintGraph,
ConstraintSccIndex,
OutlivesConstraint,
OutlivesConstraintSet,
},
member_constraints::{MemberConstraintSet, NllMemberConstraintIndex},
region_infer::values::{
PlaceholderIndices, RegionElement, ToElementIndex
},
region_infer::error_reporting::outlives_suggestion::OutlivesSuggestionBuilder,
type_check::{free_region_relations::UniversalRegionRelations, Locations},
};
use crate::borrow_check::Upvar;
use rustc::hir::def_id::DefId;
use rustc::infer::canonical::QueryOutlivesConstraint;
use rustc::infer::opaque_types;
@ -38,13 +22,31 @@ use rustc_errors::{Diagnostic, DiagnosticBuilder};
use syntax_pos::Span;
use syntax_pos::symbol::Symbol;
crate use self::error_reporting::{RegionName, RegionNameSource, RegionErrorNamingCtx};
use crate::borrow_check::{
nll::{
constraints::{
graph::NormalConstraintGraph,
ConstraintSccIndex,
OutlivesConstraint,
OutlivesConstraintSet,
},
member_constraints::{MemberConstraintSet, NllMemberConstraintIndex},
region_infer::values::{
PlaceholderIndices, RegionElement, ToElementIndex
},
type_check::{free_region_relations::UniversalRegionRelations, Locations},
},
diagnostics::{
OutlivesSuggestionBuilder, RegionErrorNamingCtx,
},
Upvar,
};
use self::values::{LivenessValues, RegionValueElements, RegionValues};
use super::universal_regions::UniversalRegions;
use super::ToRegionVid;
mod dump_mir;
mod error_reporting;
mod graphviz;
pub mod values;
@ -54,48 +56,51 @@ pub struct RegionInferenceContext<'tcx> {
/// variables are identified by their index (`RegionVid`). The
/// definition contains information about where the region came
/// from as well as its final inferred value.
definitions: IndexVec<RegionVid, RegionDefinition<'tcx>>,
pub(in crate::borrow_check) definitions: IndexVec<RegionVid, RegionDefinition<'tcx>>,
/// The liveness constraints added to each region. For most
/// regions, these start out empty and steadily grow, though for
/// each universally quantified region R they start out containing
/// the entire CFG and `end(R)`.
liveness_constraints: LivenessValues<RegionVid>,
pub(in crate::borrow_check) liveness_constraints: LivenessValues<RegionVid>,
/// The outlives constraints computed by the type-check.
constraints: Rc<OutlivesConstraintSet>,
pub(in crate::borrow_check) constraints: Rc<OutlivesConstraintSet>,
/// The constraint-set, but in graph form, making it easy to traverse
/// the constraints adjacent to a particular region. Used to construct
/// the SCC (see `constraint_sccs`) and for error reporting.
constraint_graph: Rc<NormalConstraintGraph>,
pub(in crate::borrow_check) constraint_graph: Rc<NormalConstraintGraph>,
/// The SCC computed from `constraints` and the constraint
/// graph. We have an edge from SCC A to SCC B if `A: B`. Used to
/// compute the values of each region.
constraint_sccs: Rc<Sccs<RegionVid, ConstraintSccIndex>>,
pub(in crate::borrow_check) constraint_sccs: Rc<Sccs<RegionVid, ConstraintSccIndex>>,
/// Reverse of the SCC constraint graph -- i.e., an edge `A -> B`
/// exists if `B: A`. Computed lazilly.
rev_constraint_graph: Option<Rc<VecGraph<ConstraintSccIndex>>>,
pub(in crate::borrow_check) rev_constraint_graph:
Option<Rc<VecGraph<ConstraintSccIndex>>>,
/// The "R0 member of [R1..Rn]" constraints, indexed by SCC.
member_constraints: Rc<MemberConstraintSet<'tcx, ConstraintSccIndex>>,
pub(in crate::borrow_check) member_constraints:
Rc<MemberConstraintSet<'tcx, ConstraintSccIndex>>,
/// Records the member constraints that we applied to each scc.
/// This is useful for error reporting. Once constraint
/// propagation is done, this vector is sorted according to
/// `member_region_scc`.
member_constraints_applied: Vec<AppliedMemberConstraint>,
pub(in crate::borrow_check) member_constraints_applied: Vec<AppliedMemberConstraint>,
/// Map closure bounds to a `Span` that should be used for error reporting.
closure_bounds_mapping:
pub(in crate::borrow_check) closure_bounds_mapping:
FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>>,
/// Contains the minimum universe of any variable within the same
/// SCC. We will ensure that no SCC contains values that are not
/// visible from this index.
scc_universes: IndexVec<ConstraintSccIndex, ty::UniverseIndex>,
pub(in crate::borrow_check) scc_universes:
IndexVec<ConstraintSccIndex, ty::UniverseIndex>,
/// Contains a "representative" from each SCC. This will be the
/// minimal RegionVid belonging to that universe. It is used as a
@ -104,23 +109,25 @@ pub struct RegionInferenceContext<'tcx> {
/// of its SCC and be sure that -- if they have the same repr --
/// they *must* be equal (though not having the same repr does not
/// mean they are unequal).
scc_representatives: IndexVec<ConstraintSccIndex, ty::RegionVid>,
pub(in crate::borrow_check) scc_representatives:
IndexVec<ConstraintSccIndex, ty::RegionVid>,
/// The final inferred values of the region variables; we compute
/// one value per SCC. To get the value for any given *region*,
/// you first find which scc it is a part of.
scc_values: RegionValues<ConstraintSccIndex>,
pub(in crate::borrow_check) scc_values: RegionValues<ConstraintSccIndex>,
/// Type constraints that we check after solving.
type_tests: Vec<TypeTest<'tcx>>,
pub(in crate::borrow_check) type_tests: Vec<TypeTest<'tcx>>,
/// Information about the universally quantified regions in scope
/// on this function.
universal_regions: Rc<UniversalRegions<'tcx>>,
pub (in crate::borrow_check) universal_regions: Rc<UniversalRegions<'tcx>>,
/// Information about how the universally quantified regions in
/// scope on this function relate to one another.
universal_region_relations: Rc<UniversalRegionRelations<'tcx>>,
pub(in crate::borrow_check) universal_region_relations:
Rc<UniversalRegionRelations<'tcx>>,
}
/// Each time that `apply_member_constraint` is successful, it appends
@ -132,38 +139,38 @@ pub struct RegionInferenceContext<'tcx> {
/// with `'R: 'O` where `'R` is the pick-region and `'O` is the
/// minimal viable option.
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
struct AppliedMemberConstraint {
pub(crate) struct AppliedMemberConstraint {
/// The SCC that was affected. (The "member region".)
///
/// The vector if `AppliedMemberConstraint` elements is kept sorted
/// by this field.
member_region_scc: ConstraintSccIndex,
pub(in crate::borrow_check) member_region_scc: ConstraintSccIndex,
/// The "best option" that `apply_member_constraint` found -- this was
/// added as an "ad-hoc" lower-bound to `member_region_scc`.
min_choice: ty::RegionVid,
pub(in crate::borrow_check) min_choice: ty::RegionVid,
/// The "member constraint index" -- we can find out details about
/// the constraint from
/// `set.member_constraints[member_constraint_index]`.
member_constraint_index: NllMemberConstraintIndex,
pub(in crate::borrow_check) member_constraint_index: NllMemberConstraintIndex,
}
struct RegionDefinition<'tcx> {
pub(crate) struct RegionDefinition<'tcx> {
/// What kind of variable is this -- a free region? existential
/// variable? etc. (See the `NLLRegionVariableOrigin` for more
/// info.)
origin: NLLRegionVariableOrigin,
pub(in crate::borrow_check) origin: NLLRegionVariableOrigin,
/// Which universe is this region variable defined in? This is
/// most often `ty::UniverseIndex::ROOT`, but when we encounter
/// forall-quantifiers like `for<'a> { 'a = 'b }`, we would create
/// the variable for `'a` in a fresh universe that extends ROOT.
universe: ty::UniverseIndex,
pub(in crate::borrow_check) universe: ty::UniverseIndex,
/// If this is 'static or an early-bound region, then this is
/// `Some(X)` where `X` is the name of the region.
external_name: Option<ty::Region<'tcx>>,
pub(in crate::borrow_check) external_name: Option<ty::Region<'tcx>>,
}
/// N.B., the variants in `Cause` are intentionally ordered. Lower
@ -455,7 +462,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// Once region solving has completed, this function will return
/// the member constraints that were applied to the value of a given
/// region `r`. See `AppliedMemberConstraint`.
fn applied_member_constraints(&self, r: impl ToRegionVid) -> &[AppliedMemberConstraint] {
pub(in crate::borrow_check) fn applied_member_constraints(
&self, r: impl ToRegionVid
) -> &[AppliedMemberConstraint] {
let scc = self.constraint_sccs.scc(r.to_region_vid());
binary_search_util::binary_search_slice(
&self.member_constraints_applied,