mirror of https://github.com/rust-lang/rust.git
Cleanup free_region_relations a bit
This commit is contained in:
parent
8996ea93b6
commit
1a663c0f53
|
@ -187,6 +187,7 @@ pub(crate) struct PlaceholderIndices {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PlaceholderIndices {
|
impl PlaceholderIndices {
|
||||||
|
/// Returns the `PlaceholderIndex` for the inserted `PlaceholderRegion`
|
||||||
pub(crate) fn insert(&mut self, placeholder: ty::PlaceholderRegion) -> PlaceholderIndex {
|
pub(crate) fn insert(&mut self, placeholder: ty::PlaceholderRegion) -> PlaceholderIndex {
|
||||||
let (index, _) = self.indices.insert_full(placeholder);
|
let (index, _) = self.indices.insert_full(placeholder);
|
||||||
index.into()
|
index.into()
|
||||||
|
|
|
@ -8,6 +8,7 @@ use rustc_infer::infer::InferCtxt;
|
||||||
use rustc_middle::mir::ConstraintCategory;
|
use rustc_middle::mir::ConstraintCategory;
|
||||||
use rustc_middle::traits::query::OutlivesBound;
|
use rustc_middle::traits::query::OutlivesBound;
|
||||||
use rustc_middle::ty::{self, RegionVid, Ty};
|
use rustc_middle::ty::{self, RegionVid, Ty};
|
||||||
|
use rustc_span::Span;
|
||||||
use rustc_trait_selection::traits::query::type_op::{self, TypeOp};
|
use rustc_trait_selection::traits::query::type_op::{self, TypeOp};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use type_op::TypeOpOutput;
|
use type_op::TypeOpOutput;
|
||||||
|
@ -217,65 +218,9 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
|
||||||
self.inverse_outlives.add(fr_b, fr_a);
|
self.inverse_outlives.add(fr_b, fr_a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(level = "debug", skip(self))]
|
||||||
pub(crate) fn create(mut self) -> CreateResult<'tcx> {
|
pub(crate) fn create(mut self) -> CreateResult<'tcx> {
|
||||||
let span = self.infcx.tcx.def_span(self.universal_regions.defining_ty.def_id());
|
let span = self.infcx.tcx.def_span(self.universal_regions.defining_ty.def_id());
|
||||||
let unnormalized_input_output_tys = self
|
|
||||||
.universal_regions
|
|
||||||
.unnormalized_input_tys
|
|
||||||
.iter()
|
|
||||||
.cloned()
|
|
||||||
.chain(Some(self.universal_regions.unnormalized_output_ty));
|
|
||||||
|
|
||||||
// For each of the input/output types:
|
|
||||||
// - Normalize the type. This will create some region
|
|
||||||
// constraints, which we buffer up because we are
|
|
||||||
// not ready to process them yet.
|
|
||||||
// - Then compute the implied bounds. This will adjust
|
|
||||||
// the `region_bound_pairs` and so forth.
|
|
||||||
// - After this is done, we'll process the constraints, once
|
|
||||||
// the `relations` is built.
|
|
||||||
let mut normalized_inputs_and_output =
|
|
||||||
Vec::with_capacity(self.universal_regions.unnormalized_input_tys.len() + 1);
|
|
||||||
let constraint_sets: Vec<_> = unnormalized_input_output_tys
|
|
||||||
.flat_map(|ty| {
|
|
||||||
debug!("build: input_or_output={:?}", ty);
|
|
||||||
// We add implied bounds from both the unnormalized and normalized ty.
|
|
||||||
// See issue #87748
|
|
||||||
let constraints_implied1 = self.add_implied_bounds(ty);
|
|
||||||
let TypeOpOutput { output: norm_ty, constraints: constraints1, .. } = self
|
|
||||||
.param_env
|
|
||||||
.and(type_op::normalize::Normalize::new(ty))
|
|
||||||
.fully_perform(self.infcx)
|
|
||||||
.unwrap_or_else(|_| {
|
|
||||||
let reported = self
|
|
||||||
.infcx
|
|
||||||
.tcx
|
|
||||||
.sess
|
|
||||||
.delay_span_bug(span, &format!("failed to normalize {:?}", ty));
|
|
||||||
TypeOpOutput {
|
|
||||||
output: self.infcx.tcx.ty_error_with_guaranteed(reported),
|
|
||||||
constraints: None,
|
|
||||||
error_info: None,
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// Note: we need this in examples like
|
|
||||||
// ```
|
|
||||||
// trait Foo {
|
|
||||||
// type Bar;
|
|
||||||
// fn foo(&self) -> &Self::Bar;
|
|
||||||
// }
|
|
||||||
// impl Foo for () {
|
|
||||||
// type Bar = ();
|
|
||||||
// fn foo(&self) -> &() {}
|
|
||||||
// }
|
|
||||||
// ```
|
|
||||||
// Both &Self::Bar and &() are WF
|
|
||||||
let constraints_implied2 =
|
|
||||||
if ty != norm_ty { self.add_implied_bounds(norm_ty) } else { None };
|
|
||||||
normalized_inputs_and_output.push(norm_ty);
|
|
||||||
constraints1.into_iter().chain(constraints_implied1).chain(constraints_implied2)
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
// Insert the facts we know from the predicates. Why? Why not.
|
// Insert the facts we know from the predicates. Why? Why not.
|
||||||
let param_env = self.param_env;
|
let param_env = self.param_env;
|
||||||
|
@ -295,19 +240,69 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
|
||||||
self.relate_universal_regions(fr, fr_fn_body);
|
self.relate_universal_regions(fr, fr_fn_body);
|
||||||
}
|
}
|
||||||
|
|
||||||
for data in &constraint_sets {
|
let unnormalized_input_output_tys = self
|
||||||
constraint_conversion::ConstraintConversion::new(
|
.universal_regions
|
||||||
self.infcx,
|
.unnormalized_input_tys
|
||||||
&self.universal_regions,
|
.iter()
|
||||||
&self.region_bound_pairs,
|
.cloned()
|
||||||
self.implicit_region_bound,
|
.chain(Some(self.universal_regions.unnormalized_output_ty));
|
||||||
self.param_env,
|
|
||||||
Locations::All(span),
|
// For each of the input/output types:
|
||||||
span,
|
// - Normalize the type. This will create some region
|
||||||
ConstraintCategory::Internal,
|
// constraints, which we buffer up because we are
|
||||||
&mut self.constraints,
|
// not ready to process them yet.
|
||||||
)
|
// - Then compute the implied bounds. This will adjust
|
||||||
.convert_all(data);
|
// the `region_bound_pairs` and so forth.
|
||||||
|
// - After this is done, we'll process the constraints, once
|
||||||
|
// the `relations` is built.
|
||||||
|
let mut normalized_inputs_and_output =
|
||||||
|
Vec::with_capacity(self.universal_regions.unnormalized_input_tys.len() + 1);
|
||||||
|
let mut constraints = vec![];
|
||||||
|
for ty in unnormalized_input_output_tys {
|
||||||
|
debug!("build: input_or_output={:?}", ty);
|
||||||
|
// 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));
|
||||||
|
let TypeOpOutput { output: norm_ty, constraints: constraints_normalize, .. } = self
|
||||||
|
.param_env
|
||||||
|
.and(type_op::normalize::Normalize::new(ty))
|
||||||
|
.fully_perform(self.infcx)
|
||||||
|
.unwrap_or_else(|_| {
|
||||||
|
self.infcx
|
||||||
|
.tcx
|
||||||
|
.sess
|
||||||
|
.delay_span_bug(span, &format!("failed to normalize {:?}", ty));
|
||||||
|
TypeOpOutput {
|
||||||
|
output: self.infcx.tcx.ty_error(),
|
||||||
|
constraints: None,
|
||||||
|
error_info: None,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
constraints_normalize.map(|c| constraints.push(c));
|
||||||
|
|
||||||
|
// Note: we need this in examples like
|
||||||
|
// ```
|
||||||
|
// trait Foo {
|
||||||
|
// type Bar;
|
||||||
|
// fn foo(&self) -> &Self::Bar;
|
||||||
|
// }
|
||||||
|
// impl Foo for () {
|
||||||
|
// type Bar = ();
|
||||||
|
// fn foo(&self) ->&() {}
|
||||||
|
// }
|
||||||
|
// ```
|
||||||
|
// 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));
|
||||||
|
}
|
||||||
|
|
||||||
|
normalized_inputs_and_output.push(norm_ty);
|
||||||
|
}
|
||||||
|
|
||||||
|
for c in constraints {
|
||||||
|
self.push_region_constraints(c, span);
|
||||||
}
|
}
|
||||||
|
|
||||||
CreateResult {
|
CreateResult {
|
||||||
|
@ -321,6 +316,24 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(skip(self, data), level = "debug")]
|
||||||
|
fn push_region_constraints(&mut self, data: &QueryRegionConstraints<'tcx>, span: Span) {
|
||||||
|
debug!("constraints generated: {:#?}", data);
|
||||||
|
|
||||||
|
constraint_conversion::ConstraintConversion::new(
|
||||||
|
self.infcx,
|
||||||
|
&self.universal_regions,
|
||||||
|
&self.region_bound_pairs,
|
||||||
|
self.implicit_region_bound,
|
||||||
|
self.param_env,
|
||||||
|
Locations::All(span),
|
||||||
|
span,
|
||||||
|
ConstraintCategory::Internal,
|
||||||
|
&mut self.constraints,
|
||||||
|
)
|
||||||
|
.convert_all(data);
|
||||||
|
}
|
||||||
|
|
||||||
/// Update the type of a single local, which should represent
|
/// Update the type of a single local, which should represent
|
||||||
/// either the return type of the MIR or one of its arguments. At
|
/// either the return type of the MIR or one of its arguments. At
|
||||||
/// the same time, compute and add any implied bounds that come
|
/// the same time, compute and add any implied bounds that come
|
||||||
|
@ -332,6 +345,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
|
||||||
.and(type_op::implied_outlives_bounds::ImpliedOutlivesBounds { ty })
|
.and(type_op::implied_outlives_bounds::ImpliedOutlivesBounds { ty })
|
||||||
.fully_perform(self.infcx)
|
.fully_perform(self.infcx)
|
||||||
.unwrap_or_else(|_| bug!("failed to compute implied bounds {:?}", ty));
|
.unwrap_or_else(|_| bug!("failed to compute implied bounds {:?}", ty));
|
||||||
|
debug!(?bounds, ?constraints);
|
||||||
self.add_outlives_bounds(bounds);
|
self.add_outlives_bounds(bounds);
|
||||||
constraints
|
constraints
|
||||||
}
|
}
|
||||||
|
|
|
@ -910,6 +910,8 @@ pub(crate) struct MirTypeckRegionConstraints<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> MirTypeckRegionConstraints<'tcx> {
|
impl<'tcx> MirTypeckRegionConstraints<'tcx> {
|
||||||
|
/// Creates a `Region` that for a given `PlaceholderRegion`, or returns the
|
||||||
|
/// region that corresponds to a previously created one.
|
||||||
fn placeholder_region(
|
fn placeholder_region(
|
||||||
&mut self,
|
&mut self,
|
||||||
infcx: &InferCtxt<'tcx>,
|
infcx: &InferCtxt<'tcx>,
|
||||||
|
|
|
@ -207,6 +207,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
|
||||||
///
|
///
|
||||||
/// In some cases, such as when `erased_ty` represents a `ty::Param`, however,
|
/// In some cases, such as when `erased_ty` represents a `ty::Param`, however,
|
||||||
/// the result is precise.
|
/// the result is precise.
|
||||||
|
#[instrument(level = "debug", skip(self))]
|
||||||
fn declared_generic_bounds_from_env_for_erased_ty(
|
fn declared_generic_bounds_from_env_for_erased_ty(
|
||||||
&self,
|
&self,
|
||||||
erased_ty: Ty<'tcx>,
|
erased_ty: Ty<'tcx>,
|
||||||
|
|
|
@ -81,6 +81,7 @@ fn compute_implied_outlives_bounds<'tcx>(
|
||||||
// From the full set of obligations, just filter down to the
|
// From the full set of obligations, just filter down to the
|
||||||
// region relationships.
|
// region relationships.
|
||||||
outlives_bounds.extend(obligations.into_iter().filter_map(|obligation| {
|
outlives_bounds.extend(obligations.into_iter().filter_map(|obligation| {
|
||||||
|
debug!(?obligation);
|
||||||
assert!(!obligation.has_escaping_bound_vars());
|
assert!(!obligation.has_escaping_bound_vars());
|
||||||
match obligation.predicate.kind().no_bound_vars() {
|
match obligation.predicate.kind().no_bound_vars() {
|
||||||
None => None,
|
None => None,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// Regression test for #52057. There is an implied bound
|
// Regression test for #52057. There is an implied bound
|
||||||
// that `I: 'a` where `'a` is the lifetime of `self` in `parse_first`;
|
// that `I: 'x` where `'x` is the lifetime of the reference `&mut Self::Input`
|
||||||
// but to observe that, one must normalize first.
|
// in `parse_first`; but to observe that, one must normalize first.
|
||||||
//
|
//
|
||||||
// run-pass
|
// run-pass
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue