Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
86334c7
remove unnecessary intermediate vector from `copy`
nikomatsakis Dec 3, 2017
a0f0392
rename `copy` to `dfs` and make it customizable
nikomatsakis Dec 3, 2017
cd564d2
only propagate ClosureRegionRequirements if non-trivial
nikomatsakis Dec 3, 2017
6193c5c
translate `Verify`s into `TypeTest`s and check them
nikomatsakis Dec 3, 2017
fad3d1d
dfs.rs: rustfmt
nikomatsakis Dec 5, 2017
1c57468
move `type_check` out of `transform` and into the `nll` module
nikomatsakis Dec 3, 2017
ebd086b
move `LivenessResults` from `nll` into `liveness` analysis
nikomatsakis Dec 3, 2017
4a940b3
move `flow_in_progress` into `dataflow` and document it
nikomatsakis Dec 3, 2017
47c1921
move some parts of liveness to happen during type checking
nikomatsakis Dec 3, 2017
02e6525
mild refactors of the control flow (no functional changes)
nikomatsakis Dec 4, 2017
154cd94
rework region flags: 'static can be erased too
nikomatsakis Dec 4, 2017
c7cfa23
thread through an implicit region body of the fn body
nikomatsakis Dec 4, 2017
5804637
permit `ClosureOutlivesRequirement` to constrain regions or types
nikomatsakis Dec 4, 2017
85e1d47
propagate type tests from closure to closure creators
nikomatsakis Dec 4, 2017
3a5842a
add a new RegionKind variant: ReClosureBound
nikomatsakis Dec 5, 2017
3fcb13a
handle projections with regions
nikomatsakis Dec 5, 2017
e9824c5
impose inputs/ouputs on MIR after the fact
nikomatsakis Dec 6, 2017
a118afe
add a test regarding relating closure and fn generics
nikomatsakis Dec 6, 2017
0d6bd42
make `blame_span` deterministic
nikomatsakis Dec 6, 2017
0f8ef0c
more concise debug output when dumping the value of a region
nikomatsakis Dec 6, 2017
4f43c5b
stop dumping DefPath into "failed type test" errors
nikomatsakis Dec 15, 2017
03bfb0f
tweak comment on `TypeTest` to be more accurate
nikomatsakis Dec 19, 2017
3c56c36
fix comment on `check_type_tests`
nikomatsakis Dec 19, 2017
3d826e5
remove dead `is_foo_free_region` helpers
nikomatsakis Dec 19, 2017
1816ede
be specific about what kind of normalization we mean
nikomatsakis Dec 19, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
permit ClosureOutlivesRequirement to constrain regions or types
  • Loading branch information
nikomatsakis committed Dec 15, 2017
commit 5804637a81a8e5216fbbf2e3e7c0a7bdca9c99de
21 changes: 18 additions & 3 deletions src/librustc/ich/impls_mir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -536,14 +536,29 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for mir::Literal<'gcx> {

impl_stable_hash_for!(struct mir::Location { block, statement_index });

