Skip to content

Commit 8e0909d

Browse files
Move param env bound deep normalization to OutlivesEnvironment building
1 parent 48b7e38 commit 8e0909d

File tree

3 files changed

+37
-45
lines changed

3 files changed

+37
-45
lines changed

Diff for: compiler/rustc_infer/src/infer/outlives/env.rs

+15-23
Original file line numberDiff line numberDiff line change
@@ -31,26 +31,14 @@ use crate::traits::query::OutlivesBound;
3131
pub struct OutlivesEnvironment<'tcx> {
3232
pub param_env: ty::ParamEnv<'tcx>,
3333
free_region_map: FreeRegionMap<'tcx>,
34-
35-
// Contains the implied region bounds in scope for our current body.
36-
//
37-
// Example:
38-
//
39-
// ```
40-
// fn foo<'a, 'b, T>(x: &'a T, y: &'b ()) {
41-
// bar(x, y, |y: &'b T| { .. } // body B1)
42-
// } // body B0
43-
// ```
44-
//
45-
// Here, when checking the body B0, the list would be `[T: 'a]`, because we
46-
// infer that `T` must outlive `'a` from the implied bounds on the
47-
// fn declaration.
48-
//
49-
// For the body B1 however, the list would be `[T: 'a, T: 'b]`, because we
50-
// also can see that -- within the closure body! -- `T` must
51-
// outlive `'b`. This is not necessarily true outside the closure
52-
// body, since the closure may never be called.
34+
/// FIXME: Your first reaction may be that this is a bit strange. `RegionBoundPairs`
35+
/// does not contain lifetimes, which are instead in the `FreeRegionMap`, and other
36+
/// known type outlives are stored in the `known_type_outlives` set. So why do we
37+
/// have these at all? It turns out that removing these and using `known_type_outlives`
38+
/// everywhere is just enough of a perf regression to matter. This can/should be
39+
/// optimized in the future, though.
5340
region_bound_pairs: RegionBoundPairs<'tcx>,
41+
known_type_outlives: Vec<ty::PolyTypeOutlivesPredicate<'tcx>>,
5442
}
5543

5644
/// "Region-bound pairs" tracks outlives relations that are known to
@@ -59,9 +47,10 @@ pub struct OutlivesEnvironment<'tcx> {
5947
pub type RegionBoundPairs<'tcx> = FxIndexSet<ty::OutlivesPredicate<'tcx, GenericKind<'tcx>>>;
6048

6149
impl<'tcx> OutlivesEnvironment<'tcx> {
62-
/// Create a new `OutlivesEnvironment` with extra outlives bounds.
63-
pub fn with_bounds(
50+
/// Create a new `OutlivesEnvironment` from normalized outlives bounds.
51+
pub fn from_normalized_bounds(
6452
param_env: ty::ParamEnv<'tcx>,
53+
known_type_outlives: Vec<ty::PolyTypeOutlivesPredicate<'tcx>>,
6554
extra_bounds: impl IntoIterator<Item = OutlivesBound<'tcx>>,
6655
) -> Self {
6756
let mut region_relation = TransitiveRelationBuilder::default();
@@ -96,18 +85,21 @@ impl<'tcx> OutlivesEnvironment<'tcx> {
9685

9786
OutlivesEnvironment {
9887
param_env,
88+
known_type_outlives,
9989
free_region_map: FreeRegionMap { relation: region_relation.freeze() },
10090
region_bound_pairs,
10191
}
10292
}
10393

104-
/// Borrows current value of the `free_region_map`.
10594
pub fn free_region_map(&self) -> &FreeRegionMap<'tcx> {
10695
&self.free_region_map
10796
}
10897

109-
/// Borrows current `region_bound_pairs`.
11098
pub fn region_bound_pairs(&self) -> &RegionBoundPairs<'tcx> {
11199
&self.region_bound_pairs
112100
}
101+
102+
pub fn known_type_outlives(&self) -> &[ty::PolyTypeOutlivesPredicate<'tcx>] {
103+
&self.known_type_outlives
104+
}
113105
}

