Skip to content

Commit df668b9

Browse files
committed
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`.
1 parent 81ff7e7 commit df668b9

File tree

9 files changed

+97
-237
lines changed

9 files changed

+97
-237
lines changed

compiler/rustc_borrowck/src/constraints/graph.rs

+1
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ impl<'s, 'tcx, D: ConstraintGraphDirecton> Iterator for Edges<'s, 'tcx, D> {
163163
span: DUMMY_SP,
164164
category: ConstraintCategory::Internal,
165165
variance_info: VarianceDiagInfo::default(),
166+
from_closure: false,
166167
})
167168
} else {
168169
None

compiler/rustc_borrowck/src/constraints/mod.rs

+3
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,9 @@ pub struct OutlivesConstraint<'tcx> {
9696

9797
/// Variance diagnostic information
9898
pub variance_info: VarianceDiagInfo<'tcx>,
99+
100+
/// If this constraint is promoted from closure requirements.
101+
pub from_closure: bool,
99102
}
100103

101104
impl<'tcx> fmt::Debug for OutlivesConstraint<'tcx> {

compiler/rustc_borrowck/src/nll.rs

-2
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,6 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
242242
mut liveness_constraints,
243243
outlives_constraints,
244244
member_constraints,
245-
closure_bounds_mapping,
246245
universe_causes,
247246
type_tests,
248247
} = constraints;
@@ -264,7 +263,6 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
264263
universal_region_relations,
265264
outlives_constraints,
266265
member_constraints,
267-
closure_bounds_mapping,
268266
universe_causes,
269267
type_tests,
270268
liveness_constraints,

compiler/rustc_borrowck/src/region_infer/dump_mir.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
7474
let mut constraints: Vec<_> = self.constraints.outlives().iter().collect();
7575
constraints.sort_by_key(|c| (c.sup, c.sub));
7676
for constraint in &constraints {
77-
let OutlivesConstraint { sup, sub, locations, category, span, variance_info: _ } =
78-
constraint;
77+
let OutlivesConstraint { sup, sub, locations, category, span, .. } = constraint;
7978
let (name, arg) = match locations {
8079
Locations::All(span) => {
8180
("All", tcx.sess.source_map().span_to_embeddable_string(*span))

compiler/rustc_borrowck/src/region_infer/mod.rs

+9-137
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,9 @@ use rustc_data_structures::frozen::Frozen;
66
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
77
use rustc_data_structures::graph::scc::Sccs;
88
use rustc_errors::Diagnostic;
9-
use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
9+
use rustc_hir::def_id::CRATE_DEF_ID;
1010
use rustc_hir::CRATE_HIR_ID;
1111
use rustc_index::vec::IndexVec;
12-
use rustc_infer::infer::canonical::QueryOutlivesConstraint;
1312
use rustc_infer::infer::outlives::test_type_match;
1413
use rustc_infer::infer::region_constraints::{GenericKind, VarInfos, VerifyBound, VerifyIfEq};
1514
use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin};
@@ -19,9 +18,7 @@ use rustc_middle::mir::{
1918
};
2019
use rustc_middle::traits::ObligationCause;
2120
use rustc_middle::traits::ObligationCauseCode;
22-
use rustc_middle::ty::{
23-
self, subst::SubstsRef, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitable,
24-
};
21+
use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitable};
2522
use rustc_span::Span;
2623

2724
use crate::{
@@ -89,10 +86,6 @@ pub struct RegionInferenceContext<'tcx> {
8986
/// `member_region_scc`.
9087
member_constraints_applied: Vec<AppliedMemberConstraint>,
9188

92-
/// Map closure bounds to a `Span` that should be used for error reporting.
93-
closure_bounds_mapping:
94-
FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory<'tcx>, Span)>>,
95-
9689
/// Map universe indexes to information on why we created it.
9790
universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
9891

@@ -265,10 +258,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
265258
universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
266259
outlives_constraints: OutlivesConstraintSet<'tcx>,
267260
member_constraints_in: MemberConstraintSet<'tcx, RegionVid>,
268-
closure_bounds_mapping: FxHashMap<
269-
Location,
270-
FxHashMap<(RegionVid, RegionVid), (ConstraintCategory<'tcx>, Span)>,
271-
>,
272261
universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
273262
type_tests: Vec<TypeTest<'tcx>>,
274263
liveness_constraints: LivenessValues<RegionVid>,
@@ -310,7 +299,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
310299
rev_scc_graph: None,
311300
member_constraints,
312301
member_constraints_applied: Vec::new(),
313-
closure_bounds_mapping,
314302
universe_causes,
315303
scc_universes,
316304
scc_representatives,
@@ -1804,18 +1792,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
18041792
}
18051793
}
18061794

1807-
pub(crate) fn retrieve_closure_constraint_info(
1808-
&self,
1809-
constraint: OutlivesConstraint<'tcx>,
1810-
) -> Option<(ConstraintCategory<'tcx>, Span)> {
1811-
match constraint.locations {
1812-
Locations::All(_) => None,
1813-
Locations::Single(loc) => {
1814-
self.closure_bounds_mapping[&loc].get(&(constraint.sup, constraint.sub)).copied()
1815-
}
1816-
}
1817-
}
1818-
18191795
/// Finds a good `ObligationCause` to blame for the fact that `fr1` outlives `fr2`.
18201796
pub(crate) fn find_outlives_blame_span(
18211797
&self,
@@ -1921,6 +1897,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
19211897
span: p_c.definition_span,
19221898
category: ConstraintCategory::OpaqueType,
19231899
variance_info: ty::VarianceDiagInfo::default(),
1900+
from_closure: false,
19241901
};
19251902
handle_constraint(constraint);
19261903
}
@@ -2066,31 +2043,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
20662043
// Classify each of the constraints along the path.
20672044
let mut categorized_path: Vec<BlameConstraint<'tcx>> = path
20682045
.iter()
2069-
.map(|constraint| {
2070-
let (category, span, from_closure, cause_code) =
2071-
if constraint.category == ConstraintCategory::ClosureBounds {
2072-
if let Some((category, span)) =
2073-
self.retrieve_closure_constraint_info(*constraint)
2074-
{
2075-
(category, span, true, ObligationCauseCode::MiscObligation)
2076-
} else {
2077-
(
2078-
constraint.category,
2079-
constraint.span,
2080-
false,
2081-
ObligationCauseCode::MiscObligation,
2082-
)
2083-
}
2084-
} else {
2085-
(constraint.category, constraint.span, false, cause_code.clone())
2086-
};
2087-
BlameConstraint {
2088-
category,
2089-
from_closure,
2090-
cause: ObligationCause::new(span, CRATE_HIR_ID, cause_code),
2091-
variance_info: constraint.variance_info,
2092-
outlives_constraint: *constraint,
2093-
}
2046+
.map(|constraint| BlameConstraint {
2047+
category: constraint.category,
2048+
from_closure: constraint.from_closure,
2049+
cause: ObligationCause::new(constraint.span, CRATE_HIR_ID, cause_code.clone()),
2050+
variance_info: constraint.variance_info,
2051+
outlives_constraint: *constraint,
20942052
})
20952053
.collect();
20962054
debug!("categorized_path={:#?}", categorized_path);
@@ -2274,92 +2232,6 @@ impl<'tcx> RegionDefinition<'tcx> {
22742232
}
22752233
}
22762234

2277-
pub trait ClosureRegionRequirementsExt<'tcx> {
2278-
fn apply_requirements(
2279-
&self,
2280-
tcx: TyCtxt<'tcx>,
2281-
closure_def_id: DefId,
2282-
closure_substs: SubstsRef<'tcx>,
2283-
) -> Vec<QueryOutlivesConstraint<'tcx>>;
2284-
}
2285-
2286-
impl<'tcx> ClosureRegionRequirementsExt<'tcx> for ClosureRegionRequirements<'tcx> {
2287-
/// Given an instance T of the closure type, this method
2288-
/// instantiates the "extra" requirements that we computed for the
2289-
/// closure into the inference context. This has the effect of
2290-
/// adding new outlives obligations to existing variables.
2291-
///
2292-
/// As described on `ClosureRegionRequirements`, the extra
2293-
/// requirements are expressed in terms of regionvids that index
2294-
/// into the free regions that appear on the closure type. So, to
2295-
/// do this, we first copy those regions out from the type T into
2296-
/// a vector. Then we can just index into that vector to extract
2297-
/// out the corresponding region from T and apply the
2298-
/// requirements.
2299-
fn apply_requirements(
2300-
&self,
2301-
tcx: TyCtxt<'tcx>,
2302-
closure_def_id: DefId,
2303-
closure_substs: SubstsRef<'tcx>,
2304-
) -> Vec<QueryOutlivesConstraint<'tcx>> {
2305-
debug!(
2306-
"apply_requirements(closure_def_id={:?}, closure_substs={:?})",
2307-
closure_def_id, closure_substs
2308-
);
2309-
2310-
// Extract the values of the free regions in `closure_substs`
2311-
// into a vector. These are the regions that we will be
2312-
// relating to one another.
2313-
let closure_mapping = &UniversalRegions::closure_mapping(
2314-
tcx,
2315-
closure_substs,
2316-
self.num_external_vids,
2317-
closure_def_id.expect_local(),
2318-
);
2319-
debug!("apply_requirements: closure_mapping={:?}", closure_mapping);
2320-
2321-
// Create the predicates.
2322-
self.outlives_requirements
2323-
.iter()
2324-
.map(|outlives_requirement| {
2325-
let outlived_region = closure_mapping[outlives_requirement.outlived_free_region];
2326-
2327-
match outlives_requirement.subject {
2328-
ClosureOutlivesSubject::Region(region) => {
2329-
let region = closure_mapping[region];
2330-
debug!(
2331-
"apply_requirements: region={:?} \
2332-
outlived_region={:?} \
2333-
outlives_requirement={:?}",
2334-
region, outlived_region, outlives_requirement,
2335-
);
2336-
(
2337-
ty::Binder::dummy(ty::OutlivesPredicate(
2338-
region.into(),
2339-
outlived_region,
2340-
)),
2341-
ConstraintCategory::BoringNoLocation,
2342-
)
2343-
}
2344-
2345-
ClosureOutlivesSubject::Ty(ty) => {
2346-
debug!(
2347-
"apply_requirements: ty={:?} \
2348-
outlived_region={:?} \
2349-
outlives_requirement={:?}",
2350-
ty, outlived_region, outlives_requirement,
2351-
);
2352-
(
2353-
ty::Binder::dummy(ty::OutlivesPredicate(ty.into(), outlived_region)),
2354-
ConstraintCategory::BoringNoLocation,
2355-
)
2356-
}
2357-
}
2358-
})
2359-
.collect()
2360-
}
2361-
}
2362-
23632235
#[derive(Clone, Debug)]
23642236
pub struct BlameConstraint<'tcx> {
23652237
pub category: ConstraintCategory<'tcx>,

compiler/rustc_borrowck/src/type_check/constraint_conversion.rs

+59-16
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
use rustc_infer::infer::canonical::QueryOutlivesConstraint;
1+
use rustc_hir::def_id::DefId;
22
use rustc_infer::infer::canonical::QueryRegionConstraints;
33
use rustc_infer::infer::outlives::env::RegionBoundPairs;
44
use rustc_infer::infer::outlives::obligations::{TypeOutlives, TypeOutlivesDelegate};
55
use rustc_infer::infer::region_constraints::{GenericKind, VerifyBound};
66
use rustc_infer::infer::{self, InferCtxt, SubregionOrigin};
7-
use rustc_middle::mir::ConstraintCategory;
7+
use rustc_middle::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, ConstraintCategory};
88
use rustc_middle::ty::subst::GenericArgKind;
99
use rustc_middle::ty::TypeFoldable;
1010
use rustc_middle::ty::{self, TyCtxt};
@@ -38,6 +38,7 @@ pub(crate) struct ConstraintConversion<'a, 'tcx> {
3838
locations: Locations,
3939
span: Span,
4040
category: ConstraintCategory<'tcx>,
41+
from_closure: bool,
4142
constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
4243
}
4344

@@ -64,6 +65,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
6465
span,
6566
category,
6667
constraints,
68+
from_closure: false,
6769
}
6870
}
6971

@@ -81,30 +83,70 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
8183
}
8284
self.constraints.member_constraints = tmp;
8385

84-
for query_constraint in outlives {
85-
self.convert(query_constraint);
86+
for (predicate, constraint_category) in outlives {
87+
// At the moment, we never generate any "higher-ranked"
88+
// region constraints like `for<'a> 'a: 'b`. At some point
89+
// when we move to universes, we will, and this assertion
90+
// will start to fail.
91+
let predicate = predicate.no_bound_vars().unwrap_or_else(|| {
92+
bug!("query_constraint {:?} contained bound vars", predicate,);
93+
});
94+
95+
self.convert(predicate, *constraint_category);
96+
}
97+
}
98+
99+
/// Given an instance of the closure type, this method instantiates the "extra" requirements
100+
/// that we computed for the closure. This has the effect of adding new outlives obligations
101+
/// to existing region variables in `closure_substs`.
102+
#[instrument(skip(self), level = "debug")]
103+
pub fn apply_closure_requirements(
104+
&mut self,
105+
closure_requirements: &ClosureRegionRequirements<'tcx>,
106+
closure_def_id: DefId,
107+
closure_substs: ty::SubstsRef<'tcx>,
108+
) {
109+
// Extract the values of the free regions in `closure_substs`
110+
// into a vector. These are the regions that we will be
111+
// relating to one another.
112+
let closure_mapping = &UniversalRegions::closure_mapping(
113+
self.tcx,
114+
closure_substs,
115+
closure_requirements.num_external_vids,
116+
closure_def_id.expect_local(),
117+
);
118+
debug!(?closure_mapping);
119+
120+
// Create the predicates.
121+
let backup = (self.category, self.span, self.from_closure);
122+
self.from_closure = true;
123+
for outlives_requirement in &closure_requirements.outlives_requirements {
124+
let outlived_region = closure_mapping[outlives_requirement.outlived_free_region];
125+
let subject = match outlives_requirement.subject {
126+
ClosureOutlivesSubject::Region(re) => closure_mapping[re].into(),
127+
ClosureOutlivesSubject::Ty(ty) => ty.into(),
128+
};
129+
130+
self.category = outlives_requirement.category;
131+
self.span = outlives_requirement.blame_span;
132+
self.convert(ty::OutlivesPredicate(subject, outlived_region), self.category);
86133
}
134+
(self.category, self.span, self.from_closure) = backup;
87135
}
88136

