Update implied_outlives_bounds to properly register implied bounds behind normalization
This commit is contained in:
parent
1a663c0f53
commit
0637b6b471
4 changed files with 62 additions and 43 deletions
|
@ -226,7 +226,6 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
|
|||
let param_env = self.param_env;
|
||||
self.add_outlives_bounds(outlives::explicit_outlives_bounds(param_env));
|
||||
|
||||
// Finally:
|
||||
// - outlives is reflexive, so `'r: 'r` for every region `'r`
|
||||
// - `'static: 'r` for every region `'r`
|
||||
// - `'r: 'fn_body` for every (other) universally quantified
|
||||
|
@ -263,7 +262,9 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
|
|||
// We add implied bounds from both the unnormalized and normalized ty.
|
||||
// See issue #87748
|
||||
let constraints_unnorm = self.add_implied_bounds(ty);
|
||||
constraints_unnorm.map(|c| constraints.push(c));
|
||||
if let Some(c) = constraints_unnorm {
|
||||
constraints.push(c)
|
||||
}
|
||||
let TypeOpOutput { output: norm_ty, constraints: constraints_normalize, .. } = self
|
||||
.param_env
|
||||
.and(type_op::normalize::Normalize::new(ty))
|
||||
|
@ -279,7 +280,9 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
|
|||
error_info: None,
|
||||
}
|
||||
});
|
||||
constraints_normalize.map(|c| constraints.push(c));
|
||||
if let Some(c) = constraints_normalize {
|
||||
constraints.push(c)
|
||||
}
|
||||
|
||||
// Note: we need this in examples like
|
||||
// ```
|
||||
|
@ -295,7 +298,9 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
|
|||
// Both &Self::Bar and &() are WF
|
||||
if ty != norm_ty {
|
||||
let constraints_norm = self.add_implied_bounds(norm_ty);
|
||||
constraints_norm.map(|c| constraints.push(c));
|
||||
if let Some(c) = constraints_norm {
|
||||
constraints.push(c)
|
||||
}
|
||||
}
|
||||
|
||||
normalized_inputs_and_output.push(norm_ty);
|
||||
|
|
|
@ -910,7 +910,7 @@ pub(crate) struct MirTypeckRegionConstraints<'tcx> {
|
|||
}
|
||||
|
||||
impl<'tcx> MirTypeckRegionConstraints<'tcx> {
|
||||
/// Creates a `Region` that for a given `PlaceholderRegion`, or returns the
|
||||
/// Creates a `Region` for a given `PlaceholderRegion`, or returns the
|
||||
/// region that corresponds to a previously created one.
|
||||
fn placeholder_region(
|
||||
&mut self,
|
||||
|
|
|
@ -70,48 +70,61 @@ fn compute_implied_outlives_bounds<'tcx>(
|
|||
let obligations = wf::obligations(ocx.infcx, param_env, CRATE_DEF_ID, 0, arg, DUMMY_SP)
|
||||
.unwrap_or_default();
|
||||
|
||||
// While these predicates should all be implied by other parts of
|
||||
// the program, they are still relevant as they may constrain
|
||||
// inference variables, which is necessary to add the correct
|
||||
// implied bounds in some cases, mostly when dealing with projections.
|
||||
ocx.register_obligations(
|
||||
obligations.iter().filter(|o| o.predicate.has_non_region_infer()).cloned(),
|
||||
);
|
||||
|
||||
// From the full set of obligations, just filter down to the
|
||||
// region relationships.
|
||||
outlives_bounds.extend(obligations.into_iter().filter_map(|obligation| {
|
||||
for obligation in obligations {
|
||||
debug!(?obligation);
|
||||
assert!(!obligation.has_escaping_bound_vars());
|
||||
match obligation.predicate.kind().no_bound_vars() {
|
||||
None => None,
|
||||
Some(pred) => match pred {
|
||||
ty::PredicateKind::Clause(ty::Clause::Trait(..))
|
||||
| ty::PredicateKind::Subtype(..)
|
||||
| ty::PredicateKind::Coerce(..)
|
||||
| ty::PredicateKind::Clause(ty::Clause::Projection(..))
|
||||
| ty::PredicateKind::ClosureKind(..)
|
||||
| ty::PredicateKind::ObjectSafe(..)
|
||||
| ty::PredicateKind::ConstEvaluatable(..)
|
||||
| ty::PredicateKind::ConstEquate(..)
|
||||
| ty::PredicateKind::Ambiguous
|
||||
| ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
|
||||
ty::PredicateKind::WellFormed(arg) => {
|
||||
wf_args.push(arg);
|
||||
None
|
||||
|
||||
// While these predicates should all be implied by other parts of
|
||||
// the program, they are still relevant as they may constrain
|
||||
// inference variables, which is necessary to add the correct
|
||||
// implied bounds in some cases, mostly when dealing with projections.
|
||||
//
|
||||
// Another important point here: we only register `Projection`
|
||||
// predicates, since otherwise we might register outlives
|
||||
// predicates containing inference variables, and we don't
|
||||
// learn anything new from those.
|
||||
if obligation.predicate.has_non_region_infer() {
|
||||
match obligation.predicate.kind().skip_binder() {
|
||||
ty::PredicateKind::Clause(ty::Clause::Projection(..)) => {
|
||||
ocx.register_obligation(obligation.clone());
|
||||
}
|
||||
|
||||
ty::PredicateKind::Clause(ty::Clause::RegionOutlives(
|
||||
ty::OutlivesPredicate(r_a, r_b),
|
||||
)) => Some(ty::OutlivesPredicate(r_a.into(), r_b)),
|
||||
|
||||
ty::PredicateKind::Clause(ty::Clause::TypeOutlives(ty::OutlivesPredicate(
|
||||
ty_a,
|
||||
r_b,
|
||||
))) => Some(ty::OutlivesPredicate(ty_a.into(), r_b)),
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
let pred = match obligation.predicate.kind().no_bound_vars() {
|
||||
None => continue,
|
||||
Some(pred) => pred,
|
||||
};
|
||||
match pred {
|
||||
ty::PredicateKind::Clause(ty::Clause::Trait(..))
|
||||
| ty::PredicateKind::Subtype(..)
|
||||
| ty::PredicateKind::Coerce(..)
|
||||
| ty::PredicateKind::Clause(ty::Clause::Projection(..))
|
||||
| ty::PredicateKind::ClosureKind(..)
|
||||
| ty::PredicateKind::ObjectSafe(..)
|
||||
| ty::PredicateKind::ConstEvaluatable(..)
|
||||
| ty::PredicateKind::ConstEquate(..)
|
||||
| ty::PredicateKind::Ambiguous
|
||||
| ty::PredicateKind::TypeWellFormedFromEnv(..) => {}
|
||||
|
||||
// We need to search through *all* WellFormed predicates
|
||||
ty::PredicateKind::WellFormed(arg) => {
|
||||
wf_args.push(arg);
|
||||
}
|
||||
|
||||
// We need to register region relationships
|
||||
ty::PredicateKind::Clause(ty::Clause::RegionOutlives(ty::OutlivesPredicate(
|
||||
r_a,
|
||||
r_b,
|
||||
))) => outlives_bounds.push(ty::OutlivesPredicate(r_a.into(), r_b)),
|
||||
|
||||
ty::PredicateKind::Clause(ty::Clause::TypeOutlives(ty::OutlivesPredicate(
|
||||
ty_a,
|
||||
r_b,
|
||||
))) => outlives_bounds.push(ty::OutlivesPredicate(ty_a.into(), r_b)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This call to `select_all_or_error` is necessary to constrain inference variables, which we
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
#![feature(let_chains)]
|
||||
#![feature(drain_filter)]
|
||||
#![recursion_limit = "256"]
|
||||
|
||||
#[macro_use]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue