summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_trait_selection/src/traits/query/normalize.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_trait_selection/src/traits/query/normalize.rs')
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/normalize.rs32
1 files changed, 21 insertions, 11 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
index 8bf934cb7..7fe79fd86 100644
--- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
@@ -30,7 +30,7 @@ pub trait QueryNormalizeExt<'tcx> {
///
/// After codegen, when lifetimes do not matter, it is preferable to instead
/// use [`TyCtxt::normalize_erasing_regions`], which wraps this procedure.
- fn query_normalize<T>(&self, value: T) -> Result<Normalized<'tcx, T>, NoSolution>
+ fn query_normalize<T>(self, value: T) -> Result<Normalized<'tcx, T>, NoSolution>
where
T: TypeFoldable<TyCtxt<'tcx>>;
}
@@ -49,7 +49,7 @@ impl<'cx, 'tcx> QueryNormalizeExt<'tcx> for At<'cx, 'tcx> {
/// 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".
- fn query_normalize<T>(&self, value: T) -> Result<Normalized<'tcx, T>, NoSolution>
+ fn query_normalize<T>(self, value: T) -> Result<Normalized<'tcx, T>, NoSolution>
where
T: TypeFoldable<TyCtxt<'tcx>>,
{
@@ -60,6 +60,16 @@ impl<'cx, 'tcx> QueryNormalizeExt<'tcx> for At<'cx, 'tcx> {
self.param_env,
self.cause,
);
+
+ if self.infcx.next_trait_solver() {
+ match crate::solve::deeply_normalize(self, value) {
+ Ok(value) => return Ok(Normalized { value, obligations: vec![] }),
+ Err(_errors) => {
+ return Err(NoSolution);
+ }
+ }
+ }
+
if !needs_normalization(&value, self.param_env.reveal()) {
return Ok(Normalized { value, obligations: vec![] });
}
@@ -211,10 +221,7 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx>
// Wrap this in a closure so we don't accidentally return from the outer function
let res = match kind {
- // 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 if !data.substs.has_escaping_bound_vars() => {
+ ty::Opaque => {
// Only normalize `impl Trait` outside of type inference, usually in codegen.
match self.param_env.reveal() {
Reveal::UserFacing => ty.try_super_fold_with(self)?,
@@ -255,9 +262,7 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx>
}
}
- ty::Opaque => ty.try_super_fold_with(self)?,
-
- ty::Projection | ty::Inherent => {
+ ty::Projection | ty::Inherent | ty::Weak => {
// See note in `rustc_trait_selection::traits::project`
let infcx = self.infcx;
@@ -282,6 +287,7 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx>
debug!("QueryNormalizer: orig_values = {:#?}", orig_values);
let result = match kind {
ty::Projection => tcx.normalize_projection_ty(c_data),
+ ty::Weak => tcx.normalize_weak_ty(c_data),
ty::Inherent => tcx.normalize_inherent_projection_ty(c_data),
_ => unreachable!(),
}?;
@@ -321,8 +327,12 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx>
};
// `tcx.normalize_projection_ty` may normalize to a type that still has
// unevaluated consts, so keep normalizing here if that's the case.
- if res != ty && res.has_type_flags(ty::TypeFlags::HAS_CT_PROJECTION) {
- res.try_super_fold_with(self)?
+ // Similarly, `tcx.normalize_weak_ty` will only unwrap one layer of type
+ // and we need to continue folding it to reveal the TAIT behind it.
+ if res != ty
+ && (res.has_type_flags(ty::TypeFlags::HAS_CT_PROJECTION) || kind == ty::Weak)
+ {
+ res.try_fold_with(self)?
} else {
res
}