impl_stable_hash_for!(struct mir::ClosureRegionRequirements {
impl_stable_hash_for!(struct mir::ClosureRegionRequirements<'tcx> {
num_external_vids,
outlives_requirements
});

impl_stable_hash_for!(struct mir::ClosureOutlivesRequirement {
free_region,
impl_stable_hash_for!(struct mir::ClosureOutlivesRequirement<'tcx> {
subject,
outlived_free_region,
blame_span
});

impl<'gcx> HashStable<StableHashingContext<'gcx>> for mir::ClosureOutlivesSubject<'gcx> {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'gcx>,
hasher: &mut StableHasher<W>) {
mem::discriminant(self).hash_stable(hcx, hasher);
match *self {
mir::ClosureOutlivesSubject::Ty(ref ty) => {
ty.hash_stable(hcx, hasher);
}
mir::ClosureOutlivesSubject::Region(ref region) => {
region.hash_stable(hcx, hasher);
}
}
}
}
33 changes: 25 additions & 8 deletions src/librustc/mir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1832,7 +1832,7 @@ pub struct GeneratorLayout<'tcx> {
/// can be extracted from its type and constrained to have the given
/// outlives relationship.
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct ClosureRegionRequirements {
pub struct ClosureRegionRequirements<'gcx> {
/// The number of external regions defined on the closure. In our
/// example above, it would be 3 -- one for `'static`, then `'1`
/// and `'2`. This is just used for a sanity check later on, to
Expand All @@ -1842,15 +1842,15 @@ pub struct ClosureRegionRequirements {

/// Requirements between the various free regions defined in
/// indices.
pub outlives_requirements: Vec<ClosureOutlivesRequirement>,
pub outlives_requirements: Vec<ClosureOutlivesRequirement<'gcx>>,
}

/// Indicates an outlives constraint between two free-regions declared
/// on the closure.
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
pub struct ClosureOutlivesRequirement {
// This region ...
pub free_region: ty::RegionVid,
/// Indicates an outlives constraint between a type or between two
/// free-regions declared on the closure.
#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct ClosureOutlivesRequirement<'tcx> {
// This region or type ...
pub subject: ClosureOutlivesSubject<'tcx>,

// .. must outlive this one.
pub outlived_free_region: ty::RegionVid,
Expand All @@ -1859,6 +1859,23 @@ pub struct ClosureOutlivesRequirement {
pub blame_span: Span,
}

/// The subject of a ClosureOutlivesRequirement -- that is, the thing
/// that must outlive some region.
#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
pub enum ClosureOutlivesSubject<'tcx> {
/// Subject is a type, typically a type parameter, but could also
/// be a projection. Indicates a requirement like `T: 'a` being
/// passed to the caller, where the type here is `T`.
///
/// The type here is guaranteed not to contain any free regions at
/// present.
Ty(Ty<'tcx>),

/// Subject is a free region from the closure. Indicates a requirement
/// like `'a: 'b` being passed to the caller; the region here is `'a`.
Region(ty::RegionVid),
}

/*
* TypeFoldable implementations for MIR types
*/
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/ty/maps/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ define_maps! { <'tcx>

/// Borrow checks the function body. If this is a closure, returns
/// additional requirements that the closure's creator must verify.
[] fn mir_borrowck: MirBorrowCheck(DefId) -> Option<mir::ClosureRegionRequirements>,
[] fn mir_borrowck: MirBorrowCheck(DefId) -> Option<mir::ClosureRegionRequirements<'tcx>>,

/// Gets a complete map from all types to their inherent impls.
/// Not meant to be used directly outside of coherence.
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_mir/borrow_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ pub fn provide(providers: &mut Providers) {
fn mir_borrowck<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
def_id: DefId,
) -> Option<ClosureRegionRequirements> {
) -> Option<ClosureRegionRequirements<'tcx>> {
let input_mir = tcx.mir_validated(def_id);
debug!("run query mir_borrowck: {}", tcx.item_path_str(def_id));

Expand All @@ -89,7 +89,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
infcx: &InferCtxt<'a, 'gcx, 'tcx>,
input_mir: &Mir<'gcx>,
def_id: DefId,
) -> Option<ClosureRegionRequirements> {
) -> Option<ClosureRegionRequirements<'gcx>> {
let tcx = infcx.tcx;
let attributes = tcx.get_attrs(def_id);
let param_env = tcx.param_env(def_id);
Expand Down
11 changes: 8 additions & 3 deletions src/librustc_mir/borrow_check/nll/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@
// except according to those terms.

use rustc::hir::def_id::DefId;
use rustc::mir::{ClosureRegionRequirements, Mir};
use rustc::mir::{ClosureRegionRequirements, ClosureOutlivesSubject, Mir};
use rustc::infer::InferCtxt;
use rustc::ty::{self, RegionKind, RegionVid};
use rustc::util::nodemap::FxHashMap;
use std::collections::BTreeSet;
use std::fmt::Debug;
use std::io;
use transform::MirSource;
use util::liveness::{LivenessResults, LocalSet};
Expand Down Expand Up @@ -73,7 +74,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
move_data: &MoveData<'tcx>,
) -> (
RegionInferenceContext<'tcx>,
Option<ClosureRegionRequirements>,
Option<ClosureRegionRequirements<'gcx>>,
) {
// Run the MIR type-checker.
let mir_node_id = infcx.tcx.hir.as_local_node_id(def_id).unwrap();
Expand Down Expand Up @@ -263,9 +264,13 @@ fn for_each_region_constraint(
with_msg: &mut FnMut(&str) -> io::Result<()>,
) -> io::Result<()> {
for req in &closure_region_requirements.outlives_requirements {
let subject: &Debug = match &req.subject {
ClosureOutlivesSubject::Region(subject) => subject,
ClosureOutlivesSubject::Ty(ty) => ty,
};
with_msg(&format!(
"where {:?}: {:?}",
req.free_region,
subject,
req.outlived_free_region,
))?;
}
Expand Down
63 changes: 42 additions & 21 deletions src/librustc_mir/borrow_check/nll/region_infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ use rustc::infer::NLLRegionVariableOrigin;
use rustc::infer::RegionVariableOrigin;
use rustc::infer::SubregionOrigin;
use rustc::infer::region_constraints::{GenericKind, VarOrigins};
use rustc::mir::{ClosureOutlivesRequirement, ClosureRegionRequirements, Location, Mir};
use rustc::mir::{ClosureOutlivesRequirement, ClosureOutlivesSubject, ClosureRegionRequirements,
Location, Mir};
use rustc::ty::{self, RegionVid};
use rustc_data_structures::indexed_vec::IndexVec;
use std::fmt;
Expand Down Expand Up @@ -339,12 +340,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// Perform region inference and report errors if we see any
/// unsatisfiable constraints. If this is a closure, returns the
/// region requirements to propagate to our creator, if any.
pub(super) fn solve(
pub(super) fn solve<'gcx>(
&mut self,
infcx: &InferCtxt<'_, '_, 'tcx>,
infcx: &InferCtxt<'_, 'gcx, 'tcx>,
mir: &Mir<'tcx>,
mir_def_id: DefId,
) -> Option<ClosureRegionRequirements> {
) -> Option<ClosureRegionRequirements<'gcx>> {
assert!(self.inferred_values.is_none(), "values already inferred");

self.propagate_constraints(mir);
Expand Down Expand Up @@ -559,10 +560,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// If `propagated_outlives_requirements` is `Some`, then we will
/// push unsatisfied obligations into there. Otherwise, we'll
/// report them as errors.
fn check_universal_regions(
fn check_universal_regions<'gcx>(
&self,
infcx: &InferCtxt<'_, '_, 'tcx>,
mut propagated_outlives_requirements: Option<&mut Vec<ClosureOutlivesRequirement>>,
infcx: &InferCtxt<'_, 'gcx, 'tcx>,
mut propagated_outlives_requirements: Option<&mut Vec<ClosureOutlivesRequirement<'gcx>>>,
) {
// The universal regions are always found in a prefix of the
// full list.
Expand All @@ -583,9 +584,17 @@ impl<'tcx> RegionInferenceContext<'tcx> {
propagated_outlives_requirements.extend(outlives_requirements.drain(..));
} else {
for outlives_requirement in outlives_requirements.drain(..) {
let fr = match outlives_requirement.subject {
ClosureOutlivesSubject::Region(fr) => fr,
_ => span_bug!(
outlives_requirement.blame_span,
"check_universal_region() produced requirement w/ non-region subject"
),
};

self.report_error(
infcx,
outlives_requirement.free_region,
fr,
outlives_requirement.outlived_free_region,
outlives_requirement.blame_span,
);
Expand All @@ -602,11 +611,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
///
/// Things that are to be propagated are accumulated into the
/// `outlives_requirements` vector.
fn check_universal_region(
fn check_universal_region<'gcx>(
&self,
infcx: &InferCtxt<'_, '_, 'tcx>,
infcx: &InferCtxt<'_, 'gcx, 'tcx>,
longer_fr: RegionVid,
propagated_outlives_requirements: &mut Vec<ClosureOutlivesRequirement>,
propagated_outlives_requirements: &mut Vec<ClosureOutlivesRequirement<'gcx>>,
) {
let inferred_values = self.inferred_values.as_ref().unwrap();

Expand Down Expand Up @@ -645,7 +654,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {

// Push the constraint `fr-: shorter_fr+`
propagated_outlives_requirements.push(ClosureOutlivesRequirement {
free_region: fr_minus,
subject: ClosureOutlivesSubject::Region(fr_minus),
outlived_free_region: shorter_fr_plus,
blame_span: blame_span,
});
Expand Down Expand Up @@ -773,7 +782,7 @@ pub trait ClosureRegionRequirementsExt {
);
}

impl ClosureRegionRequirementsExt for ClosureRegionRequirements {
impl<'gcx> ClosureRegionRequirementsExt for ClosureRegionRequirements<'gcx> {
/// Given an instance T of the closure type, this method
/// instantiates the "extra" requirements that we computed for the
/// closure into the inference context. This has the effect of
Expand Down Expand Up @@ -815,17 +824,29 @@ impl ClosureRegionRequirementsExt for ClosureRegionRequirements {

// Create the predicates.
for outlives_requirement in &self.outlives_requirements {
let region = closure_mapping[outlives_requirement.free_region];
let outlived_region = closure_mapping[outlives_requirement.outlived_free_region];
debug!(
"apply_requirements: region={:?} outlived_region={:?} outlives_requirements={:?}",
region,
outlived_region,
outlives_requirement
);

// FIXME, this origin is not entirely suitable.
let origin = SubregionOrigin::CallRcvr(outlives_requirement.blame_span);
infcx.sub_regions(origin, outlived_region, region);

match outlives_requirement.subject {
ClosureOutlivesSubject::Region(region) => {
let region = closure_mapping[region];
debug!(
"apply_requirements: region={:?} \
outlived_region={:?} \
outlives_requirements={:?}",
region,
outlived_region,
outlives_requirement
);
infcx.sub_regions(origin, outlived_region, region);
}

ClosureOutlivesSubject::Ty(_ty) => {
bug!("TODO not yet implemented -- closure outlives subject of a type");
}
}
}
}
}