Skip to content

Commit 0637b6b

Browse files
committed
Update implied_outlives_bounds to properly register implied bounds behind normalization
1 parent 1a663c0 commit 0637b6b

File tree

4 files changed

+60
-41
lines changed

4 files changed

+60
-41
lines changed

Diff for: compiler/rustc_borrowck/src/type_check/free_region_relations.rs

+9-4
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,6 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
226226
let param_env = self.param_env;
227227
self.add_outlives_bounds(outlives::explicit_outlives_bounds(param_env));
228228

229-
// Finally:
230229
// - outlives is reflexive, so `'r: 'r` for every region `'r`
231230
// - `'static: 'r` for every region `'r`
232231
// - `'r: 'fn_body` for every (other) universally quantified
@@ -263,7 +262,9 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
263262
// We add implied bounds from both the unnormalized and normalized ty.
264263
// See issue #87748
265264
let constraints_unnorm = self.add_implied_bounds(ty);
266-
constraints_unnorm.map(|c| constraints.push(c));
265+
if let Some(c) = constraints_unnorm {
266+
constraints.push(c)
267+
}
267268
let TypeOpOutput { output: norm_ty, constraints: constraints_normalize, .. } = self
268269
.param_env
269270
.and(type_op::normalize::Normalize::new(ty))
@@ -279,7 +280,9 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
279280
error_info: None,
280281
}
281282
});
282-
constraints_normalize.map(|c| constraints.push(c));
283+
if let Some(c) = constraints_normalize {
284+
constraints.push(c)
285+
}
283286

284287
// Note: we need this in examples like
285288
// ```
@@ -295,7 +298,9 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
295298
// Both &Self::Bar and &() are WF
296299
if ty != norm_ty {
297300
let constraints_norm = self.add_implied_bounds(norm_ty);
298-
constraints_norm.map(|c| constraints.push(c));
301+
if let Some(c) = constraints_norm {
302+
constraints.push(c)
303+
}
299304
}
300305

301306
normalized_inputs_and_output.push(norm_ty);

Diff for: compiler/rustc_borrowck/src/type_check/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -910,7 +910,7 @@ pub(crate) struct MirTypeckRegionConstraints<'tcx> {
910910
}
911911

