2018-02-25 10:58:54 -05:00
|
|
|
//! Code for the 'normalization' query. This consists of a wrapper
|
|
|
|
//! which folds deeply, invoking the underlying
|
2024-02-20 10:34:51 +01:00
|
|
|
//! `normalize_canonicalized_projection_ty` query when it encounters projections.
|
2018-02-25 10:58:54 -05:00
|
|
|
|
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;
|
2024-04-29 08:53:45 +10:00
|
|
|
use rustc_macros::extension;
|
2020-03-29 16:41:09 +02:00
|
|
|
pub use rustc_middle::traits::query::NormalizationResult;
|
2023-02-22 02:18:40 +00:00
|
|
|
use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable};
|
|
|
|
use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt};
|
|
|
|
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitor};
|
2024-01-09 09:08:49 +11:00
|
|
|
use rustc_span::DUMMY_SP;
|
2024-08-30 09:20:26 +10:00
|
|
|
use tracing::{debug, info, instrument};
|
2021-05-03 09:25:32 -04:00
|
|
|
|
2018-02-25 10:58:54 -05:00
|
|
|
use super::NoSolution;
|
2024-07-08 15:36:57 -04:00
|
|
|
use crate::error_reporting::traits::OverflowCause;
|
2020-03-29 16:41:09 +02:00
|
|
|
use crate::error_reporting::InferCtxtErrorExt;
|
2019-02-05 11:20:45 -06:00
|
|
|
use crate::infer::at::At;
|
2020-03-29 16:41:09 +02:00
|
|
|
use crate::infer::canonical::OriginalQueryValues;
|
2019-02-05 11:20:45 -06:00
|
|
|
use crate::infer::{InferCtxt, InferOk};
|
2020-03-29 16:41:09 +02:00
|
|
|
use crate::traits::normalize::needs_normalization;
|
2022-12-06 00:19:42 +00:00
|
|
|
use crate::traits::{
|
2020-03-29 16:41:09 +02:00
|
|
|
BoundVarReplacer, Normalized, ObligationCause, PlaceholderReplacer, PredicateObligation,
|
|
|
|
Reveal, ScrubbedTraitError,
|
2024-07-29 08:13:50 +10:00
|
|
|
};
|
2020-01-22 09:04:50 +01:00
|
|
|
|
2024-02-14 17:18:56 +00:00
|
|
|
#[extension(pub trait QueryNormalizeExt<'tcx>)]
|
2024-09-12 09:25:11 +10:00
|
|
|
impl<'a, 'tcx> At<'a, '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".
|
2024-02-16 15:07:32 +00:00
|
|
|
///
|
|
|
|
/// This normalization should *only* be used when the projection does not
|
|
|
|
/// have possible ambiguity or may not be well-formed.
|
|
|
|
///
|
|
|
|
/// After codegen, when lifetimes do not matter, it is preferable to instead
|
|
|
|
/// use [`TyCtxt::normalize_erasing_regions`], which wraps this procedure.
|
2023-06-27 23:11:37 +02:00
|
|
|
fn query_normalize<T>(self, value: T) -> Result<Normalized<'tcx, T>, NoSolution>
|
2018-02-25 10:58:54 -05:00
|
|
|
where
|
2023-02-22 02:18:40 +00:00
|
|
|
T: TypeFoldable<TyCtxt<'tcx>>,
|
2018-02-25 10:58:54 -05:00
|
|
|
{
|
2018-02-26 11:14:16 -05:00
|
|
|
debug!(
|
2022-08-30 21:50:22 -04:00
|
|
|
"normalize::<{}>(value={:?}, param_env={:?}, cause={:?})",
|
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,
|
2022-08-30 21:50:22 -04:00
|
|
|
self.cause,
|
2018-02-26 11:14:16 -05:00
|
|
|
);
|
2023-06-27 23:11:37 +02:00
|
|
|
|
2023-07-13 18:24:37 +00: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.
|
|
|
|
let universes = if value.has_escaping_bound_vars() {
|
|
|
|
let mut max_visitor =
|
|
|
|
MaxEscapingBoundVarVisitor { outer_index: ty::INNERMOST, escaping: 0 };
|
|
|
|
value.visit_with(&mut max_visitor);
|
|
|
|
vec![None; max_visitor.escaping]
|
|
|
|
} else {
|
|
|
|
vec![]
|
|
|
|
};
|
|
|
|
|
2023-06-27 23:11:37 +02:00
|
|
|
if self.infcx.next_trait_solver() {
|
2024-06-02 18:36:11 -04:00
|
|
|
match crate::solve::deeply_normalize_with_skipped_universes::<_, ScrubbedTraitError<'tcx>>(
|
2024-06-01 14:12:34 -04:00
|
|
|
self, value, universes,
|
|
|
|
) {
|
2023-06-27 23:11:37 +02:00
|
|
|
Ok(value) => return Ok(Normalized { value, obligations: vec![] }),
|
|
|
|
Err(_errors) => {
|
|
|
|
return Err(NoSolution);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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![],
|
2020-09-23 23:32:11 -05:00
|
|
|
cache: SsoHashMap::new(),
|
2018-02-25 10:58:54 -05:00
|
|
|
anon_depth: 0,
|
2023-07-13 18:24:37 +00:00
|
|
|
universes,
|
2018-02-25 10:58:54 -05:00
|
|
|
};
|
|
|
|
|
2021-12-01 00:55:57 +00:00
|
|
|
let result = value.try_fold_with(&mut normalizer);
|
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,
|
|
|
|
);
|
2021-05-19 23:08:32 +02:00
|
|
|
result.map(|value| Normalized { value, obligations: normalizer.obligations })
|
2018-02-25 10:58:54 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-16 10:56:01 +01:00
|
|
|
// Visitor to find the maximum escaping bound var
|
2022-01-12 03:19:52 +00:00
|
|
|
struct MaxEscapingBoundVarVisitor {
|
2021-05-03 09:25:32 -04:00
|
|
|
// The index which would count as escaping
|
|
|
|
outer_index: ty::DebruijnIndex,
|
|
|
|
escaping: usize,
|
|
|
|
}
|
|
|
|
|
2023-02-09 19:38:07 +00:00
|
|
|
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for MaxEscapingBoundVarVisitor {
|
2024-02-24 17:22:28 -05:00
|
|
|
fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(&mut self, t: &ty::Binder<'tcx, T>) {
|
2021-05-03 09:25:32 -04:00
|
|
|
self.outer_index.shift_in(1);
|
2024-02-24 17:22:28 -05:00
|
|
|
t.super_visit_with(self);
|
2021-05-03 09:25:32 -04:00
|
|
|
self.outer_index.shift_out(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2024-02-24 17:22:28 -05:00
|
|
|
fn visit_ty(&mut self, t: Ty<'tcx>) {
|
2021-05-03 09:25:32 -04:00
|
|
|
if t.outer_exclusive_binder() > self.outer_index {
|
|
|
|
self.escaping = self
|
|
|
|
.escaping
|
|
|
|
.max(t.outer_exclusive_binder().as_usize() - self.outer_index.as_usize());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2024-02-24 17:22:28 -05:00
|
|
|
fn visit_region(&mut self, r: ty::Region<'tcx>) {
|
2021-05-03 09:25:32 -04:00
|
|
|
match *r {
|
2023-11-13 14:00:05 +00:00
|
|
|
ty::ReBound(debruijn, _) if debruijn > self.outer_index => {
|
2021-05-03 09:25:32 -04:00
|
|
|
self.escaping =
|
|
|
|
self.escaping.max(debruijn.as_usize() - self.outer_index.as_usize());
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-24 17:22:28 -05:00
|
|
|
fn visit_const(&mut self, ct: ty::Const<'tcx>) {
|
2023-11-22 23:28:28 +00:00
|
|
|
if ct.outer_exclusive_binder() > self.outer_index {
|
|
|
|
self.escaping = self
|
|
|
|
.escaping
|
|
|
|
.max(ct.outer_exclusive_binder().as_usize() - self.outer_index.as_usize());
|
2021-05-03 09:25:32 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-09-12 09:25:11 +10:00
|
|
|
struct QueryNormalizer<'a, 'tcx> {
|
|
|
|
infcx: &'a InferCtxt<'tcx>,
|
|
|
|
cause: &'a ObligationCause<'tcx>,
|
2018-02-25 10:58:54 -05:00
|
|
|
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
|
|
|
anon_depth: usize,
|
2021-07-13 10:50:40 -04:00
|
|
|
universes: Vec<Option<ty::UniverseIndex>>,
|
2018-02-25 10:58:54 -05:00
|
|
|
}
|
|
|
|
|
2024-09-12 09:25:11 +10:00
|
|
|
impl<'a, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'a, 'tcx> {
|
2021-05-19 23:08:32 +02:00
|
|
|
type Error = NoSolution;
|
|
|
|
|
2024-06-18 19:13:54 -04:00
|
|
|
fn cx(&self) -> TyCtxt<'tcx> {
|
2018-02-25 10:58:54 -05:00
|
|
|
self.infcx.tcx
|
|
|
|
}
|
|
|
|
|
2023-02-22 02:18:40 +00:00
|
|
|
fn try_fold_binder<T: TypeFoldable<TyCtxt<'tcx>>>(
|
2021-07-13 10:50:40 -04:00
|
|
|
&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);
|
2021-12-01 00:55:57 +00:00
|
|
|
let t = t.try_super_fold_with(self);
|
2021-07-13 10:50:40 -04:00
|
|
|
self.universes.pop();
|
|
|
|
t
|
|
|
|
}
|
|
|
|
|
2021-01-24 00:00:00 +00:00
|
|
|
#[instrument(level = "debug", skip(self))]
|
2021-12-01 00:55:57 +00:00
|
|
|
fn try_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) {
|
Overhaul `TyS` and `Ty`.
Specifically, change `Ty` from this:
```
pub type Ty<'tcx> = &'tcx TyS<'tcx>;
```
to this
```
pub struct Ty<'tcx>(Interned<'tcx, TyS<'tcx>>);
```
There are two benefits to this.
- It's now a first class type, so we can define methods on it. This
means we can move a lot of methods away from `TyS`, leaving `TyS` as a
barely-used type, which is appropriate given that it's not meant to
be used directly.
- The uniqueness requirement is now explicit, via the `Interned` type.
E.g. the pointer-based `Eq` and `Hash` comes from `Interned`, rather
than via `TyS`, which wasn't obvious at all.
Much of this commit is boring churn. The interesting changes are in
these files:
- compiler/rustc_middle/src/arena.rs
- compiler/rustc_middle/src/mir/visit.rs
- compiler/rustc_middle/src/ty/context.rs
- compiler/rustc_middle/src/ty/mod.rs
Specifically:
- Most mentions of `TyS` are removed. It's very much a dumb struct now;
`Ty` has all the smarts.
- `TyS` now has `crate` visibility instead of `pub`.
- `TyS::make_for_test` is removed in favour of the static `BOOL_TY`,
which just works better with the new structure.
- The `Eq`/`Ord`/`Hash` impls are removed from `TyS`. `Interned`s impls
of `Eq`/`Hash` now suffice. `Ord` is now partly on `Interned`
(pointer-based, for the `Equal` case) and partly on `TyS`
(contents-based, for the other cases).
- There are many tedious sigil adjustments, i.e. adding or removing `*`
or `&`. They seem to be unavoidable.
2022-01-25 14:13:38 +11:00
|
|
|
return Ok(*ty);
|
2020-09-19 17:27:13 +02:00
|
|
|
}
|
|
|
|
|
2023-03-07 10:21:20 +00:00
|
|
|
let (kind, data) = match *ty.kind() {
|
|
|
|
ty::Alias(kind, data) => (kind, data),
|
|
|
|
_ => {
|
|
|
|
let res = ty.try_super_fold_with(self)?;
|
|
|
|
self.cache.insert(ty, res);
|
|
|
|
return Ok(res);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-08-24 22:26:48 -04:00
|
|
|
// See note in `rustc_trait_selection::traits::project` about why we
|
2023-07-11 22:35:29 +01:00
|
|
|
// wait to fold the args.
|
2021-05-03 09:25:32 -04:00
|
|
|
|
|
|
|
// Wrap this in a closure so we don't accidentally return from the outer function
|
2023-03-07 10:21:20 +00:00
|
|
|
let res = match kind {
|
2023-06-21 02:22:55 +00:00
|
|
|
ty::Opaque => {
|
2021-10-25 15:43:07 -05:00
|
|
|
// Only normalize `impl Trait` outside of type inference, usually in codegen.
|
2020-07-02 20:52:40 -04:00
|
|
|
match self.param_env.reveal() {
|
2023-01-09 15:15:26 +00:00
|
|
|
Reveal::UserFacing => ty.try_super_fold_with(self)?,
|
2018-02-25 10:58:54 -05:00
|
|
|
|
|
|
|
Reveal::All => {
|
2023-07-11 22:35:29 +01:00
|
|
|
let args = data.args.try_fold_with(self)?;
|
2024-06-18 19:13:54 -04:00
|
|
|
let recursion_limit = self.cx().recursion_limit();
|
2023-10-30 19:24:08 +00:00
|
|
|
|
2020-05-26 19:48:08 +01:00
|
|
|
if !recursion_limit.value_within_limit(self.anon_depth) {
|
2023-10-30 19:24:08 +00:00
|
|
|
let guar = self
|
|
|
|
.infcx
|
2022-09-11 11:22:47 +02:00
|
|
|
.err_ctxt()
|
2024-01-15 15:06:25 +01:00
|
|
|
.build_overflow_error(
|
2024-05-13 10:00:38 -04:00
|
|
|
OverflowCause::DeeplyNormalize(data.into()),
|
2024-01-15 15:06:25 +01:00
|
|
|
self.cause.span,
|
|
|
|
true,
|
|
|
|
)
|
2022-09-11 11:22:47 +02:00
|
|
|
.delay_as_bug();
|
2024-06-18 19:13:54 -04:00
|
|
|
return Ok(Ty::new_error(self.cx(), guar));
|
2018-02-25 10:58:54 -05:00
|
|
|
}
|
|
|
|
|
2024-06-18 19:13:54 -04:00
|
|
|
let generic_ty = self.cx().type_of(data.def_id);
|
|
|
|
let mut concrete_ty = generic_ty.instantiate(self.cx(), args);
|
2018-02-25 10:58:54 -05:00
|
|
|
self.anon_depth += 1;
|
2018-05-22 14:31:56 +02:00
|
|
|
if concrete_ty == ty {
|
2023-11-08 06:56:06 +00:00
|
|
|
concrete_ty = Ty::new_error_with_message(
|
2024-06-18 19:13:54 -04:00
|
|
|
self.cx(),
|
2023-11-08 06:56:06 +00:00
|
|
|
DUMMY_SP,
|
|
|
|
"recursive opaque type",
|
2018-08-22 00:24:03 -04:00
|
|
|
);
|
2018-05-22 14:31:56 +02:00
|
|
|
}
|
2021-12-01 00:55:57 +00:00
|
|
|
let folded_ty = ensure_sufficient_stack(|| self.try_fold_ty(concrete_ty));
|
2018-02-25 10:58:54 -05:00
|
|
|
self.anon_depth -= 1;
|
2023-01-09 15:15:26 +00:00
|
|
|
folded_ty?
|
2018-02-25 10:58:54 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-07 12:03:11 +00:00
|
|
|
ty::Projection | ty::Inherent | ty::Weak => {
|
2021-05-03 09:25:32 -04:00
|
|
|
// 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 infcx = self.infcx;
|
2023-03-21 01:46:52 +01:00
|
|
|
let tcx = infcx.tcx;
|
2023-03-08 08:46:15 +00:00
|
|
|
// Just an optimization: When we don't have escaping bound vars,
|
|
|
|
// we don't need to replace them with placeholders.
|
|
|
|
let (data, maps) = if data.has_escaping_bound_vars() {
|
|
|
|
let (data, mapped_regions, mapped_types, mapped_consts) =
|
|
|
|
BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, data);
|
|
|
|
(data, Some((mapped_regions, mapped_types, mapped_consts)))
|
|
|
|
} else {
|
|
|
|
(data, None)
|
|
|
|
};
|
Folding revamp.
This commit makes type folding more like the way chalk does it.
Currently, `TypeFoldable` has `fold_with` and `super_fold_with` methods.
- `fold_with` is the standard entry point, and defaults to calling
`super_fold_with`.
- `super_fold_with` does the actual work of traversing a type.
- For a few types of interest (`Ty`, `Region`, etc.) `fold_with` instead
calls into a `TypeFolder`, which can then call back into
`super_fold_with`.
With the new approach, `TypeFoldable` has `fold_with` and
`TypeSuperFoldable` has `super_fold_with`.
- `fold_with` is still the standard entry point, *and* it does the
actual work of traversing a type, for all types except types of
interest.
- `super_fold_with` is only implemented for the types of interest.
Benefits of the new model.
- I find it easier to understand. The distinction between types of
interest and other types is clearer, and `super_fold_with` doesn't
exist for most types.
- With the current model is easy to get confused and implement a
`super_fold_with` method that should be left defaulted. (Some of the
precursor commits fixed such cases.)
- With the current model it's easy to call `super_fold_with` within
`TypeFolder` impls where `fold_with` should be called. The new
approach makes this mistake impossible, and this commit fixes a number
of such cases.
- It's potentially faster, because it avoids the `fold_with` ->
`super_fold_with` call in all cases except types of interest. A lot of
the time the compile would inline those away, but not necessarily
always.
2022-06-02 11:38:15 +10:00
|
|
|
let data = data.try_fold_with(self)?;
|
2021-07-09 00:04:47 -04:00
|
|
|
|
|
|
|
let mut orig_values = OriginalQueryValues::default();
|
2023-12-15 06:02:40 +00:00
|
|
|
let c_data = infcx.canonicalize_query(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);
|
2023-03-21 01:46:52 +01:00
|
|
|
let result = match kind {
|
2024-02-20 10:34:51 +01:00
|
|
|
ty::Projection => tcx.normalize_canonicalized_projection_ty(c_data),
|
|
|
|
ty::Weak => tcx.normalize_canonicalized_weak_ty(c_data),
|
|
|
|
ty::Inherent => tcx.normalize_canonicalized_inherent_projection_ty(c_data),
|
2023-12-15 03:19:46 +00:00
|
|
|
kind => unreachable!("did not expect {kind:?} due to match arm above"),
|
2023-03-21 01:46:52 +01:00
|
|
|
}?;
|
2021-05-19 23:08:32 +02:00
|
|
|
// We don't expect ambiguity.
|
2023-10-20 21:07:30 -07:00
|
|
|
if !result.value.is_proven() {
|
2022-10-21 18:53:16 +00:00
|
|
|
// Rustdoc normalizes possibly not well-formed types, so only
|
|
|
|
// treat this as a bug if we're not in rustdoc.
|
|
|
|
if !tcx.sess.opts.actually_rustdoc {
|
2024-01-04 12:54:23 +11:00
|
|
|
tcx.dcx()
|
|
|
|
.delayed_bug(format!("unexpected ambiguity: {c_data:?} {result:?}"));
|
2022-10-21 18:53:16 +00:00
|
|
|
}
|
|
|
|
return Err(NoSolution);
|
2021-08-24 22:26:48 -04:00
|
|
|
}
|
2023-03-21 01:46:52 +01:00
|
|
|
let InferOk { value: result, obligations } = infcx
|
|
|
|
.instantiate_query_response_and_region_obligations(
|
2021-05-19 23:08:32 +02:00
|
|
|
self.cause,
|
|
|
|
self.param_env,
|
|
|
|
&orig_values,
|
|
|
|
result,
|
|
|
|
)?;
|
|
|
|
debug!("QueryNormalizer: result = {:#?}", result);
|
|
|
|
debug!("QueryNormalizer: obligations = {:#?}", obligations);
|
|
|
|
self.obligations.extend(obligations);
|
2023-03-08 08:46:15 +00:00
|
|
|
let res = if let Some((mapped_regions, mapped_types, mapped_consts)) = maps {
|
|
|
|
PlaceholderReplacer::replace_placeholders(
|
|
|
|
infcx,
|
|
|
|
mapped_regions,
|
|
|
|
mapped_types,
|
|
|
|
mapped_consts,
|
|
|
|
&self.universes,
|
|
|
|
result.normalized_ty,
|
|
|
|
)
|
|
|
|
} else {
|
|
|
|
result.normalized_ty
|
|
|
|
};
|
2024-02-20 10:34:51 +01:00
|
|
|
// `tcx.normalize_canonicalized_projection_ty` may normalize to a type that
|
|
|
|
// still has unevaluated consts, so keep normalizing here if that's the case.
|
|
|
|
// Similarly, `tcx.normalize_canonicalized_weak_ty` will only unwrap one layer
|
|
|
|
// of type and we need to continue folding it to reveal the TAIT behind it.
|
2023-06-18 20:56:30 +00:00
|
|
|
if res != ty
|
|
|
|
&& (res.has_type_flags(ty::TypeFlags::HAS_CT_PROJECTION) || kind == ty::Weak)
|
|
|
|
{
|
|
|
|
res.try_fold_with(self)?
|
2022-08-09 18:19:58 +00:00
|
|
|
} else {
|
2023-01-09 15:15:26 +00:00
|
|
|
res
|
2022-08-09 18:19:58 +00:00
|
|
|
}
|
2021-07-09 00:04:47 -04:00
|
|
|
}
|
2023-01-09 15:15:26 +00:00
|
|
|
};
|
2022-08-09 09:41:23 +00: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-12-01 00:55:57 +00:00
|
|
|
fn try_fold_const(
|
2021-05-19 15:01:30 +02:00
|
|
|
&mut self,
|
2022-02-02 14:24:45 +11:00
|
|
|
constant: ty::Const<'tcx>,
|
|
|
|
) -> Result<ty::Const<'tcx>, Self::Error> {
|
2022-11-06 17:14:05 +00:00
|
|
|
if !needs_normalization(&constant, self.param_env.reveal()) {
|
|
|
|
return Ok(constant);
|
|
|
|
}
|
|
|
|
|
2024-08-17 20:45:45 +02:00
|
|
|
let constant = crate::traits::with_replaced_escaping_bound_vars(
|
2022-07-04 18:38:35 +02:00
|
|
|
self.infcx,
|
|
|
|
&mut self.universes,
|
|
|
|
constant,
|
2023-09-12 23:28:25 +02:00
|
|
|
|constant| constant.normalize(self.infcx.tcx, self.param_env),
|
2024-08-17 20:45:45 +02:00
|
|
|
);
|
|
|
|
debug!(?constant, ?self.param_env);
|
|
|
|
constant.try_super_fold_with(self)
|
2018-02-25 10:58:54 -05:00
|
|
|
}
|
2021-03-30 14:26:40 +00:00
|
|
|
|
2022-07-13 19:42:08 +02:00
|
|
|
#[inline]
|
|
|
|
fn try_fold_predicate(
|
|
|
|
&mut self,
|
|
|
|
p: ty::Predicate<'tcx>,
|
|
|
|
) -> Result<ty::Predicate<'tcx>, Self::Error> {
|
|
|
|
if p.allow_normalization() && needs_normalization(&p, self.param_env.reveal()) {
|
|
|
|
p.try_super_fold_with(self)
|
|
|
|
} else {
|
|
|
|
Ok(p)
|
|
|
|
}
|
|
|
|
}
|
2018-02-25 10:58:54 -05:00
|
|
|
}
|