2018-02-25 10:58:54 -05:00
|
|
|
//! Code for the 'normalization' query. This consists of a wrapper
|
|
|
|
//! which folds deeply, invoking the underlying
|
|
|
|
//! `normalize_projection_ty` query when it encounters projections.
|
|
|
|
|
2019-02-05 11:20:45 -06:00
|
|
|
use crate::infer::at::At;
|
|
|
|
use crate::infer::canonical::OriginalQueryValues;
|
|
|
|
use crate::infer::{InferCtxt, InferOk};
|
2020-02-22 11:44:18 +01:00
|
|
|
use crate::traits::error_reporting::InferCtxtExt;
|
2021-07-16 16:23:42 -04:00
|
|
|
use crate::traits::project::needs_normalization;
|
2019-02-05 11:20:45 -06:00
|
|
|
use crate::traits::{Obligation, ObligationCause, PredicateObligation, Reveal};
|
2020-09-23 23:32:11 -05:00
|
|
|
use rustc_data_structures::sso::SsoHashMap;
|
2020-03-14 20:13:55 +02:00
|
|
|
use rustc_data_structures::stack::ensure_sufficient_stack;
|
2020-03-29 17:19:48 +02:00
|
|
|
use rustc_infer::traits::Normalized;
|
2021-03-30 14:26:40 +00:00
|
|
|
use rustc_middle::mir;
|
2020-03-29 16:41:09 +02:00
|
|
|
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder};
|
|
|
|
use rustc_middle::ty::subst::Subst;
|
2021-05-03 09:25:32 -04:00
|
|
|
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitor};
|
|
|
|
|
|
|
|
use std::ops::ControlFlow;
|
2018-02-25 10:58:54 -05:00
|
|
|
|
|
|
|
use super::NoSolution;
|
|
|
|
|
2020-03-29 16:41:09 +02:00
|
|
|
pub use rustc_middle::traits::query::NormalizationResult;
|
2020-01-22 09:04:50 +01:00
|
|
|
|
2020-02-22 11:44:18 +01:00
|
|
|
pub trait AtExt<'tcx> {
|
2020-10-24 02:21:18 +02:00
|
|
|
fn normalize<T>(&self, value: T) -> Result<Normalized<'tcx, T>, NoSolution>
|
2020-02-22 11:44:18 +01:00
|
|
|
where
|
|
|
|
T: TypeFoldable<'tcx>;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'cx, 'tcx> AtExt<'tcx> for At<'cx, 'tcx> {
|
2018-02-25 10:58:54 -05:00
|
|
|
/// Normalize `value` in the context of the inference context,
|
|
|
|
/// yielding a resulting type, or an error if `value` cannot be
|
|
|
|
/// normalized. If you don't care about regions, you should prefer
|
|
|
|
/// `normalize_erasing_regions`, which is more efficient.
|
|
|
|
///
|
2018-06-02 00:20:00 -07:00
|
|
|
/// If the normalization succeeds and is unambiguous, returns back
|
2018-02-25 10:58:54 -05:00
|
|
|
/// the normalized value along with various outlives relations (in
|
|
|
|
/// the form of obligations that must be discharged).
|
|
|
|
///
|
2019-02-08 14:53:55 +01:00
|
|
|
/// N.B., this will *eventually* be the main means of
|
2018-02-25 10:58:54 -05:00
|
|
|
/// normalizing, but for now should be used only when we actually
|
|
|
|
/// know that normalization will succeed, since error reporting
|
|
|
|
/// and other details are still "under development".
|
2020-10-24 02:21:18 +02:00
|
|
|
fn normalize<T>(&self, value: T) -> Result<Normalized<'tcx, T>, NoSolution>
|
2018-02-25 10:58:54 -05:00
|
|
|
where
|
|
|
|
T: TypeFoldable<'tcx>,
|
|
|
|
{
|
2018-02-26 11:14:16 -05:00
|
|
|
debug!(
|
|
|
|
"normalize::<{}>(value={:?}, param_env={:?})",
|
2020-10-13 10:17:05 +02:00
|
|
|
std::any::type_name::<T>(),
|
2018-02-26 11:14:16 -05:00
|
|
|
value,
|
|
|
|
self.param_env,
|
|
|
|
);
|
2021-07-16 16:23:42 -04:00
|
|
|
if !needs_normalization(&value, self.param_env.reveal()) {
|
2020-12-05 12:59:54 +01:00
|
|
|
return Ok(Normalized { value, obligations: vec![] });
|
2018-09-12 16:57:19 +02:00
|
|
|
}
|
|
|
|
|
2018-02-25 10:58:54 -05:00
|
|
|
let mut normalizer = QueryNormalizer {
|
|
|
|
infcx: self.infcx,
|
|
|
|
cause: self.cause,
|
|
|
|
param_env: self.param_env,
|
|
|
|
obligations: vec![],
|
|
|
|
error: false,
|
2020-09-23 23:32:11 -05:00
|
|
|
cache: SsoHashMap::new(),
|
2018-02-25 10:58:54 -05:00
|
|
|
anon_depth: 0,
|
2021-07-13 10:50:40 -04:00
|
|
|
universes: vec![],
|
2018-02-25 10:58:54 -05:00
|
|
|
};
|
|
|
|
|
2021-08-24 22:26:48 -04:00
|
|
|
// This is actually a consequence by the way `normalize_erasing_regions` works currently.
|
|
|
|
// Because it needs to call the `normalize_generic_arg_after_erasing_regions`, it folds
|
|
|
|
// through tys and consts in a `TypeFoldable`. Importantly, it skips binders, leaving us
|
|
|
|
// with trying to normalize with escaping bound vars.
|
|
|
|
//
|
|
|
|
// Here, we just add the universes that we *would* have created had we passed through the binders.
|
|
|
|
//
|
|
|
|
// We *could* replace escaping bound vars eagerly here, but it doesn't seem really necessary.
|
|
|
|
// The rest of the code is already set up to be lazy about replacing bound vars,
|
|
|
|
// and only when we actually have to normalize.
|
2021-05-03 09:25:32 -04:00
|
|
|
if value.has_escaping_bound_vars() {
|
2021-08-26 11:04:01 +02:00
|
|
|
let mut max_visitor = MaxEscapingBoundVarVisitor {
|
|
|
|
tcx: self.infcx.tcx,
|
|
|
|
outer_index: ty::INNERMOST,
|
|
|
|
escaping: 0,
|
|
|
|
};
|
2021-05-03 09:25:32 -04:00
|
|
|
value.visit_with(&mut max_visitor);
|
|
|
|
if max_visitor.escaping > 0 {
|
|
|
|
normalizer.universes.extend((0..max_visitor.escaping).map(|_| None));
|
|
|
|
}
|
|
|
|
}
|
2021-05-19 15:03:43 +02:00
|
|
|
let result = value.fold_with(&mut normalizer).into_ok();
|
2021-07-16 16:23:42 -04:00
|
|
|
info!(
|
2020-04-04 21:23:38 +03:00
|
|
|
"normalize::<{}>: result={:?} with {} obligations",
|
2020-10-13 10:17:05 +02:00
|
|
|
std::any::type_name::<T>(),
|
2020-04-04 21:23:38 +03:00
|
|
|
result,
|
|
|
|
normalizer.obligations.len(),
|
|
|
|
);
|
|
|
|
debug!(
|
|
|
|
"normalize::<{}>: obligations={:?}",
|
2020-10-13 10:17:05 +02:00
|
|
|
std::any::type_name::<T>(),
|
2020-04-04 21:23:38 +03:00
|
|
|
normalizer.obligations,
|
|
|
|
);
|
2018-02-25 10:58:54 -05:00
|
|
|
if normalizer.error {
|
|
|
|
Err(NoSolution)
|
|
|
|
} else {
|
2020-04-04 21:23:38 +03:00
|
|
|
Ok(Normalized { value: result, obligations: normalizer.obligations })
|
2018-02-25 10:58:54 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-03 09:25:32 -04:00
|
|
|
/// Visitor to find the maximum escaping bound var
|
2021-08-26 11:04:01 +02:00
|
|
|
struct MaxEscapingBoundVarVisitor<'tcx> {
|
|
|
|
tcx: TyCtxt<'tcx>,
|
2021-05-03 09:25:32 -04:00
|
|
|
// The index which would count as escaping
|
|
|
|
outer_index: ty::DebruijnIndex,
|
|
|
|
escaping: usize,
|
|
|
|
}
|
|
|
|
|
2021-08-26 11:04:01 +02:00
|
|
|
impl<'tcx> TypeVisitor<'tcx> for MaxEscapingBoundVarVisitor<'tcx> {
|
|
|
|
fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
|
|
|
|
Some(self.tcx)
|
|
|
|
}
|
|
|
|
|
2021-05-03 09:25:32 -04:00
|
|
|
fn visit_binder<T: TypeFoldable<'tcx>>(
|
|
|
|
&mut self,
|
|
|
|
t: &ty::Binder<'tcx, T>,
|
|
|
|
) -> ControlFlow<Self::BreakTy> {
|
|
|
|
self.outer_index.shift_in(1);
|
|
|
|
let result = t.super_visit_with(self);
|
|
|
|
self.outer_index.shift_out(1);
|
|
|
|
result
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
|
|
|
if t.outer_exclusive_binder() > self.outer_index {
|
|
|
|
self.escaping = self
|
|
|
|
.escaping
|
|
|
|
.max(t.outer_exclusive_binder().as_usize() - self.outer_index.as_usize());
|
|
|
|
}
|
|
|
|
ControlFlow::CONTINUE
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
|
|
|
|
match *r {
|
|
|
|
ty::ReLateBound(debruijn, _) if debruijn > self.outer_index => {
|
|
|
|
self.escaping =
|
|
|
|
self.escaping.max(debruijn.as_usize() - self.outer_index.as_usize());
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
ControlFlow::CONTINUE
|
|
|
|
}
|
|
|
|
|
|
|
|
fn visit_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
|
|
|
|
match ct.val {
|
|
|
|
ty::ConstKind::Bound(debruijn, _) if debruijn >= self.outer_index => {
|
|
|
|
self.escaping =
|
|
|
|
self.escaping.max(debruijn.as_usize() - self.outer_index.as_usize());
|
|
|
|
ControlFlow::CONTINUE
|
|
|
|
}
|
|
|
|
_ => ct.super_visit_with(self),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-14 19:39:39 +03:00
|
|
|
struct QueryNormalizer<'cx, 'tcx> {
|
2019-06-14 00:48:52 +03:00
|
|
|
infcx: &'cx InferCtxt<'cx, 'tcx>,
|
2018-02-25 10:58:54 -05:00
|
|
|
cause: &'cx ObligationCause<'tcx>,
|
|
|
|
param_env: ty::ParamEnv<'tcx>,
|
|
|
|
obligations: Vec<PredicateObligation<'tcx>>,
|
2020-09-23 23:32:11 -05:00
|
|
|
cache: SsoHashMap<Ty<'tcx>, Ty<'tcx>>,
|
2018-02-25 10:58:54 -05:00
|
|
|
error: bool,
|
|
|
|
anon_depth: usize,
|
2021-07-13 10:50:40 -04:00
|
|
|
universes: Vec<Option<ty::UniverseIndex>>,
|
2018-02-25 10:58:54 -05:00
|
|
|
}
|
|
|
|
|
2019-06-14 00:48:52 +03:00
|
|
|
impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
|
|
|
|
fn tcx<'c>(&'c self) -> TyCtxt<'tcx> {
|
2018-02-25 10:58:54 -05:00
|
|
|
self.infcx.tcx
|
|
|
|
}
|
|
|
|
|
2021-07-13 10:50:40 -04:00
|
|
|
fn fold_binder<T: TypeFoldable<'tcx>>(
|
|
|
|
&mut self,
|
|
|
|
t: ty::Binder<'tcx, T>,
|
2021-05-19 15:01:30 +02:00
|
|
|
) -> Result<ty::Binder<'tcx, T>, Self::Error> {
|
2021-07-13 10:50:40 -04:00
|
|
|
self.universes.push(None);
|
|
|
|
let t = t.super_fold_with(self);
|
|
|
|
self.universes.pop();
|
|
|
|
t
|
|
|
|
}
|
|
|
|
|
2021-01-24 00:00:00 +00:00
|
|
|
#[instrument(level = "debug", skip(self))]
|
2021-05-19 15:01:30 +02:00
|
|
|
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
|
2021-07-16 16:23:42 -04:00
|
|
|
if !needs_normalization(&ty, self.param_env.reveal()) {
|
2021-05-19 15:01:30 +02:00
|
|
|
return Ok(ty);
|
2020-01-28 00:52:21 +01:00
|
|
|
}
|
|
|
|
|
2020-09-19 17:27:13 +02:00
|
|
|
if let Some(ty) = self.cache.get(&ty) {
|
2021-05-19 15:01:30 +02:00
|
|
|
return Ok(ty);
|
2020-09-19 17:27:13 +02:00
|
|
|
}
|
|
|
|
|
2021-08-24 22:26:48 -04:00
|
|
|
// See note in `rustc_trait_selection::traits::project` about why we
|
|
|
|
// wait to fold the substs.
|
2021-05-03 09:25:32 -04:00
|
|
|
|
|
|
|
// Wrap this in a closure so we don't accidentally return from the outer function
|
2020-09-19 17:27:13 +02:00
|
|
|
let res = (|| match *ty.kind() {
|
2021-09-26 15:58:24 -04:00
|
|
|
// This is really important. While we *can* handle this, this has
|
|
|
|
// severe performance implications for large opaque types with
|
|
|
|
// late-bound regions. See `issue-88862` benchmark.
|
|
|
|
ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => {
|
2018-05-08 16:10:16 +03:00
|
|
|
// Only normalize `impl Trait` after type-checking, usually in codegen.
|
2020-07-02 20:52:40 -04:00
|
|
|
match self.param_env.reveal() {
|
2021-05-03 09:25:32 -04:00
|
|
|
Reveal::UserFacing => ty.super_fold_with(self),
|
2018-02-25 10:58:54 -05:00
|
|
|
|
|
|
|
Reveal::All => {
|
2021-05-19 15:01:30 +02:00
|
|
|
let substs = substs.super_fold_with(self)?;
|
2021-07-04 13:02:51 -05:00
|
|
|
let recursion_limit = self.tcx().recursion_limit();
|
2020-05-26 19:48:08 +01:00
|
|
|
if !recursion_limit.value_within_limit(self.anon_depth) {
|
2018-02-25 10:58:54 -05:00
|
|
|
let obligation = Obligation::with_depth(
|
|
|
|
self.cause.clone(),
|
2020-05-26 19:48:08 +01:00
|
|
|
recursion_limit.0,
|
2018-02-25 10:58:54 -05:00
|
|
|
self.param_env,
|
|
|
|
ty,
|
|
|
|
);
|
|
|
|
self.infcx.report_overflow_error(&obligation, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
let generic_ty = self.tcx().type_of(def_id);
|
|
|
|
let concrete_ty = generic_ty.subst(self.tcx(), substs);
|
|
|
|
self.anon_depth += 1;
|
2018-05-22 14:31:56 +02:00
|
|
|
if concrete_ty == ty {
|
2018-08-22 00:24:03 -04:00
|
|
|
bug!(
|
|
|
|
"infinite recursion generic_ty: {:#?}, substs: {:#?}, \
|
|
|
|
concrete_ty: {:#?}, ty: {:#?}",
|
|
|
|
generic_ty,
|
|
|
|
substs,
|
|
|
|
concrete_ty,
|
|
|
|
ty
|
|
|
|
);
|
2018-05-22 14:31:56 +02:00
|
|
|
}
|
2018-11-02 16:14:24 +01:00
|
|
|
let folded_ty = ensure_sufficient_stack(|| self.fold_ty(concrete_ty));
|
2018-02-25 10:58:54 -05:00
|
|
|
self.anon_depth -= 1;
|
|
|
|
folded_ty
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-24 09:27:15 +02:00
|
|
|
ty::Projection(data) if !data.has_escaping_bound_vars() => {
|
2021-05-03 09:25:32 -04:00
|
|
|
// This branch is just an optimization: when we don't have escaping bound vars,
|
|
|
|
// we don't need to replace them with placeholders (see branch below).
|
2018-02-25 10:58:54 -05:00
|
|
|
|
2019-09-25 15:36:14 -04:00
|
|
|
let tcx = self.infcx.tcx;
|
2021-05-19 15:01:30 +02:00
|
|
|
let data = data.super_fold_with(self)?;
|
2018-02-25 10:58:54 -05:00
|
|
|
|
2018-09-26 15:49:41 -04:00
|
|
|
let mut orig_values = OriginalQueryValues::default();
|
2019-06-03 15:04:40 +01:00
|
|
|
// HACK(matthewjasper) `'static` is special-cased in selection,
|
|
|
|
// so we cannot canonicalize it.
|
2019-12-22 17:42:04 -05:00
|
|
|
let c_data = self
|
|
|
|
.infcx
|
2021-07-07 10:56:26 -05:00
|
|
|
.canonicalize_query_keep_static(self.param_env.and(data), &mut orig_values);
|
2018-02-25 10:58:54 -05:00
|
|
|
debug!("QueryNormalizer: c_data = {:#?}", c_data);
|
|
|
|
debug!("QueryNormalizer: orig_values = {:#?}", orig_values);
|
2019-09-25 15:36:14 -04:00
|
|
|
match tcx.normalize_projection_ty(c_data) {
|
2018-02-25 10:58:54 -05:00
|
|
|
Ok(result) => {
|
|
|
|
// We don't expect ambiguity.
|
|
|
|
if result.is_ambiguous() {
|
|
|
|
self.error = true;
|
2021-08-24 22:26:48 -04:00
|
|
|
return ty.super_fold_with(self);
|
2018-02-25 10:58:54 -05:00
|
|
|
}
|
|
|
|
|
2018-09-24 15:27:47 -04:00
|
|
|
match self.infcx.instantiate_query_response_and_region_obligations(
|
2018-02-25 10:58:54 -05:00
|
|
|
self.cause,
|
|
|
|
self.param_env,
|
|
|
|
&orig_values,
|
2020-10-24 09:27:15 +02:00
|
|
|
result,
|
2019-12-22 17:42:04 -05:00
|
|
|
) {
|
2018-09-12 16:57:19 +02:00
|
|
|
Ok(InferOk { value: result, obligations }) => {
|
2018-02-25 10:58:54 -05:00
|
|
|
debug!("QueryNormalizer: result = {:#?}", result);
|
|
|
|
debug!("QueryNormalizer: obligations = {:#?}", obligations);
|
|
|
|
self.obligations.extend(obligations);
|
2021-05-19 15:01:30 +02:00
|
|
|
Ok(result.normalized_ty)
|
2018-02-25 10:58:54 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
Err(_) => {
|
|
|
|
self.error = true;
|
2021-08-24 22:26:48 -04:00
|
|
|
ty.super_fold_with(self)
|
2018-02-25 10:58:54 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Err(NoSolution) => {
|
|
|
|
self.error = true;
|
2021-08-24 22:26:48 -04:00
|
|
|
ty.super_fold_with(self)
|
2018-02-25 10:58:54 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-07-09 00:04:47 -04:00
|
|
|
|
2021-05-03 09:25:32 -04:00
|
|
|
ty::Projection(data) => {
|
|
|
|
// See note in `rustc_trait_selection::traits::project`
|
2021-07-15 10:41:35 -04:00
|
|
|
|
2021-07-09 00:04:47 -04:00
|
|
|
let tcx = self.infcx.tcx;
|
|
|
|
let infcx = self.infcx;
|
2021-07-15 10:41:35 -04:00
|
|
|
let (data, mapped_regions, mapped_types, mapped_consts) =
|
|
|
|
crate::traits::project::BoundVarReplacer::replace_bound_vars(
|
|
|
|
infcx,
|
|
|
|
&mut self.universes,
|
|
|
|
data,
|
|
|
|
);
|
2021-05-19 15:01:30 +02:00
|
|
|
let data = data.super_fold_with(self)?;
|
2021-07-09 00:04:47 -04:00
|
|
|
|
|
|
|
let mut orig_values = OriginalQueryValues::default();
|
|
|
|
// HACK(matthewjasper) `'static` is special-cased in selection,
|
|
|
|
// so we cannot canonicalize it.
|
|
|
|
let c_data = self
|
|
|
|
.infcx
|
2021-07-07 10:56:26 -05:00
|
|
|
.canonicalize_query_keep_static(self.param_env.and(data), &mut orig_values);
|
2021-07-09 00:04:47 -04:00
|
|
|
debug!("QueryNormalizer: c_data = {:#?}", c_data);
|
|
|
|
debug!("QueryNormalizer: orig_values = {:#?}", orig_values);
|
2021-08-24 22:26:48 -04:00
|
|
|
match tcx.normalize_projection_ty(c_data) {
|
2021-07-09 00:04:47 -04:00
|
|
|
Ok(result) => {
|
|
|
|
// We don't expect ambiguity.
|
|
|
|
if result.is_ambiguous() {
|
|
|
|
self.error = true;
|
2021-08-24 22:26:48 -04:00
|
|
|
return ty.super_fold_with(self);
|
2021-07-09 00:04:47 -04:00
|
|
|
}
|
|
|
|
match self.infcx.instantiate_query_response_and_region_obligations(
|
|
|
|
self.cause,
|
|
|
|
self.param_env,
|
|
|
|
&orig_values,
|
|
|
|
result,
|
|
|
|
) {
|
|
|
|
Ok(InferOk { value: result, obligations }) => {
|
|
|
|
debug!("QueryNormalizer: result = {:#?}", result);
|
|
|
|
debug!("QueryNormalizer: obligations = {:#?}", obligations);
|
|
|
|
self.obligations.extend(obligations);
|
2021-05-19 15:01:30 +02:00
|
|
|
Ok(crate::traits::project::PlaceholderReplacer::replace_placeholders(
|
2021-08-24 22:26:48 -04:00
|
|
|
infcx,
|
|
|
|
mapped_regions,
|
|
|
|
mapped_types,
|
|
|
|
mapped_consts,
|
|
|
|
&self.universes,
|
|
|
|
result.normalized_ty,
|
2021-05-19 15:01:30 +02:00
|
|
|
))
|
2021-07-09 00:04:47 -04:00
|
|
|
}
|
|
|
|
Err(_) => {
|
|
|
|
self.error = true;
|
2021-08-24 22:26:48 -04:00
|
|
|
ty.super_fold_with(self)
|
2021-07-09 00:04:47 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Err(NoSolution) => {
|
|
|
|
self.error = true;
|
2021-08-24 22:26:48 -04:00
|
|
|
ty.super_fold_with(self)
|
2021-07-09 00:04:47 -04:00
|
|
|
}
|
2021-08-24 22:26:48 -04:00
|
|
|
}
|
2021-07-09 00:04:47 -04:00
|
|
|
}
|
2018-02-25 10:58:54 -05:00
|
|
|
|
2021-05-03 09:25:32 -04:00
|
|
|
_ => ty.super_fold_with(self),
|
2021-05-19 15:01:30 +02:00
|
|
|
})()?;
|
2020-09-19 17:27:13 +02:00
|
|
|
self.cache.insert(ty, res);
|
2021-05-19 15:01:30 +02:00
|
|
|
Ok(res)
|
2018-02-25 10:58:54 -05:00
|
|
|
}
|
|
|
|
|
2021-05-19 15:01:30 +02:00
|
|
|
fn fold_const(
|
|
|
|
&mut self,
|
|
|
|
constant: &'tcx ty::Const<'tcx>,
|
|
|
|
) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
|
|
|
|
let constant = constant.super_fold_with(self)?;
|
|
|
|
Ok(constant.eval(self.infcx.tcx, self.param_env))
|
2018-02-25 10:58:54 -05:00
|
|
|
}
|
2021-03-30 14:26:40 +00:00
|
|
|
|
2021-05-19 15:01:30 +02:00
|
|
|
fn fold_mir_const(
|
|
|
|
&mut self,
|
|
|
|
constant: mir::ConstantKind<'tcx>,
|
|
|
|
) -> Result<mir::ConstantKind<'tcx>, Self::Error> {
|
2021-03-30 14:26:40 +00:00
|
|
|
constant.super_fold_with(self)
|
|
|
|
}
|
2018-02-25 10:58:54 -05:00
|
|
|
}
|