Diff for: compiler/rustc_infer/src/infer/outlives/obligations.rs

+1-21
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@ use rustc_middle::ty::{
6767
self, GenericArgKind, GenericArgsRef, PolyTypeOutlivesPredicate, Region, Ty, TyCtxt,
6868
TypeFoldable as _, TypeVisitableExt,
6969
};
70-
use rustc_span::DUMMY_SP;
7170
use rustc_type_ir::outlives::{Component, push_outlives_components};
7271
use smallvec::smallvec;
7372
use tracing::{debug, instrument};
@@ -142,25 +141,6 @@ impl<'tcx> InferCtxt<'tcx> {
142141
) -> Result<(), (PolyTypeOutlivesPredicate<'tcx>, SubregionOrigin<'tcx>)> {
143142
assert!(!self.in_snapshot(), "cannot process registered region obligations in a snapshot");
144143

145-
let normalized_caller_bounds: Vec<_> = outlives_env
146-
.param_env
147-
.caller_bounds()
148-
.iter()
149-
.filter_map(|clause| {
150-
let outlives = clause.as_type_outlives_clause()?;
151-
Some(
152-
deeply_normalize_ty(
153-
outlives,
154-
SubregionOrigin::AscribeUserTypeProvePredicate(DUMMY_SP),
155-
)
156-
// FIXME(-Znext-solver): How do we accurately report an error span here :(
157-
.map_err(|NoSolution| {
158-
(outlives, SubregionOrigin::AscribeUserTypeProvePredicate(DUMMY_SP))
159-
}),
160-
)
161-
})
162-
.try_collect()?;
163-
164144
// Must loop since the process of normalizing may itself register region obligations.
165145
for iteration in 0.. {
166146
let my_region_obligations = self.take_registered_region_obligations();
@@ -194,7 +174,7 @@ impl<'tcx> InferCtxt<'tcx> {
194174
self.tcx,
195175
outlives_env.region_bound_pairs(),
196176
None,
197-
&normalized_caller_bounds,
177+
outlives_env.known_type_outlives(),
198178
);
199179
let category = origin.to_constraint_category();
200180
outlives.type_must_outlive(origin, sup_type, sub_region, category);

Diff for: compiler/rustc_trait_selection/src/regions.rs

+21-1
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,32 @@ impl<'tcx> OutlivesEnvironment<'tcx> {
3333
assumed_wf_tys: impl IntoIterator<Item = Ty<'tcx>>,
3434
implied_bounds_compat: bool,
3535
) -> Self {
36+
let mut bounds = vec![];
37+
38+
for bound in param_env.caller_bounds() {
39+
if let Some(mut type_outlives) = bound.as_type_outlives_clause() {
40+
if infcx.next_trait_solver() {
41+
match crate::solve::deeply_normalize::<_, ScrubbedTraitError<'tcx>>(
42+
infcx.at(&ObligationCause::dummy(), param_env),
43+
type_outlives,
44+
) {
45+
Ok(new) => type_outlives = new,
46+
Err(_) => {
47+
infcx.dcx().delayed_bug(format!("could not normalize `{bound}`"));
48+
}
49+
}
50+
}
51+
bounds.push(type_outlives);
52+
}
53+
}
54+
3655
// FIXME: This needs to be modified so that we normalize the known type
3756
// outlives obligations then elaborate them into their region/type components.
3857
// Otherwise, `<W<'a> as Mirror>::Assoc: 'b` will not imply `'a: 'b` even
3958
// if we can normalize `'a`.
40-
OutlivesEnvironment::with_bounds(
59+
OutlivesEnvironment::from_normalized_bounds(
4160
param_env,
61+
bounds,
4262
infcx.implied_bounds_tys_with_compat(
4363
body_id,
4464
param_env,

0 commit comments

Comments
 (0)