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;
|
let param_env = self.param_env;
|
||||||
self.add_outlives_bounds(outlives::explicit_outlives_bounds(param_env));
|
self.add_outlives_bounds(outlives::explicit_outlives_bounds(param_env));
|
||||||
|
|
||||||
// Finally:
|
|
||||||
// - outlives is reflexive, so `'r: 'r` for every region `'r`
|
// - outlives is reflexive, so `'r: 'r` for every region `'r`
|
||||||
// - `'static: 'r` for every region `'r`
|
// - `'static: 'r` for every region `'r`
|
||||||
// - `'r: 'fn_body` for every (other) universally quantified
|
// - `'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.
|
// We add implied bounds from both the unnormalized and normalized ty.
|
||||||
// See issue #87748
|
// See issue #87748
|
||||||
let constraints_unnorm = self.add_implied_bounds(ty);
|
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
|
let TypeOpOutput { output: norm_ty, constraints: constraints_normalize, .. } = self
|
||||||
.param_env
|
.param_env
|
||||||
.and(type_op::normalize::Normalize::new(ty))
|
.and(type_op::normalize::Normalize::new(ty))
|
||||||
|
@ -279,7 +280,9 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
|
||||||
error_info: None,
|
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
|
// Note: we need this in examples like
|
||||||
// ```
|
// ```
|
||||||
|
@ -295,7 +298,9 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
|
||||||
// Both &Self::Bar and &() are WF
|
// Both &Self::Bar and &() are WF
|
||||||
if ty != norm_ty {
|
if ty != norm_ty {
|
||||||
let constraints_norm = self.add_implied_bounds(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);
|
normalized_inputs_and_output.push(norm_ty);
|
||||||
|
|
|
@ -910,7 +910,7 @@ pub(crate) struct MirTypeckRegionConstraints<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> 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.
|
/// region that corresponds to a previously created one.
|
||||||
fn placeholder_region(
|
fn placeholder_region(
|
||||||
&mut self,
|
&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)
|
let obligations = wf::obligations(ocx.infcx, param_env, CRATE_DEF_ID, 0, arg, DUMMY_SP)
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
// While these predicates should all be implied by other parts of
|
for obligation in obligations {
|
||||||
// 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| {
|
|
||||||
debug!(?obligation);
|
debug!(?obligation);
|
||||||
assert!(!obligation.has_escaping_bound_vars());
|
assert!(!obligation.has_escaping_bound_vars());
|
||||||
match obligation.predicate.kind().no_bound_vars() {
|
|
||||||
None => None,
|
// While these predicates should all be implied by other parts of
|
||||||
Some(pred) => match pred {
|
// the program, they are still relevant as they may constrain
|
||||||
ty::PredicateKind::Clause(ty::Clause::Trait(..))
|
// inference variables, which is necessary to add the correct
|
||||||
| ty::PredicateKind::Subtype(..)
|
// implied bounds in some cases, mostly when dealing with projections.
|
||||||
| ty::PredicateKind::Coerce(..)
|
//
|
||||||
| ty::PredicateKind::Clause(ty::Clause::Projection(..))
|
// Another important point here: we only register `Projection`
|
||||||
| ty::PredicateKind::ClosureKind(..)
|
// predicates, since otherwise we might register outlives
|
||||||
| ty::PredicateKind::ObjectSafe(..)
|
// predicates containing inference variables, and we don't
|
||||||
| ty::PredicateKind::ConstEvaluatable(..)
|
// learn anything new from those.
|
||||||
| ty::PredicateKind::ConstEquate(..)
|
if obligation.predicate.has_non_region_infer() {
|
||||||
| ty::PredicateKind::Ambiguous
|
match obligation.predicate.kind().skip_binder() {
|
||||||
| ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
|
ty::PredicateKind::Clause(ty::Clause::Projection(..)) => {
|
||||||
ty::PredicateKind::WellFormed(arg) => {
|
ocx.register_obligation(obligation.clone());
|
||||||
wf_args.push(arg);
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
|
_ => {}
|
||||||
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
|
// 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::untranslatable_diagnostic)]
|
||||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||||
#![feature(let_chains)]
|
#![feature(let_chains)]
|
||||||
|
#![feature(drain_filter)]
|
||||||
#![recursion_limit = "256"]
|
#![recursion_limit = "256"]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue