Move ConstraintCategory to rustc::mir

Allows us to use the category of outlive requirements inside a closure
when reporting free region errors caused by its closure bounds.
This commit is contained in:
Matthew Jasper 2018-10-03 21:33:22 +01:00
parent ac841e7450
commit 1160e60df9
12 changed files with 86 additions and 62 deletions

View file

@ -550,7 +550,23 @@ impl_stable_hash_for!(struct mir::ClosureRegionRequirements<'tcx> {
impl_stable_hash_for!(struct mir::ClosureOutlivesRequirement<'tcx> {
subject,
outlived_free_region,
blame_span
blame_span,
category
});
impl_stable_hash_for!(enum mir::ConstraintCategory {
Return,
TypeAnnotation,
Cast,
ClosureBounds,
CallArgument,
CopyBound,
SizedBound,
Assignment,
OpaqueType,
Boring,
BoringNoLocation,
Internal,
});
impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for mir::ClosureOutlivesSubject<'gcx> {

View file

@ -2646,6 +2646,43 @@ pub struct ClosureOutlivesRequirement<'tcx> {
pub blame_span: Span,
}
/// Outlives constraints can be categorized to determine whether and why they
/// are interesting (for error reporting). Order of variants indicates sort
/// order of the category, thereby influencing diagnostic output.
///
/// See also [rustc_mir::borrow_check::nll::constraints]
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
pub enum ConstraintCategory {
Return,
TypeAnnotation,
Cast,
/// A constraint that came from checking the body of a closure.
///
/// We try to get the category that the closure used when reporting this.
ClosureBounds,
CallArgument,
CopyBound,
SizedBound,
Assignment,
OpaqueType,
/// A "boring" constraint (caused by the given location) is one that
/// the user probably doesn't want to see described in diagnostics,
/// because it is kind of an artifact of the type system setup.
/// Example: `x = Foo { field: y }` technically creates
/// intermediate regions representing the "type of `Foo { field: y
/// }`", and data flows from `y` into those variables, but they
/// are not very interesting. The assignment into `x` on the other
/// hand might be.
Boring,
// Boring and applicable everywhere.
BoringNoLocation,
/// A constraint that doesn't correspond to anything the user sees.
Internal,
}
/// The subject of a ClosureOutlivesRequirement -- that is, the thing
/// that must outlive some region.
#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]

View file

@ -9,8 +9,9 @@
// except according to those terms.
use borrow_check::nll::type_check::Locations;
use borrow_check::nll::constraints::{ConstraintCategory, ConstraintIndex};
use borrow_check::nll::constraints::ConstraintIndex;
use borrow_check::nll::constraints::{ConstraintSet, OutlivesConstraint};
use rustc::mir::ConstraintCategory;
use rustc::ty::RegionVid;
use rustc_data_structures::graph;
use rustc_data_structures::indexed_vec::IndexVec;

View file