89-
fn convert(&mut self, query_constraint: &QueryOutlivesConstraint<'tcx>) {
137+
fn convert(
138+
&mut self,
139+
predicate: ty::OutlivesPredicate<ty::GenericArg<'tcx>, ty::Region<'tcx>>,
140+
constraint_category: ConstraintCategory<'tcx>,
141+
) {
90142
debug!("generate: constraints at: {:#?}", self.locations);
91143

92144
// Extract out various useful fields we'll need below.
93145
let ConstraintConversion {
94146
tcx, region_bound_pairs, implicit_region_bound, param_env, ..
95147
} = *self;
96148

97-
// At the moment, we never generate any "higher-ranked"
98-
// region constraints like `for<'a> 'a: 'b`. At some point
99-
// when we move to universes, we will, and this assertion
100-
// will start to fail.
101-
let ty::OutlivesPredicate(k1, r2) =
102-
query_constraint.0.no_bound_vars().unwrap_or_else(|| {
103-
bug!("query_constraint {:?} contained bound vars", query_constraint,);
104-
});
105-
106-
let constraint_category = query_constraint.1;
107-
149+
let ty::OutlivesPredicate(k1, r2) = predicate;
108150
match k1.unpack() {
109151
GenericArgKind::Lifetime(r1) => {
110152
let r1_vid = self.to_region_vid(r1);
@@ -188,6 +230,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
188230
sub,
189231
sup,
190232
variance_info: ty::VarianceDiagInfo::default(),
233+
from_closure: self.from_closure,
191234
});
192235
}
193236

0 commit comments

Comments
 (0)