Auto merge of #98900 - lcnr:region-stuff, r=jackh726
const_generics: correctly deal with bound variables removes the hack in `resolve` which was needed because we evaluated constants without caring about their bound variables. Each commit should be fairly self-contained, even if they build on each other r? `@jackh726`
This commit is contained in:
commit
ccb5595df2
12 changed files with 76 additions and 83 deletions
|
@ -635,13 +635,18 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
|
|||
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
fn fold_const(&mut self, constant: ty::Const<'tcx>) -> ty::Const<'tcx> {
|
||||
if self.selcx.tcx().lazy_normalization() || !self.eager_inference_replacement {
|
||||
let tcx = self.selcx.tcx();
|
||||
if tcx.lazy_normalization() {
|
||||
constant
|
||||
} else {
|
||||
let constant = constant.super_fold_with(self);
|
||||
debug!(?constant);
|
||||
debug!("self.param_env: {:?}", self.param_env);
|
||||
constant.eval(self.selcx.tcx(), self.param_env)
|
||||
debug!(?constant, ?self.param_env);
|
||||
with_replaced_escaping_bound_vars(
|
||||
self.selcx.infcx(),
|
||||
&mut self.universes,
|
||||
constant,
|
||||
|constant| constant.eval(tcx, self.param_env),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -671,6 +676,41 @@ pub struct BoundVarReplacer<'me, 'tcx> {
|
|||
universe_indices: &'me mut Vec<Option<ty::UniverseIndex>>,
|
||||
}
|
||||
|
||||
/// Executes `f` on `value` after replacing all escaping bound variables with placeholders
|
||||
/// and then replaces these placeholders with the original bound variables in the result.
|
||||
///
|
||||
/// In most places, bound variables should be replaced right when entering a binder, making
|
||||
/// this function unnecessary. However, normalization currently does not do that, so we have
|
||||
/// to do this lazily.
|
||||
///
|
||||
/// You should not add any additional uses of this function, at least not without first
|
||||
/// discussing it with t-types.
|
||||
///
|
||||
/// FIXME(@lcnr): We may even consider experimenting with eagerly replacing bound vars during
|
||||
/// normalization as well, at which point this function will be unnecessary and can be removed.
|
||||
pub fn with_replaced_escaping_bound_vars<'a, 'tcx, T: TypeFoldable<'tcx>, R: TypeFoldable<'tcx>>(
|
||||
infcx: &'a InferCtxt<'a, 'tcx>,
|
||||
universe_indices: &'a mut Vec<Option<ty::UniverseIndex>>,
|
||||
value: T,
|
||||
f: impl FnOnce(T) -> R,
|
||||
) -> R {
|
||||
if value.has_escaping_bound_vars() {
|
||||
let (value, mapped_regions, mapped_types, mapped_consts) =
|
||||
BoundVarReplacer::replace_bound_vars(infcx, universe_indices, value);
|
||||
let result = f(value);
|
||||
PlaceholderReplacer::replace_placeholders(
|
||||
infcx,
|
||||
mapped_regions,
|
||||
mapped_types,
|
||||
mapped_consts,
|
||||
universe_indices,
|
||||
result,
|
||||
)
|
||||
} else {
|
||||
f(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'me, 'tcx> BoundVarReplacer<'me, 'tcx> {
|
||||
/// Returns `Some` if we *were* able to replace bound vars. If there are any bound vars that
|
||||
/// use a binding level above `universe_indices.len()`, we fail.
|
||||
|
|
|
@ -6,7 +6,7 @@ use crate::infer::at::At;
|
|||
use crate::infer::canonical::OriginalQueryValues;
|
||||
use crate::infer::{InferCtxt, InferOk};
|
||||
use crate::traits::error_reporting::InferCtxtExt;
|
||||
use crate::traits::project::needs_normalization;
|
||||
use crate::traits::project::{needs_normalization, BoundVarReplacer, PlaceholderReplacer};
|
||||
use crate::traits::{Obligation, ObligationCause, PredicateObligation, Reveal};
|
||||
use rustc_data_structures::sso::SsoHashMap;
|
||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||
|
@ -283,11 +283,7 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
|
|||
let tcx = self.infcx.tcx;
|
||||
let infcx = self.infcx;
|
||||
let (data, mapped_regions, mapped_types, mapped_consts) =
|
||||
crate::traits::project::BoundVarReplacer::replace_bound_vars(
|
||||
infcx,
|
||||
&mut self.universes,
|
||||
data,
|
||||
);
|
||||
BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, data);
|
||||
let data = data.try_fold_with(self)?;
|
||||
|
||||
let mut orig_values = OriginalQueryValues::default();
|
||||
|
@ -313,8 +309,7 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
|
|||
debug!("QueryNormalizer: result = {:#?}", result);
|
||||
debug!("QueryNormalizer: obligations = {:#?}", obligations);
|
||||
self.obligations.extend(obligations);
|
||||
|
||||
let res = crate::traits::project::PlaceholderReplacer::replace_placeholders(
|
||||
let res = PlaceholderReplacer::replace_placeholders(
|
||||
infcx,
|
||||
mapped_regions,
|
||||
mapped_types,
|
||||
|
@ -343,7 +338,13 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
|
|||
constant: ty::Const<'tcx>,
|
||||
) -> Result<ty::Const<'tcx>, Self::Error> {
|
||||
let constant = constant.try_super_fold_with(self)?;
|
||||
Ok(constant.eval(self.infcx.tcx, self.param_env))
|
||||
debug!(?constant, ?self.param_env);
|
||||
Ok(crate::traits::project::with_replaced_escaping_bound_vars(
|
||||
self.infcx,
|
||||
&mut self.universes,
|
||||
constant,
|
||||
|constant| constant.eval(self.infcx.tcx, self.param_env),
|
||||
))
|
||||
}
|
||||
|
||||
fn try_fold_mir_const(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue