simplify applying closure requirements
Don't use `ConstraintCategory::ClosureBounds`! Set the category and the span for the promoted constraints to that of the original constraint earlier than before. This eliminates the need for `closure_bounds_mapping`.
This commit is contained in:
parent
81ff7e7385
commit
df668b9fb9
9 changed files with 97 additions and 237 deletions
|
@ -163,6 +163,7 @@ impl<'s, 'tcx, D: ConstraintGraphDirecton> Iterator for Edges<'s, 'tcx, D> {
|
||||||
span: DUMMY_SP,
|
span: DUMMY_SP,
|
||||||
category: ConstraintCategory::Internal,
|
category: ConstraintCategory::Internal,
|
||||||
variance_info: VarianceDiagInfo::default(),
|
variance_info: VarianceDiagInfo::default(),
|
||||||
|
from_closure: false,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
|
|
@ -96,6 +96,9 @@ pub struct OutlivesConstraint<'tcx> {
|
||||||
|
|
||||||
/// Variance diagnostic information
|
/// Variance diagnostic information
|
||||||
pub variance_info: VarianceDiagInfo<'tcx>,
|
pub variance_info: VarianceDiagInfo<'tcx>,
|
||||||
|
|
||||||
|
/// If this constraint is promoted from closure requirements.
|
||||||
|
pub from_closure: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> fmt::Debug for OutlivesConstraint<'tcx> {
|
impl<'tcx> fmt::Debug for OutlivesConstraint<'tcx> {
|
||||||
|
|
|
@ -242,7 +242,6 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
|
||||||
mut liveness_constraints,
|
mut liveness_constraints,
|
||||||
outlives_constraints,
|
outlives_constraints,
|
||||||
member_constraints,
|
member_constraints,
|
||||||
closure_bounds_mapping,
|
|
||||||
universe_causes,
|
universe_causes,
|
||||||
type_tests,
|
type_tests,
|
||||||
} = constraints;
|
} = constraints;
|
||||||
|
@ -264,7 +263,6 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
|
||||||
universal_region_relations,
|
universal_region_relations,
|
||||||
outlives_constraints,
|
outlives_constraints,
|
||||||
member_constraints,
|
member_constraints,
|
||||||
closure_bounds_mapping,
|
|
||||||
universe_causes,
|
universe_causes,
|
||||||
type_tests,
|
type_tests,
|
||||||
liveness_constraints,
|
liveness_constraints,
|
||||||
|
|
|
@ -74,8 +74,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
let mut constraints: Vec<_> = self.constraints.outlives().iter().collect();
|
let mut constraints: Vec<_> = self.constraints.outlives().iter().collect();
|
||||||
constraints.sort_by_key(|c| (c.sup, c.sub));
|
constraints.sort_by_key(|c| (c.sup, c.sub));
|
||||||
for constraint in &constraints {
|
for constraint in &constraints {
|
||||||
let OutlivesConstraint { sup, sub, locations, category, span, variance_info: _ } =
|
let OutlivesConstraint { sup, sub, locations, category, span, .. } = constraint;
|
||||||
constraint;
|
|
||||||
let (name, arg) = match locations {
|
let (name, arg) = match locations {
|
||||||
Locations::All(span) => {
|
Locations::All(span) => {
|
||||||
("All", tcx.sess.source_map().span_to_embeddable_string(*span))
|
("All", tcx.sess.source_map().span_to_embeddable_string(*span))
|
||||||
|
|
|
@ -6,10 +6,9 @@ use rustc_data_structures::frozen::Frozen;
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||||
use rustc_data_structures::graph::scc::Sccs;
|
use rustc_data_structures::graph::scc::Sccs;
|
||||||
use rustc_errors::Diagnostic;
|
use rustc_errors::Diagnostic;
|
||||||
use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
|
use rustc_hir::def_id::CRATE_DEF_ID;
|
||||||
use rustc_hir::CRATE_HIR_ID;
|
use rustc_hir::CRATE_HIR_ID;
|
||||||
use rustc_index::vec::IndexVec;
|
use rustc_index::vec::IndexVec;
|
||||||
use rustc_infer::infer::canonical::QueryOutlivesConstraint;
|
|
||||||
use rustc_infer::infer::outlives::test_type_match;
|
use rustc_infer::infer::outlives::test_type_match;
|
||||||
use rustc_infer::infer::region_constraints::{GenericKind, VarInfos, VerifyBound, VerifyIfEq};
|
use rustc_infer::infer::region_constraints::{GenericKind, VarInfos, VerifyBound, VerifyIfEq};
|
||||||
use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin};
|
use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin};
|
||||||
|
@ -19,9 +18,7 @@ use rustc_middle::mir::{
|
||||||
};
|
};
|
||||||
use rustc_middle::traits::ObligationCause;
|
use rustc_middle::traits::ObligationCause;
|
||||||
use rustc_middle::traits::ObligationCauseCode;
|
use rustc_middle::traits::ObligationCauseCode;
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitable};
|
||||||
self, subst::SubstsRef, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitable,
|
|
||||||
};
|
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -89,10 +86,6 @@ pub struct RegionInferenceContext<'tcx> {
|
||||||
/// `member_region_scc`.
|
/// `member_region_scc`.
|
||||||
member_constraints_applied: Vec<AppliedMemberConstraint>,
|
member_constraints_applied: Vec<AppliedMemberConstraint>,
|
||||||
|
|
||||||
/// Map closure bounds to a `Span` that should be used for error reporting.
|
|
||||||
closure_bounds_mapping:
|
|
||||||
FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory<'tcx>, Span)>>,
|
|
||||||
|
|
||||||
/// Map universe indexes to information on why we created it.
|
/// Map universe indexes to information on why we created it.
|
||||||
universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
|
universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
|
||||||
|
|
||||||
|
@ -265,10 +258,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
|
universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
|
||||||
outlives_constraints: OutlivesConstraintSet<'tcx>,
|
outlives_constraints: OutlivesConstraintSet<'tcx>,
|
||||||
member_constraints_in: MemberConstraintSet<'tcx, RegionVid>,
|
member_constraints_in: MemberConstraintSet<'tcx, RegionVid>,
|
||||||
closure_bounds_mapping: FxHashMap<
|
|
||||||
Location,
|
|
||||||
FxHashMap<(RegionVid, RegionVid), (ConstraintCategory<'tcx>, Span)>,
|
|
||||||
>,
|
|
||||||
universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
|
universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
|
||||||
type_tests: Vec<TypeTest<'tcx>>,
|
type_tests: Vec<TypeTest<'tcx>>,
|
||||||
liveness_constraints: LivenessValues<RegionVid>,
|
liveness_constraints: LivenessValues<RegionVid>,
|
||||||
|
@ -310,7 +299,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
rev_scc_graph: None,
|
rev_scc_graph: None,
|
||||||
member_constraints,
|
member_constraints,
|
||||||
member_constraints_applied: Vec::new(),
|
member_constraints_applied: Vec::new(),
|
||||||
closure_bounds_mapping,
|
|
||||||
universe_causes,
|
universe_causes,
|
||||||
scc_universes,
|
scc_universes,
|
||||||
scc_representatives,
|
scc_representatives,
|
||||||
|
@ -1804,18 +1792,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn retrieve_closure_constraint_info(
|
|
||||||
&self,
|
|
||||||
constraint: OutlivesConstraint<'tcx>,
|
|
||||||
) -> Option<(ConstraintCategory<'tcx>, Span)> {
|
|
||||||
match constraint.locations {
|
|
||||||
Locations::All(_) => None,
|
|
||||||
Locations::Single(loc) => {
|
|
||||||
self.closure_bounds_mapping[&loc].get(&(constraint.sup, constraint.sub)).copied()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Finds a good `ObligationCause` to blame for the fact that `fr1` outlives `fr2`.
|
/// Finds a good `ObligationCause` to blame for the fact that `fr1` outlives `fr2`.
|
||||||
pub(crate) fn find_outlives_blame_span(
|
pub(crate) fn find_outlives_blame_span(
|
||||||
&self,
|
&self,
|
||||||
|
@ -1921,6 +1897,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
span: p_c.definition_span,
|
span: p_c.definition_span,
|
||||||
category: ConstraintCategory::OpaqueType,
|
category: ConstraintCategory::OpaqueType,
|
||||||
variance_info: ty::VarianceDiagInfo::default(),
|
variance_info: ty::VarianceDiagInfo::default(),
|
||||||
|
from_closure: false,
|
||||||
};
|
};
|
||||||
handle_constraint(constraint);
|
handle_constraint(constraint);
|
||||||
}
|
}
|
||||||
|
@ -2066,31 +2043,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
// Classify each of the constraints along the path.
|
// Classify each of the constraints along the path.
|
||||||
let mut categorized_path: Vec<BlameConstraint<'tcx>> = path
|
let mut categorized_path: Vec<BlameConstraint<'tcx>> = path
|
||||||
.iter()
|
.iter()
|
||||||
.map(|constraint| {
|
.map(|constraint| BlameConstraint {
|
||||||
let (category, span, from_closure, cause_code) =
|
category: constraint.category,
|
||||||
if constraint.category == ConstraintCategory::ClosureBounds {
|
from_closure: constraint.from_closure,
|
||||||
if let Some((category, span)) =
|
cause: ObligationCause::new(constraint.span, CRATE_HIR_ID, cause_code.clone()),
|
||||||
self.retrieve_closure_constraint_info(*constraint)
|
|
||||||
{
|
|
||||||
(category, span, true, ObligationCauseCode::MiscObligation)
|
|
||||||
} else {
|
|
||||||
(
|
|
||||||
constraint.category,
|
|
||||||
constraint.span,
|
|
||||||
false,
|
|
||||||
ObligationCauseCode::MiscObligation,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
(constraint.category, constraint.span, false, cause_code.clone())
|
|
||||||
};
|
|
||||||
BlameConstraint {
|
|
||||||
category,
|
|
||||||
from_closure,
|
|
||||||
cause: ObligationCause::new(span, CRATE_HIR_ID, cause_code),
|
|
||||||
variance_info: constraint.variance_info,
|
variance_info: constraint.variance_info,
|
||||||
outlives_constraint: *constraint,
|
outlives_constraint: *constraint,
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
debug!("categorized_path={:#?}", categorized_path);
|
debug!("categorized_path={:#?}", categorized_path);
|
||||||
|
@ -2274,92 +2232,6 @@ impl<'tcx> RegionDefinition<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ClosureRegionRequirementsExt<'tcx> {
|
|
||||||
fn apply_requirements(
|
|
||||||
&self,
|
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
closure_def_id: DefId,
|
|
||||||
closure_substs: SubstsRef<'tcx>,
|
|
||||||
) -> Vec<QueryOutlivesConstraint<'tcx>>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> ClosureRegionRequirementsExt<'tcx> for ClosureRegionRequirements<'tcx> {
|
|
||||||
/// 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
|
|
||||||
/// adding new outlives obligations to existing variables.
|
|
||||||
///
|
|
||||||
/// As described on `ClosureRegionRequirements`, the extra
|
|
||||||
/// requirements are expressed in terms of regionvids that index
|
|
||||||
/// into the free regions that appear on the closure type. So, to
|
|
||||||
/// do this, we first copy those regions out from the type T into
|
|
||||||
/// a vector. Then we can just index into that vector to extract
|
|
||||||
/// out the corresponding region from T and apply the
|
|
||||||
/// requirements.
|
|
||||||
fn apply_requirements(
|
|
||||||
&self,
|
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
closure_def_id: DefId,
|
|
||||||
closure_substs: SubstsRef<'tcx>,
|
|
||||||
) -> Vec<QueryOutlivesConstraint<'tcx>> {
|
|
||||||
debug!(
|
|
||||||
"apply_requirements(closure_def_id={:?}, closure_substs={:?})",
|
|
||||||
closure_def_id, closure_substs
|
|
||||||
);
|
|
||||||
|
|
||||||
// Extract the values of the free regions in `closure_substs`
|
|
||||||
// into a vector. These are the regions that we will be
|
|
||||||
// relating to one another.
|
|
||||||
let closure_mapping = &UniversalRegions::closure_mapping(
|
|
||||||
tcx,
|
|
||||||
closure_substs,
|
|
||||||
self.num_external_vids,
|
|
||||||
closure_def_id.expect_local(),
|
|
||||||
);
|
|
||||||
debug!("apply_requirements: closure_mapping={:?}", closure_mapping);
|
|
||||||
|
|
||||||
// Create the predicates.
|
|
||||||
self.outlives_requirements
|
|
||||||
.iter()
|
|
||||||
.map(|outlives_requirement| {
|
|
||||||
let outlived_region = closure_mapping[outlives_requirement.outlived_free_region];
|
|
||||||
|
|
||||||
match outlives_requirement.subject {
|
|
||||||
ClosureOutlivesSubject::Region(region) => {
|
|
||||||
let region = closure_mapping[region];
|
|
||||||
debug!(
|
|
||||||
"apply_requirements: region={:?} \
|
|
||||||
outlived_region={:?} \
|
|
||||||
outlives_requirement={:?}",
|
|
||||||
region, outlived_region, outlives_requirement,
|
|
||||||
);
|
|
||||||
(
|
|
||||||
ty::Binder::dummy(ty::OutlivesPredicate(
|
|
||||||
region.into(),
|
|
||||||
outlived_region,
|
|
||||||
)),
|
|
||||||
ConstraintCategory::BoringNoLocation,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
ClosureOutlivesSubject::Ty(ty) => {
|
|
||||||
debug!(
|
|
||||||
"apply_requirements: ty={:?} \
|
|
||||||
outlived_region={:?} \
|
|
||||||
outlives_requirement={:?}",
|
|
||||||
ty, outlived_region, outlives_requirement,
|
|
||||||
);
|
|
||||||
(
|
|
||||||
ty::Binder::dummy(ty::OutlivesPredicate(ty.into(), outlived_region)),
|
|
||||||
ConstraintCategory::BoringNoLocation,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct BlameConstraint<'tcx> {
|
pub struct BlameConstraint<'tcx> {
|
||||||
pub category: ConstraintCategory<'tcx>,
|
pub category: ConstraintCategory<'tcx>,
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
use rustc_infer::infer::canonical::QueryOutlivesConstraint;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_infer::infer::canonical::QueryRegionConstraints;
|
use rustc_infer::infer::canonical::QueryRegionConstraints;
|
||||||
use rustc_infer::infer::outlives::env::RegionBoundPairs;
|
use rustc_infer::infer::outlives::env::RegionBoundPairs;
|
||||||
use rustc_infer::infer::outlives::obligations::{TypeOutlives, TypeOutlivesDelegate};
|
use rustc_infer::infer::outlives::obligations::{TypeOutlives, TypeOutlivesDelegate};
|
||||||
use rustc_infer::infer::region_constraints::{GenericKind, VerifyBound};
|
use rustc_infer::infer::region_constraints::{GenericKind, VerifyBound};
|
||||||
use rustc_infer::infer::{self, InferCtxt, SubregionOrigin};
|
use rustc_infer::infer::{self, InferCtxt, SubregionOrigin};
|
||||||
use rustc_middle::mir::ConstraintCategory;
|
use rustc_middle::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, ConstraintCategory};
|
||||||
use rustc_middle::ty::subst::GenericArgKind;
|
use rustc_middle::ty::subst::GenericArgKind;
|
||||||
use rustc_middle::ty::TypeFoldable;
|
use rustc_middle::ty::TypeFoldable;
|
||||||
use rustc_middle::ty::{self, TyCtxt};
|
use rustc_middle::ty::{self, TyCtxt};
|
||||||
|
@ -38,6 +38,7 @@ pub(crate) struct ConstraintConversion<'a, 'tcx> {
|
||||||
locations: Locations,
|
locations: Locations,
|
||||||
span: Span,
|
span: Span,
|
||||||
category: ConstraintCategory<'tcx>,
|
category: ConstraintCategory<'tcx>,
|
||||||
|
from_closure: bool,
|
||||||
constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
|
constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,6 +65,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
|
||||||
span,
|
span,
|
||||||
category,
|
category,
|
||||||
constraints,
|
constraints,
|
||||||
|
from_closure: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,12 +83,62 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
self.constraints.member_constraints = tmp;
|
self.constraints.member_constraints = tmp;
|
||||||
|
|
||||||
for query_constraint in outlives {
|
for (predicate, constraint_category) in outlives {
|
||||||
self.convert(query_constraint);
|
// At the moment, we never generate any "higher-ranked"
|
||||||
|
// region constraints like `for<'a> 'a: 'b`. At some point
|
||||||
|
// when we move to universes, we will, and this assertion
|
||||||
|
// will start to fail.
|
||||||
|
let predicate = predicate.no_bound_vars().unwrap_or_else(|| {
|
||||||
|
bug!("query_constraint {:?} contained bound vars", predicate,);
|
||||||
|
});
|
||||||
|
|
||||||
|
self.convert(predicate, *constraint_category);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn convert(&mut self, query_constraint: &QueryOutlivesConstraint<'tcx>) {
|
/// Given an instance of the closure type, this method instantiates the "extra" requirements
|
||||||
|
/// that we computed for the closure. This has the effect of adding new outlives obligations
|
||||||
|
/// to existing region variables in `closure_substs`.
|
||||||
|
#[instrument(skip(self), level = "debug")]
|
||||||
|
pub fn apply_closure_requirements(
|
||||||
|
&mut self,
|
||||||
|
closure_requirements: &ClosureRegionRequirements<'tcx>,
|
||||||
|
closure_def_id: DefId,
|
||||||
|
closure_substs: ty::SubstsRef<'tcx>,
|
||||||
|
) {
|
||||||
|
// Extract the values of the free regions in `closure_substs`
|
||||||
|
// into a vector. These are the regions that we will be
|
||||||
|
// relating to one another.
|
||||||
|
let closure_mapping = &UniversalRegions::closure_mapping(
|
||||||
|
self.tcx,
|
||||||
|
closure_substs,
|
||||||
|
closure_requirements.num_external_vids,
|
||||||
|
closure_def_id.expect_local(),
|
||||||
|
);
|
||||||
|
debug!(?closure_mapping);
|
||||||
|
|
||||||
|
// Create the predicates.
|
||||||
|
let backup = (self.category, self.span, self.from_closure);
|
||||||
|
self.from_closure = true;
|
||||||
|
for outlives_requirement in &closure_requirements.outlives_requirements {
|
||||||
|
let outlived_region = closure_mapping[outlives_requirement.outlived_free_region];
|
||||||
|
let subject = match outlives_requirement.subject {
|
||||||
|
ClosureOutlivesSubject::Region(re) => closure_mapping[re].into(),
|
||||||
|
ClosureOutlivesSubject::Ty(ty) => ty.into(),
|
||||||
|
};
|
||||||
|
|
||||||
|
self.category = outlives_requirement.category;
|
||||||
|
self.span = outlives_requirement.blame_span;
|
||||||
|
self.convert(ty::OutlivesPredicate(subject, outlived_region), self.category);
|
||||||
|
}
|
||||||
|
(self.category, self.span, self.from_closure) = backup;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn convert(
|
||||||
|
&mut self,
|
||||||
|
predicate: ty::OutlivesPredicate<ty::GenericArg<'tcx>, ty::Region<'tcx>>,
|
||||||
|
constraint_category: ConstraintCategory<'tcx>,
|
||||||
|
) {
|
||||||
debug!("generate: constraints at: {:#?}", self.locations);
|
debug!("generate: constraints at: {:#?}", self.locations);
|
||||||
|
|
||||||
// Extract out various useful fields we'll need below.
|
// Extract out various useful fields we'll need below.
|
||||||
|
@ -94,17 +146,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
|
||||||
tcx, region_bound_pairs, implicit_region_bound, param_env, ..
|
tcx, region_bound_pairs, implicit_region_bound, param_env, ..
|
||||||
} = *self;
|
} = *self;
|
||||||
|
|
||||||
// At the moment, we never generate any "higher-ranked"
|
let ty::OutlivesPredicate(k1, r2) = predicate;
|
||||||
// region constraints like `for<'a> 'a: 'b`. At some point
|
|
||||||
// when we move to universes, we will, and this assertion
|
|
||||||
// will start to fail.
|
|
||||||
let ty::OutlivesPredicate(k1, r2) =
|
|
||||||
query_constraint.0.no_bound_vars().unwrap_or_else(|| {
|
|
||||||
bug!("query_constraint {:?} contained bound vars", query_constraint,);
|
|
||||||
});
|
|
||||||
|
|
||||||
let constraint_category = query_constraint.1;
|
|
||||||
|
|
||||||
match k1.unpack() {
|
match k1.unpack() {
|
||||||
GenericArgKind::Lifetime(r1) => {
|
GenericArgKind::Lifetime(r1) => {
|
||||||
let r1_vid = self.to_region_vid(r1);
|
let r1_vid = self.to_region_vid(r1);
|
||||||
|
@ -188,6 +230,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
|
||||||
sub,
|
sub,
|
||||||
sup,
|
sup,
|
||||||
variance_info: ty::VarianceDiagInfo::default(),
|
variance_info: ty::VarianceDiagInfo::default(),
|
||||||
|
from_closure: self.from_closure,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ use rustc_middle::mir::AssertKind;
|
||||||
use rustc_middle::mir::*;
|
use rustc_middle::mir::*;
|
||||||
use rustc_middle::ty::adjustment::PointerCast;
|
use rustc_middle::ty::adjustment::PointerCast;
|
||||||
use rustc_middle::ty::cast::CastTy;
|
use rustc_middle::ty::cast::CastTy;
|
||||||
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef, UserSubsts};
|
use rustc_middle::ty::subst::{SubstsRef, UserSubsts};
|
||||||
use rustc_middle::ty::visit::TypeVisitable;
|
use rustc_middle::ty::visit::TypeVisitable;
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
self, Binder, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, Dynamic,
|
self, Binder, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, Dynamic,
|
||||||
|
@ -61,7 +61,7 @@ use crate::{
|
||||||
region_infer::values::{
|
region_infer::values::{
|
||||||
LivenessValues, PlaceholderIndex, PlaceholderIndices, RegionValueElements,
|
LivenessValues, PlaceholderIndex, PlaceholderIndices, RegionValueElements,
|
||||||
},
|
},
|
||||||
region_infer::{ClosureRegionRequirementsExt, TypeTest},
|
region_infer::TypeTest,
|
||||||
type_check::free_region_relations::{CreateResult, UniversalRegionRelations},
|
type_check::free_region_relations::{CreateResult, UniversalRegionRelations},
|
||||||
universal_regions::{DefiningTy, UniversalRegions},
|
universal_regions::{DefiningTy, UniversalRegions},
|
||||||
Upvar,
|
Upvar,
|
||||||
|
@ -144,7 +144,6 @@ pub(crate) fn type_check<'mir, 'tcx>(
|
||||||
liveness_constraints: LivenessValues::new(elements.clone()),
|
liveness_constraints: LivenessValues::new(elements.clone()),
|
||||||
outlives_constraints: OutlivesConstraintSet::default(),
|
outlives_constraints: OutlivesConstraintSet::default(),
|
||||||
member_constraints: MemberConstraintSet::default(),
|
member_constraints: MemberConstraintSet::default(),
|
||||||
closure_bounds_mapping: Default::default(),
|
|
||||||
type_tests: Vec::default(),
|
type_tests: Vec::default(),
|
||||||
universe_causes: FxHashMap::default(),
|
universe_causes: FxHashMap::default(),
|
||||||
};
|
};
|
||||||
|
@ -585,7 +584,6 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
|
||||||
let all_facts = &mut None;
|
let all_facts = &mut None;
|
||||||
let mut constraints = Default::default();
|
let mut constraints = Default::default();
|
||||||
let mut type_tests = Default::default();
|
let mut type_tests = Default::default();
|
||||||
let mut closure_bounds = Default::default();
|
|
||||||
let mut liveness_constraints =
|
let mut liveness_constraints =
|
||||||
LivenessValues::new(Rc::new(RegionValueElements::new(&promoted_body)));
|
LivenessValues::new(Rc::new(RegionValueElements::new(&promoted_body)));
|
||||||
// Don't try to add borrow_region facts for the promoted MIR
|
// Don't try to add borrow_region facts for the promoted MIR
|
||||||
|
@ -597,10 +595,6 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
|
||||||
&mut constraints,
|
&mut constraints,
|
||||||
);
|
);
|
||||||
mem::swap(&mut this.cx.borrowck_context.constraints.type_tests, &mut type_tests);
|
mem::swap(&mut this.cx.borrowck_context.constraints.type_tests, &mut type_tests);
|
||||||
mem::swap(
|
|
||||||
&mut this.cx.borrowck_context.constraints.closure_bounds_mapping,
|
|
||||||
&mut closure_bounds,
|
|
||||||
);
|
|
||||||
mem::swap(
|
mem::swap(
|
||||||
&mut this.cx.borrowck_context.constraints.liveness_constraints,
|
&mut this.cx.borrowck_context.constraints.liveness_constraints,
|
||||||
&mut liveness_constraints,
|
&mut liveness_constraints,
|
||||||
|
@ -653,18 +647,6 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
|
||||||
.add_element(region, location);
|
.add_element(region, location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !closure_bounds.is_empty() {
|
|
||||||
let combined_bounds_mapping =
|
|
||||||
closure_bounds.into_iter().flat_map(|(_, value)| value).collect();
|
|
||||||
let existing = self
|
|
||||||
.cx
|
|
||||||
.borrowck_context
|
|
||||||
.constraints
|
|
||||||
.closure_bounds_mapping
|
|
||||||
.insert(location, combined_bounds_mapping);
|
|
||||||
assert!(existing.is_none(), "Multiple promoteds/closures at the same location.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sanitize_projection(
|
fn sanitize_projection(
|
||||||
|
@ -941,9 +923,6 @@ pub(crate) struct MirTypeckRegionConstraints<'tcx> {
|
||||||
|
|
||||||
pub(crate) member_constraints: MemberConstraintSet<'tcx, RegionVid>,
|
pub(crate) member_constraints: MemberConstraintSet<'tcx, RegionVid>,
|
||||||
|
|
||||||
pub(crate) closure_bounds_mapping:
|
|
||||||
FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory<'tcx>, Span)>>,
|
|
||||||
|
|
||||||
pub(crate) universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
|
pub(crate) universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
|
||||||
|
|
||||||
pub(crate) type_tests: Vec<TypeTest<'tcx>>,
|
pub(crate) type_tests: Vec<TypeTest<'tcx>>,
|
||||||
|
@ -2562,6 +2541,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
span: location.to_locations().span(body),
|
span: location.to_locations().span(body),
|
||||||
category,
|
category,
|
||||||
variance_info: ty::VarianceDiagInfo::default(),
|
variance_info: ty::VarianceDiagInfo::default(),
|
||||||
|
from_closure: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
match mutbl {
|
match mutbl {
|
||||||
|
@ -2679,62 +2659,22 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
substs: SubstsRef<'tcx>,
|
substs: SubstsRef<'tcx>,
|
||||||
location: Location,
|
location: Location,
|
||||||
) -> ty::InstantiatedPredicates<'tcx> {
|
) -> ty::InstantiatedPredicates<'tcx> {
|
||||||
if let Some(ref closure_region_requirements) = tcx.mir_borrowck(def_id).closure_requirements
|
if let Some(ref closure_requirements) = tcx.mir_borrowck(def_id).closure_requirements {
|
||||||
{
|
constraint_conversion::ConstraintConversion::new(
|
||||||
let closure_constraints = QueryRegionConstraints {
|
self.infcx,
|
||||||
outlives: closure_region_requirements.apply_requirements(
|
self.borrowck_context.universal_regions,
|
||||||
tcx,
|
self.region_bound_pairs,
|
||||||
|
self.implicit_region_bound,
|
||||||
|
self.param_env,
|
||||||
|
location.to_locations(),
|
||||||
|
DUMMY_SP, // irrelevant; will be overrided.
|
||||||
|
ConstraintCategory::Boring, // same as above.
|
||||||
|
&mut self.borrowck_context.constraints,
|
||||||
|
)
|
||||||
|
.apply_closure_requirements(
|
||||||
|
&closure_requirements,
|
||||||
def_id.to_def_id(),
|
def_id.to_def_id(),
|
||||||
substs,
|
substs,
|
||||||
),
|
|
||||||
|
|
||||||
// Presently, closures never propagate member
|
|
||||||
// constraints to their parents -- they are enforced
|
|
||||||
// locally. This is largely a non-issue as member
|
|
||||||
// constraints only come from `-> impl Trait` and
|
|
||||||
// friends which don't appear (thus far...) in
|
|
||||||
// closures.
|
|
||||||
member_constraints: vec![],
|
|
||||||
};
|
|
||||||
|
|
||||||
let bounds_mapping = closure_constraints
|
|
||||||
.outlives
|
|
||||||
.iter()
|
|
||||||
.enumerate()
|
|
||||||
.filter_map(|(idx, constraint)| {
|
|
||||||
let ty::OutlivesPredicate(k1, r2) =
|
|
||||||
constraint.0.no_bound_vars().unwrap_or_else(|| {
|
|
||||||
bug!("query_constraint {:?} contained bound vars", constraint,);
|
|
||||||
});
|
|
||||||
|
|
||||||
match k1.unpack() {
|
|
||||||
GenericArgKind::Lifetime(r1) => {
|
|
||||||
// constraint is r1: r2
|
|
||||||
let r1_vid = self.borrowck_context.universal_regions.to_region_vid(r1);
|
|
||||||
let r2_vid = self.borrowck_context.universal_regions.to_region_vid(r2);
|
|
||||||
let outlives_requirements =
|
|
||||||
&closure_region_requirements.outlives_requirements[idx];
|
|
||||||
Some((
|
|
||||||
(r1_vid, r2_vid),
|
|
||||||
(outlives_requirements.category, outlives_requirements.blame_span),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
GenericArgKind::Type(_) | GenericArgKind::Const(_) => None,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let existing = self
|
|
||||||
.borrowck_context
|
|
||||||
.constraints
|
|
||||||
.closure_bounds_mapping
|
|
||||||
.insert(location, bounds_mapping);
|
|
||||||
assert!(existing.is_none(), "Multiple closures at the same location.");
|
|
||||||
|
|
||||||
self.push_region_constraints(
|
|
||||||
location.to_locations(),
|
|
||||||
ConstraintCategory::ClosureBounds,
|
|
||||||
&closure_constraints,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -136,6 +136,7 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx>
|
||||||
span: self.locations.span(self.type_checker.body),
|
span: self.locations.span(self.type_checker.body),
|
||||||
category: self.category,
|
category: self.category,
|
||||||
variance_info: info,
|
variance_info: info,
|
||||||
|
from_closure: false,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -167,7 +167,7 @@ LL | | T: Anything<'b, 'b>,
|
||||||
= note: defining type: two_regions::<'_#1r, T>
|
= note: defining type: two_regions::<'_#1r, T>
|
||||||
|
|
||||||
error: lifetime may not live long enough
|
error: lifetime may not live long enough
|
||||||
--> $DIR/projection-two-region-trait-bound-closure.rs:87:29
|
--> $DIR/projection-two-region-trait-bound-closure.rs:87:5
|
||||||
|
|
|
|
||||||
LL | fn two_regions<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
|
LL | fn two_regions<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
|
||||||
| -- -- lifetime `'b` defined here
|
| -- -- lifetime `'b` defined here
|
||||||
|
@ -175,9 +175,12 @@ LL | fn two_regions<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
|
||||||
| lifetime `'a` defined here
|
| lifetime `'a` defined here
|
||||||
...
|
...
|
||||||
LL | with_signature(cell, t, |cell, t| require(cell, t));
|
LL | with_signature(cell, t, |cell, t| require(cell, t));
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ closure body requires that `'b` must outlive `'a`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a`
|
||||||
|
|
|
|
||||||
= help: consider adding the following bound: `'b: 'a`
|
= help: consider adding the following bound: `'b: 'a`
|
||||||
|
= note: requirement occurs because of the type `Cell<&'_#8r ()>`, which makes the generic argument `&'_#8r ()` invariant
|
||||||
|
= note: the struct `Cell<T>` is invariant over the parameter `T`
|
||||||
|
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
|
||||||
|
|
||||||
note: external requirements
|
note: external requirements
|
||||||
--> $DIR/projection-two-region-trait-bound-closure.rs:97:29
|
--> $DIR/projection-two-region-trait-bound-closure.rs:97:29
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue