1 //! Methods for normalizing when you don't care about regions (and
2 //! aren't doing type inference). If either of those things don't
3 //! apply to you, use `infcx.normalize(...)`.
5 //! The methods in this file use a `TypeFolder` to recursively process
6 //! contents, invoking the underlying
7 //! `normalize_generic_arg_after_erasing_regions` query for each type
8 //! or constant found within. (This underlying query is what is cached.)
10 use crate::traits
::query
::NoSolution
;
11 use crate::ty
::fold
::{FallibleTypeFolder, TypeFoldable, TypeFolder}
;
12 use crate::ty
::{self, EarlyBinder, SubstsRef, Ty, TyCtxt, TypeVisitableExt}
;
14 #[derive(Debug, Copy, Clone, HashStable, TyEncodable, TyDecodable)]
15 pub enum NormalizationError
<'tcx
> {
17 Const(ty
::Const
<'tcx
>),
20 impl<'tcx
> NormalizationError
<'tcx
> {
21 pub fn get_type_for_failure(&self) -> String
{
23 NormalizationError
::Type(t
) => format
!("{}", t
),
24 NormalizationError
::Const(c
) => format
!("{}", c
),
29 impl<'tcx
> TyCtxt
<'tcx
> {
30 /// Erase the regions in `value` and then fully normalize all the
31 /// types found within. The result will also have regions erased.
33 /// This should only be used outside of type inference. For example,
34 /// it assumes that normalization will succeed.
35 #[tracing::instrument(level = "debug", skip(self, param_env), ret)]
36 pub fn normalize_erasing_regions
<T
>(self, param_env
: ty
::ParamEnv
<'tcx
>, value
: T
) -> T
38 T
: TypeFoldable
<TyCtxt
<'tcx
>>,
41 "normalize_erasing_regions::<{}>(value={:?}, param_env={:?})",
42 std
::any
::type_name
::<T
>(),
47 // Erase first before we do the real query -- this keeps the
48 // cache from being too polluted.
49 let value
= self.erase_regions(value
);
52 if !value
.has_projections() {
55 value
.fold_with(&mut NormalizeAfterErasingRegionsFolder { tcx: self, param_env }
)
59 /// Tries to erase the regions in `value` and then fully normalize all the
60 /// types found within. The result will also have regions erased.
62 /// Contrary to `normalize_erasing_regions` this function does not assume that normalization
64 pub fn try_normalize_erasing_regions
<T
>(
66 param_env
: ty
::ParamEnv
<'tcx
>,
68 ) -> Result
<T
, NormalizationError
<'tcx
>>
70 T
: TypeFoldable
<TyCtxt
<'tcx
>>,
73 "try_normalize_erasing_regions::<{}>(value={:?}, param_env={:?})",
74 std
::any
::type_name
::<T
>(),
79 // Erase first before we do the real query -- this keeps the
80 // cache from being too polluted.
81 let value
= self.erase_regions(value
);
84 if !value
.has_projections() {
87 let mut folder
= TryNormalizeAfterErasingRegionsFolder
::new(self, param_env
);
88 value
.try_fold_with(&mut folder
)
92 /// If you have a `Binder<'tcx, T>`, you can do this to strip out the
93 /// late-bound regions and then normalize the result, yielding up
94 /// a `T` (with regions erased). This is appropriate when the
95 /// binder is being instantiated at the call site.
97 /// N.B., currently, higher-ranked type bounds inhibit
98 /// normalization. Therefore, each time we erase them in
99 /// codegen, we need to normalize the contents.
100 #[tracing::instrument(level = "debug", skip(self, param_env))]
101 pub fn normalize_erasing_late_bound_regions
<T
>(
103 param_env
: ty
::ParamEnv
<'tcx
>,
104 value
: ty
::Binder
<'tcx
, T
>,
107 T
: TypeFoldable
<TyCtxt
<'tcx
>>,
109 let value
= self.erase_late_bound_regions(value
);
110 self.normalize_erasing_regions(param_env
, value
)
113 /// If you have a `Binder<'tcx, T>`, you can do this to strip out the
114 /// late-bound regions and then normalize the result, yielding up
115 /// a `T` (with regions erased). This is appropriate when the
116 /// binder is being instantiated at the call site.
118 /// N.B., currently, higher-ranked type bounds inhibit
119 /// normalization. Therefore, each time we erase them in
120 /// codegen, we need to normalize the contents.
121 pub fn try_normalize_erasing_late_bound_regions
<T
>(
123 param_env
: ty
::ParamEnv
<'tcx
>,
124 value
: ty
::Binder
<'tcx
, T
>,
125 ) -> Result
<T
, NormalizationError
<'tcx
>>
127 T
: TypeFoldable
<TyCtxt
<'tcx
>>,
129 let value
= self.erase_late_bound_regions(value
);
130 self.try_normalize_erasing_regions(param_env
, value
)
133 /// Monomorphizes a type from the AST by first applying the
134 /// in-scope substitutions and then normalizing any associated
136 /// Panics if normalization fails. In case normalization might fail
137 /// use `try_subst_and_normalize_erasing_regions` instead.
138 pub fn subst_and_normalize_erasing_regions
<T
>(
140 param_substs
: SubstsRef
<'tcx
>,
141 param_env
: ty
::ParamEnv
<'tcx
>,
142 value
: EarlyBinder
<T
>,
145 T
: TypeFoldable
<TyCtxt
<'tcx
>>,
148 "subst_and_normalize_erasing_regions(\
152 param_substs
, value
, param_env
,
154 let substituted
= value
.subst(self, param_substs
);
155 self.normalize_erasing_regions(param_env
, substituted
)
158 /// Monomorphizes a type from the AST by first applying the
159 /// in-scope substitutions and then trying to normalize any associated
160 /// types. Contrary to `subst_and_normalize_erasing_regions` this does
161 /// not assume that normalization succeeds.
162 pub fn try_subst_and_normalize_erasing_regions
<T
>(
164 param_substs
: SubstsRef
<'tcx
>,
165 param_env
: ty
::ParamEnv
<'tcx
>,
166 value
: EarlyBinder
<T
>,
167 ) -> Result
<T
, NormalizationError
<'tcx
>>
169 T
: TypeFoldable
<TyCtxt
<'tcx
>>,
172 "subst_and_normalize_erasing_regions(\
176 param_substs
, value
, param_env
,
178 let substituted
= value
.subst(self, param_substs
);
179 self.try_normalize_erasing_regions(param_env
, substituted
)
183 struct NormalizeAfterErasingRegionsFolder
<'tcx
> {
185 param_env
: ty
::ParamEnv
<'tcx
>,
188 impl<'tcx
> NormalizeAfterErasingRegionsFolder
<'tcx
> {
189 fn normalize_generic_arg_after_erasing_regions(
191 arg
: ty
::GenericArg
<'tcx
>,
192 ) -> ty
::GenericArg
<'tcx
> {
193 let arg
= self.param_env
.and(arg
);
195 self.tcx
.try_normalize_generic_arg_after_erasing_regions(arg
).unwrap_or_else(|_
| bug
!(
196 "Failed to normalize {:?}, maybe try to call `try_normalize_erasing_regions` instead",
202 impl<'tcx
> TypeFolder
<TyCtxt
<'tcx
>> for NormalizeAfterErasingRegionsFolder
<'tcx
> {
203 fn interner(&self) -> TyCtxt
<'tcx
> {
207 fn fold_ty(&mut self, ty
: Ty
<'tcx
>) -> Ty
<'tcx
> {
208 self.normalize_generic_arg_after_erasing_regions(ty
.into()).expect_ty()
211 fn fold_const(&mut self, c
: ty
::Const
<'tcx
>) -> ty
::Const
<'tcx
> {
212 self.normalize_generic_arg_after_erasing_regions(c
.into()).expect_const()
216 struct TryNormalizeAfterErasingRegionsFolder
<'tcx
> {
218 param_env
: ty
::ParamEnv
<'tcx
>,
221 impl<'tcx
> TryNormalizeAfterErasingRegionsFolder
<'tcx
> {
222 fn new(tcx
: TyCtxt
<'tcx
>, param_env
: ty
::ParamEnv
<'tcx
>) -> Self {
223 TryNormalizeAfterErasingRegionsFolder { tcx, param_env }
226 #[instrument(skip(self), level = "debug")]
227 fn try_normalize_generic_arg_after_erasing_regions(
229 arg
: ty
::GenericArg
<'tcx
>,
230 ) -> Result
<ty
::GenericArg
<'tcx
>, NoSolution
> {
231 let arg
= self.param_env
.and(arg
);
234 self.tcx
.try_normalize_generic_arg_after_erasing_regions(arg
)
238 impl<'tcx
> FallibleTypeFolder
<TyCtxt
<'tcx
>> for TryNormalizeAfterErasingRegionsFolder
<'tcx
> {
239 type Error
= NormalizationError
<'tcx
>;
241 fn interner(&self) -> TyCtxt
<'tcx
> {
245 fn try_fold_ty(&mut self, ty
: Ty
<'tcx
>) -> Result
<Ty
<'tcx
>, Self::Error
> {
246 match self.try_normalize_generic_arg_after_erasing_regions(ty
.into()) {
247 Ok(t
) => Ok(t
.expect_ty()),
248 Err(_
) => Err(NormalizationError
::Type(ty
)),
252 fn try_fold_const(&mut self, c
: ty
::Const
<'tcx
>) -> Result
<ty
::Const
<'tcx
>, Self::Error
> {
253 match self.try_normalize_generic_arg_after_erasing_regions(c
.into()) {
254 Ok(t
) => Ok(t
.expect_const()),
255 Err(_
) => Err(NormalizationError
::Const(c
)),