912912
impl<'tcx> MirTypeckRegionConstraints<'tcx> {
913-
/// Creates a `Region` that for a given `PlaceholderRegion`, or returns the
913+
/// Creates a `Region` for a given `PlaceholderRegion`, or returns the
914914
/// region that corresponds to a previously created one.
915915
fn placeholder_region(
916916
&mut self,

Diff for: compiler/rustc_traits/src/implied_outlives_bounds.rs

+49-36
Original file line numberDiff line numberDiff line change
@@ -70,48 +70,61 @@ fn compute_implied_outlives_bounds<'tcx>(
7070
let obligations = wf::obligations(ocx.infcx, param_env, CRATE_DEF_ID, 0, arg, DUMMY_SP)
7171
.unwrap_or_default();
7272

73-
// While these predicates should all be implied by other parts of
74-
// the program, they are still relevant as they may constrain
75-
// inference variables, which is necessary to add the correct
76-
// implied bounds in some cases, mostly when dealing with projections.
77-
ocx.register_obligations(
78-
obligations.iter().filter(|o| o.predicate.has_non_region_infer()).cloned(),
79-
);
80-
81-
// From the full set of obligations, just filter down to the
82-
// region relationships.
83-
outlives_bounds.extend(obligations.into_iter().filter_map(|obligation| {
73+
for obligation in obligations {
8474
debug!(?obligation);
8575
assert!(!obligation.has_escaping_bound_vars());
86-
match obligation.predicate.kind().no_bound_vars() {
87-
None => None,
88-
Some(pred) => match pred {
89-
ty::PredicateKind::Clause(ty::Clause::Trait(..))
90-
| ty::PredicateKind::Subtype(..)
91-
| ty::PredicateKind::Coerce(..)
92-
| ty::PredicateKind::Clause(ty::Clause::Projection(..))
93-
| ty::PredicateKind::ClosureKind(..)
94-
| ty::PredicateKind::ObjectSafe(..)
95-
| ty::PredicateKind::ConstEvaluatable(..)
96-
| ty::PredicateKind::ConstEquate(..)
97-
| ty::PredicateKind::Ambiguous
98-
| ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
99-
ty::PredicateKind::WellFormed(arg) => {
100-
wf_args.push(arg);
101-
None
76+
77+
// While these predicates should all be implied by other parts of
78+
// the program, they are still relevant as they may constrain
79+
// inference variables, which is necessary to add the correct
80+
// implied bounds in some cases, mostly when dealing with projections.
81+
//
82+
// Another important point here: we only register `Projection`
83+
// predicates, since otherwise we might register outlives
84+
// predicates containing inference variables, and we don't
85+
// learn anything new from those.
86+
if obligation.predicate.has_non_region_infer() {
87+
match obligation.predicate.kind().skip_binder() {
88+
ty::PredicateKind::Clause(ty::Clause::Projection(..)) => {
89+
ocx.register_obligation(obligation.clone());
10290
}
91+
_ => {}
92+
}
93+
}
10394

104-
ty::PredicateKind::Clause(ty::Clause::RegionOutlives(
105-
ty::OutlivesPredicate(r_a, r_b),
106-
)) => Some(ty::OutlivesPredicate(r_a.into(), r_b)),
95+
let pred = match obligation.predicate.kind().no_bound_vars() {
96+
None => continue,
97+
Some(pred) => pred,
98+
};
99+
match pred {
100+
ty::PredicateKind::Clause(ty::Clause::Trait(..))
101+
| ty::PredicateKind::Subtype(..)
102+
| ty::PredicateKind::Coerce(..)
103+
| ty::PredicateKind::Clause(ty::Clause::Projection(..))
104+
| ty::PredicateKind::ClosureKind(..)
105+
| ty::PredicateKind::ObjectSafe(..)
106+
| ty::PredicateKind::ConstEvaluatable(..)
107+
| ty::PredicateKind::ConstEquate(..)
108+
| ty::PredicateKind::Ambiguous
109+
| ty::PredicateKind::TypeWellFormedFromEnv(..) => {}
110+
111+
// We need to search through *all* WellFormed predicates
112+
ty::PredicateKind::WellFormed(arg) => {
113+
wf_args.push(arg);
114+
}
115+
116+
// We need to register region relationships
117+
ty::PredicateKind::Clause(ty::Clause::RegionOutlives(ty::OutlivesPredicate(
118+
r_a,
119+
r_b,
120+
))) => outlives_bounds.push(ty::OutlivesPredicate(r_a.into(), r_b)),
107121

108-
ty::PredicateKind::Clause(ty::Clause::TypeOutlives(ty::OutlivesPredicate(
109-
ty_a,
110-
r_b,
111-
))) => Some(ty::OutlivesPredicate(ty_a.into(), r_b)),
112-
},
122+
ty::PredicateKind::Clause(ty::Clause::TypeOutlives(ty::OutlivesPredicate(
123+
ty_a,
124+
r_b,
125+
))) => outlives_bounds.push(ty::OutlivesPredicate(ty_a.into(), r_b)),
113126
}
114-
}));
127+
}
115128
}
116129

117130
// This call to `select_all_or_error` is necessary to constrain inference variables, which we

Diff for: compiler/rustc_traits/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#![deny(rustc::untranslatable_diagnostic)]
55
#![deny(rustc::diagnostic_outside_of_impl)]
66
#![feature(let_chains)]
7+
#![feature(drain_filter)]
78
#![recursion_limit = "256"]
89

910
#[macro_use]

0 commit comments

Comments
 (0)