]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
New upstream version 1.60.0+dfsg1
[rustc.git] / compiler / rustc_middle / src / ty / normalize_erasing_regions.rs
CommitLineData
0531ce1d
XL
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(...)`.
4//!
5//! The methods in this file use a `TypeFolder` to recursively process
6//! contents, invoking the underlying
ba9703b0
XL
7//! `normalize_generic_arg_after_erasing_regions` query for each type
8//! or constant found within. (This underlying query is what is cached.)
0531ce1d 9
cdc7bbd5 10use crate::mir;
a2a8927a
XL
11use crate::traits::query::NoSolution;
12use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder};
dfeec247
XL
13use crate::ty::subst::{Subst, SubstsRef};
14use crate::ty::{self, Ty, TyCtxt};
0531ce1d 15
a2a8927a
XL
16#[derive(Debug, Copy, Clone, HashStable, TyEncodable, TyDecodable)]
17pub enum NormalizationError<'tcx> {
18 Type(Ty<'tcx>),
19 Const(ty::Const<'tcx>),
20 ConstantKind(mir::ConstantKind<'tcx>),
21}
22
23impl<'tcx> NormalizationError<'tcx> {
24 pub fn get_type_for_failure(&self) -> String {
25 match self {
26 NormalizationError::Type(t) => format!("{}", t),
27 NormalizationError::Const(c) => format!("{}", c),
28 NormalizationError::ConstantKind(ck) => format!("{}", ck),
29 }
30 }
31}
32
dc9dc135 33impl<'tcx> TyCtxt<'tcx> {
0531ce1d
XL
34 /// Erase the regions in `value` and then fully normalize all the
35 /// types found within. The result will also have regions erased.
36 ///
5099ac24
FG
37 /// This should only be used outside of type inference. For example,
38 /// it assumes that normalization will succeed.
0531ce1d
XL
39 pub fn normalize_erasing_regions<T>(self, param_env: ty::ParamEnv<'tcx>, value: T) -> T
40 where
41 T: TypeFoldable<'tcx>,
42 {
43 debug!(
44 "normalize_erasing_regions::<{}>(value={:?}, param_env={:?})",
29967ef6 45 std::any::type_name::<T>(),
0531ce1d
XL
46 value,
47 param_env,
48 );
49
50 // Erase first before we do the real query -- this keeps the
51 // cache from being too polluted.
fc512014 52 let value = self.erase_regions(value);
a2a8927a
XL
53 debug!(?value);
54
0531ce1d
XL
55 if !value.has_projections() {
56 value
57 } else {
74b04a01 58 value.fold_with(&mut NormalizeAfterErasingRegionsFolder { tcx: self, param_env })
0531ce1d
XL
59 }
60 }
61
a2a8927a
XL
62 /// Tries to erase the regions in `value` and then fully normalize all the
63 /// types found within. The result will also have regions erased.
64 ///
65 /// Contrary to `normalize_erasing_regions` this function does not assume that normalization
66 /// succeeds.
67 pub fn try_normalize_erasing_regions<T>(
68 self,
69 param_env: ty::ParamEnv<'tcx>,
70 value: T,
71 ) -> Result<T, NormalizationError<'tcx>>
72 where
73 T: TypeFoldable<'tcx>,
74 {
75 debug!(
76 "try_normalize_erasing_regions::<{}>(value={:?}, param_env={:?})",
77 std::any::type_name::<T>(),
78 value,
79 param_env,
80 );
81
82 // Erase first before we do the real query -- this keeps the
83 // cache from being too polluted.
84 let value = self.erase_regions(value);
85 debug!(?value);
86
87 if !value.has_projections() {
88 Ok(value)
89 } else {
90 let mut folder = TryNormalizeAfterErasingRegionsFolder::new(self, param_env);
91 value.try_fold_with(&mut folder)
92 }
93 }
94
cdc7bbd5 95 /// If you have a `Binder<'tcx, T>`, you can do this to strip out the
0531ce1d
XL
96 /// late-bound regions and then normalize the result, yielding up
97 /// a `T` (with regions erased). This is appropriate when the
98 /// binder is being instantiated at the call site.
99 ///
9fa01778 100 /// N.B., currently, higher-ranked type bounds inhibit
0531ce1d 101 /// normalization. Therefore, each time we erase them in
94b46f34 102 /// codegen, we need to normalize the contents.
0531ce1d
XL
103 pub fn normalize_erasing_late_bound_regions<T>(
104 self,
105 param_env: ty::ParamEnv<'tcx>,
cdc7bbd5 106 value: ty::Binder<'tcx, T>,
0531ce1d
XL
107 ) -> T
108 where
109 T: TypeFoldable<'tcx>,
110 {
0531ce1d
XL
111 let value = self.erase_late_bound_regions(value);
112 self.normalize_erasing_regions(param_env, value)
113 }
dfeec247
XL
114
115 /// Monomorphizes a type from the AST by first applying the
116 /// in-scope substitutions and then normalizing any associated
117 /// types.
a2a8927a
XL
118 /// Panics if normalization fails. In case normalization might fail
119 /// use `try_subst_and_normalize_erasing_regions` instead.
dfeec247
XL
120 pub fn subst_and_normalize_erasing_regions<T>(
121 self,
122 param_substs: SubstsRef<'tcx>,
123 param_env: ty::ParamEnv<'tcx>,
fc512014 124 value: T,
dfeec247
XL
125 ) -> T
126 where
127 T: TypeFoldable<'tcx>,
128 {
129 debug!(
130 "subst_and_normalize_erasing_regions(\
131 param_substs={:?}, \
132 value={:?}, \
133 param_env={:?})",
134 param_substs, value, param_env,
135 );
136 let substituted = value.subst(self, param_substs);
137 self.normalize_erasing_regions(param_env, substituted)
138 }
a2a8927a
XL
139
140 /// Monomorphizes a type from the AST by first applying the
141 /// in-scope substitutions and then trying to normalize any associated
142 /// types. Contrary to `subst_and_normalize_erasing_regions` this does
143 /// not assume that normalization succeeds.
144 pub fn try_subst_and_normalize_erasing_regions<T>(
145 self,
146 param_substs: SubstsRef<'tcx>,
147 param_env: ty::ParamEnv<'tcx>,
148 value: T,
149 ) -> Result<T, NormalizationError<'tcx>>
150 where
151 T: TypeFoldable<'tcx>,
152 {
153 debug!(
154 "subst_and_normalize_erasing_regions(\
155 param_substs={:?}, \
156 value={:?}, \
157 param_env={:?})",
158 param_substs, value, param_env,
159 );
160 let substituted = value.subst(self, param_substs);
161 self.try_normalize_erasing_regions(param_env, substituted)
162 }
0531ce1d
XL
163}
164
dc9dc135
XL
165struct NormalizeAfterErasingRegionsFolder<'tcx> {
166 tcx: TyCtxt<'tcx>,
0531ce1d
XL
167 param_env: ty::ParamEnv<'tcx>,
168}
169
136023e0 170impl<'tcx> NormalizeAfterErasingRegionsFolder<'tcx> {
a2a8927a 171 #[instrument(skip(self), level = "debug")]
136023e0
XL
172 fn normalize_generic_arg_after_erasing_regions(
173 &self,
174 arg: ty::GenericArg<'tcx>,
175 ) -> ty::GenericArg<'tcx> {
176 let arg = self.param_env.and(arg);
a2a8927a
XL
177 debug!(?arg);
178
179 self.tcx.try_normalize_generic_arg_after_erasing_regions(arg).unwrap_or_else(|_| bug!(
180 "Failed to normalize {:?}, maybe try to call `try_normalize_erasing_regions` instead",
181 arg.value
182 ))
136023e0
XL
183 }
184}
185
a2a8927a 186impl<'tcx> TypeFolder<'tcx> for NormalizeAfterErasingRegionsFolder<'tcx> {
dc9dc135 187 fn tcx(&self) -> TyCtxt<'tcx> {
0531ce1d
XL
188 self.tcx
189 }
190
191 fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
136023e0 192 self.normalize_generic_arg_after_erasing_regions(ty.into()).expect_ty()
ba9703b0
XL
193 }
194
5099ac24 195 fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> {
136023e0 196 self.normalize_generic_arg_after_erasing_regions(c.into()).expect_const()
0531ce1d 197 }
cdc7bbd5
XL
198
199 #[inline]
200 fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> {
136023e0 201 // FIXME: This *probably* needs canonicalization too!
cdc7bbd5 202 let arg = self.param_env.and(c);
a2a8927a
XL
203 self.tcx
204 .try_normalize_mir_const_after_erasing_regions(arg)
205 .unwrap_or_else(|_| bug!("failed to normalize {:?}", c))
206 }
207}
208
209struct TryNormalizeAfterErasingRegionsFolder<'tcx> {
210 tcx: TyCtxt<'tcx>,
211 param_env: ty::ParamEnv<'tcx>,
212}
213
214impl<'tcx> TryNormalizeAfterErasingRegionsFolder<'tcx> {
215 fn new(tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Self {
216 TryNormalizeAfterErasingRegionsFolder { tcx, param_env }
217 }
218
219 #[instrument(skip(self), level = "debug")]
220 fn try_normalize_generic_arg_after_erasing_regions(
221 &self,
222 arg: ty::GenericArg<'tcx>,
223 ) -> Result<ty::GenericArg<'tcx>, NoSolution> {
224 let arg = self.param_env.and(arg);
225 debug!(?arg);
226
227 self.tcx.try_normalize_generic_arg_after_erasing_regions(arg)
228 }
229}
230
231impl<'tcx> TypeFolder<'tcx> for TryNormalizeAfterErasingRegionsFolder<'tcx> {
232 type Error = NormalizationError<'tcx>;
233
234 fn tcx(&self) -> TyCtxt<'tcx> {
235 self.tcx
236 }
237}
238
239impl<'tcx> FallibleTypeFolder<'tcx> for TryNormalizeAfterErasingRegionsFolder<'tcx> {
240 fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
241 match self.try_normalize_generic_arg_after_erasing_regions(ty.into()) {
242 Ok(t) => Ok(t.expect_ty()),
243 Err(_) => Err(NormalizationError::Type(ty)),
244 }
245 }
246
5099ac24 247 fn try_fold_const(&mut self, c: ty::Const<'tcx>) -> Result<ty::Const<'tcx>, Self::Error> {
a2a8927a
XL
248 match self.try_normalize_generic_arg_after_erasing_regions(c.into()) {
249 Ok(t) => Ok(t.expect_const()),
5099ac24 250 Err(_) => Err(NormalizationError::Const(c)),
a2a8927a
XL
251 }
252 }
253
254 fn try_fold_mir_const(
255 &mut self,
256 c: mir::ConstantKind<'tcx>,
257 ) -> Result<mir::ConstantKind<'tcx>, Self::Error> {
258 // FIXME: This *probably* needs canonicalization too!
259 let arg = self.param_env.and(c);
260 match self.tcx.try_normalize_mir_const_after_erasing_regions(arg) {
261 Ok(c) => Ok(c),
262 Err(_) => Err(NormalizationError::ConstantKind(c)),
263 }
cdc7bbd5 264 }
0531ce1d 265}