Skip to content

Commit 1f5a006

Browse files
rework normalization
1 parent d368f0c commit 1f5a006

File tree

1 file changed

+55
-4
lines changed

1 file changed

+55
-4
lines changed

compiler/rustc_traits/src/normalize_erasing_regions.rs

+55-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
use rustc_infer::infer::TyCtxtInferExt;
22
use rustc_middle::traits::query::NoSolution;
33
use rustc_middle::ty::query::Providers;
4-
use rustc_middle::ty::{self, ParamEnvAnd, TyCtxt, TypeFoldable};
4+
use rustc_middle::ty::{
5+
self, FallibleTypeFolder, ParamEnvAnd, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable, TypeVisitable,
6+
};
57
use rustc_trait_selection::traits::query::normalize::AtExt;
68
use rustc_trait_selection::traits::{Normalized, ObligationCause};
79
use std::sync::atomic::Ordering;
@@ -16,17 +18,33 @@ pub(crate) fn provide(p: &mut Providers) {
1618
.normalize_generic_arg_after_erasing_regions
1719
.fetch_add(1, Ordering::Relaxed);
1820

19-
try_normalize_after_erasing_regions(tcx, goal)
21+
let ParamEnvAnd { param_env, value } = goal;
22+
23+
match value.unpack() {
24+
ty::GenericArgKind::Type(ty) => {
25+
let ty =
26+
ty.try_super_fold_with(&mut NormalizeDeeperFolder { tcx, param_env })?;
27+
if let ty::Projection(..) | ty::Opaque(..) = ty.kind() {
28+
Ok(try_normalize_after_erasing_regions(tcx, param_env, ty)?.into())
29+
} else {
30+
Ok(ty.into())
31+
}
32+
}
33+
ty::GenericArgKind::Const(_) => {
34+
try_normalize_after_erasing_regions(tcx, param_env, value)
35+
}
36+
ty::GenericArgKind::Lifetime(_) => unreachable!(),
37+
}
2038
},
2139
..*p
2240
};
2341
}
2442

2543
fn try_normalize_after_erasing_regions<'tcx, T: TypeFoldable<'tcx> + PartialEq + Copy>(
2644
tcx: TyCtxt<'tcx>,
27-
goal: ParamEnvAnd<'tcx, T>,
45+
param_env: ty::ParamEnv<'tcx>,
46+
value: T,
2847
) -> Result<T, NoSolution> {
29-
let ParamEnvAnd { param_env, value } = goal;
3048
let infcx = tcx.infer_ctxt().ignoring_regions().build();
3149
let cause = ObligationCause::dummy();
3250
match infcx.at(&cause, param_env).normalize(value) {
@@ -52,6 +70,39 @@ fn try_normalize_after_erasing_regions<'tcx, T: TypeFoldable<'tcx> + PartialEq +
5270
}
5371
}
5472

73+
struct NormalizeDeeperFolder<'tcx> {
74+
tcx: TyCtxt<'tcx>,
75+
param_env: ty::ParamEnv<'tcx>,
76+
}
77+
78+
impl<'tcx> FallibleTypeFolder<'tcx> for NormalizeDeeperFolder<'tcx> {
79+
type Error = NoSolution;
80+
81+
fn tcx(&self) -> TyCtxt<'tcx> {
82+
self.tcx
83+
}
84+
85+
fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
86+
if !ty.needs_normalization(self.param_env.reveal()) {
87+
return Ok(ty);
88+
}
89+
90+
let ty = ty.try_super_fold_with(self)?;
91+
if let ty::Projection(..) | ty::Opaque(..) = ty.kind() {
92+
Ok(self
93+
.tcx
94+
.try_normalize_generic_arg_after_erasing_regions(self.param_env.and(ty.into()))?
95+
.expect_ty())
96+
} else {
97+
Ok(ty)
98+
}
99+
}
100+
101+
fn try_fold_const(&mut self, c: ty::Const<'tcx>) -> Result<ty::Const<'tcx>, Self::Error> {
102+
try_normalize_after_erasing_regions(self.tcx, self.param_env, c)
103+
}
104+
}
105+
55106
fn not_outlives_predicate<'tcx>(p: ty::Predicate<'tcx>) -> bool {
56107
match p.kind().skip_binder() {
57108
ty::PredicateKind::RegionOutlives(..) | ty::PredicateKind::TypeOutlives(..) => false,

0 commit comments

Comments
 (0)