@ -8,6 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use rustc::mir::ConstraintCategory;
use rustc::ty::RegionVid;
use rustc_data_structures::graph::scc::Sccs;
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
@ -23,42 +24,6 @@ crate struct ConstraintSet {
constraints: IndexVec<ConstraintIndex, OutlivesConstraint>,
}
/// Constraints can be categorized to determine whether and why they are
/// interesting. Order of variants indicates sort order of the category,
/// thereby influencing diagnostic output.
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
pub enum ConstraintCategory {
Return,
TypeAnnotation,
Cast,
CallArgument,
/// A constraint that came from checking the body of a closure.
///
/// Ideally we would give an explanation that points to the relevant part
/// of the closure's body.
ClosureBounds,
CopyBound,
SizedBound,
Assignment,
OpaqueType,
/// A "boring" constraint (caused by the given location) is one that
/// the user probably doesn't want to see described in diagnostics,
/// because it is kind of an artifact of the type system setup.
/// Example: `x = Foo { field: y }` technically creates
/// intermediate regions representing the "type of `Foo { field: y
/// }`", and data flows from `y` into those variables, but they
/// are not very interesting. The assignment into `x` on the other
/// hand might be.
Boring,
// Boring and applicable everywhere.
BoringNoLocation,
/// A constraint that doesn't correspond to anything the user sees.
Internal,
}
impl ConstraintSet {
crate fn push(&mut self, constraint: OutlivesConstraint) {
debug!(

View file

@ -8,12 +8,12 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use borrow_check::nll::constraints::{OutlivesConstraint, ConstraintCategory};
use borrow_check::nll::constraints::{OutlivesConstraint};
use borrow_check::nll::region_infer::RegionInferenceContext;
use rustc::hir::def_id::DefId;
use rustc::infer::error_reporting::nice_region_error::NiceRegionError;
use rustc::infer::InferCtxt;
use rustc::mir::{Location, Mir};
use rustc::mir::{ConstraintCategory, Location, Mir};
use rustc::ty::{self, RegionVid};
use rustc_data_structures::indexed_vec::IndexVec;
use rustc_errors::{Diagnostic, DiagnosticBuilder};
@ -28,22 +28,26 @@ mod var_name;
use self::region_name::RegionName;
impl fmt::Display for ConstraintCategory {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
trait ConstraintDescription {
fn description(&self) -> &'static str;
}
impl ConstraintDescription for ConstraintCategory {
fn description(&self) -> &'static str {
// Must end with a space. Allows for empty names to be provided.
match self {
ConstraintCategory::Assignment => write!(f, "assignment "),
ConstraintCategory::Return => write!(f, "returning this value "),
ConstraintCategory::Cast => write!(f, "cast "),
ConstraintCategory::CallArgument => write!(f, "argument "),
ConstraintCategory::TypeAnnotation => write!(f, "type annotation "),
ConstraintCategory::ClosureBounds => write!(f, "closure body "),
ConstraintCategory::SizedBound => write!(f, "proving this value is `Sized` "),
ConstraintCategory::CopyBound => write!(f, "copying this value "),
ConstraintCategory::OpaqueType => write!(f, "opaque type "),
ConstraintCategory::Assignment => "assignment ",
ConstraintCategory::Return => "returning this value ",
ConstraintCategory::Cast => "cast ",
ConstraintCategory::CallArgument => "argument ",
ConstraintCategory::TypeAnnotation => "type annotation ",
ConstraintCategory::ClosureBounds => "closure body ",
ConstraintCategory::SizedBound => "proving this value is `Sized` ",
ConstraintCategory::CopyBound => "copying this value ",
ConstraintCategory::OpaqueType => "opaque type ",
ConstraintCategory::Boring
| ConstraintCategory::BoringNoLocation
| ConstraintCategory::Internal => write!(f, ""),
| ConstraintCategory::Internal => "",
}
}
}
@ -358,7 +362,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
_ => {
diag.span_label(span, format!(
"{}requires that `{}` must outlive `{}`",
category, fr_name, outlived_fr_name,
category.description(), fr_name, outlived_fr_name,
));
},
}

View file

@ -19,8 +19,8 @@ use rustc::infer::canonical::QueryRegionConstraint;
use rustc::infer::region_constraints::{GenericKind, VarInfos, VerifyBound};
use rustc::infer::{InferCtxt, NLLRegionVariableOrigin, RegionVariableOrigin};
use rustc::mir::{
ClosureOutlivesRequirement, ClosureOutlivesSubject, ClosureRegionRequirements, Local, Location,
Mir,
ClosureOutlivesRequirement, ClosureOutlivesSubject, ClosureRegionRequirements,
ConstraintCategory, Local, Location, Mir,
};
use rustc::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable};
use rustc::util::common;

View file

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use borrow_check::nll::constraints::{ConstraintCategory, ConstraintSet, OutlivesConstraint};
use borrow_check::nll::constraints::{ConstraintSet, OutlivesConstraint};
use borrow_check::nll::region_infer::TypeTest;
use borrow_check::nll::type_check::Locations;
use borrow_check::nll::universal_regions::UniversalRegions;
@ -17,6 +17,7 @@ use rustc::infer::outlives::env::RegionBoundPairs;
use rustc::infer::outlives::obligations::{TypeOutlives, TypeOutlivesDelegate};
use rustc::infer::region_constraints::{GenericKind, VerifyBound};
use rustc::infer::{self, SubregionOrigin};
use rustc::mir::ConstraintCategory;
use rustc::ty::subst::UnpackedKind;
use rustc::ty::{self, TyCtxt};
use syntax_pos::DUMMY_SP;

View file

@ -12,11 +12,11 @@ use borrow_check::nll::type_check::constraint_conversion;
use borrow_check::nll::type_check::{Locations, MirTypeckRegionConstraints};
use borrow_check::nll::universal_regions::UniversalRegions;
use borrow_check::nll::ToRegionVid;
use borrow_check::nll::constraints::ConstraintCategory;
use rustc::infer::canonical::QueryRegionConstraint;
use rustc::infer::outlives::free_region_map::FreeRegionRelations;
use rustc::infer::region_constraints::GenericKind;
use rustc::infer::InferCtxt;
use rustc::mir::ConstraintCategory;
use rustc::traits::query::outlives_bounds::{self, OutlivesBound};
use rustc::traits::query::type_op::{self, TypeOp};
use rustc::ty::{self, RegionVid, Ty};

View file

@ -24,7 +24,7 @@ use rustc::ty::Ty;
use rustc_data_structures::indexed_vec::Idx;
use syntax_pos::Span;
use super::{ConstraintCategory, Locations, TypeChecker};
use super::{Locations, TypeChecker};
impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
pub(super) fn equate_inputs_and_outputs(

View file

@ -9,7 +9,6 @@
// except according to those terms.
use borrow_check::location::LocationTable;
use borrow_check::nll::constraints::ConstraintCategory;
use borrow_check::nll::region_infer::values::{self, PointIndex, RegionValueElements};
use borrow_check::nll::type_check::liveness::liveness_map::{LiveVar, NllLivenessMap};
use borrow_check::nll::type_check::liveness::local_use_map::LocalUseMap;
@ -19,7 +18,7 @@ use dataflow::move_paths::indexes::MovePathIndex;
use dataflow::move_paths::MoveData;
use dataflow::{FlowAtLocation, FlowsAtLocation, MaybeInitializedPlaces};
use rustc::infer::canonical::QueryRegionConstraint;
use rustc::mir::{BasicBlock, Local, Location, Mir};
use rustc::mir::{BasicBlock, ConstraintCategory, Local, Location, Mir};
use rustc::traits::query::dropck_outlives::DropckOutlivesResult;
use rustc::traits::query::type_op::outlives::DropckOutlives;
use rustc::traits::query::type_op::TypeOp;

View file

@ -13,7 +13,7 @@
use borrow_check::borrow_set::BorrowSet;
use borrow_check::location::LocationTable;
use borrow_check::nll::constraints::{ConstraintCategory, ConstraintSet, OutlivesConstraint};
use borrow_check::nll::constraints::{ConstraintSet, OutlivesConstraint};
use borrow_check::nll::facts::AllFacts;
use borrow_check::nll::region_infer::values::LivenessValues;
use borrow_check::nll::region_infer::values::PlaceholderIndices;

View file

@ -8,10 +8,11 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use borrow_check::nll::constraints::{ConstraintCategory, OutlivesConstraint};
use borrow_check::nll::constraints::OutlivesConstraint;
use borrow_check::nll::type_check::{BorrowCheckContext, Locations};
use rustc::infer::canonical::{Canonical, CanonicalVarInfos};
use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
use rustc::mir::ConstraintCategory;
use rustc::traits::query::Fallible;
use rustc::ty::fold::{TypeFoldable, TypeVisitor};
use rustc::ty::relate::{self, Relate, RelateResult, TypeRelation};