]>
Commit | Line | Data |
---|---|---|
0731742a | 1 | //! This module contains `TyKind` and its major components. |
e9174d1e | 2 | |
e1599b0c | 3 | #![allow(rustc::usage_of_ty_tykind)] |
416331ca | 4 | |
9fa01778 | 5 | use crate::infer::canonical::Canonical; |
2b03887a | 6 | use crate::ty::subst::{GenericArg, InternalSubsts, SubstsRef}; |
064997fb | 7 | use crate::ty::visit::ValidateBoundVars; |
923072b8 | 8 | use crate::ty::InferTy::*; |
5099ac24 | 9 | use crate::ty::{ |
353b0b11 FG |
10 | self, AdtDef, Discr, Term, Ty, TyCtxt, TypeFlags, TypeSuperVisitable, TypeVisitable, |
11 | TypeVisitableExt, TypeVisitor, | |
5099ac24 | 12 | }; |
923072b8 | 13 | use crate::ty::{List, ParamEnv}; |
f2b60f7d | 14 | use hir::def::DefKind; |
60c5eb7d | 15 | use polonius_engine::Atom; |
dfeec247 | 16 | use rustc_data_structures::captures::Captures; |
5099ac24 | 17 | use rustc_data_structures::intern::Interned; |
353b0b11 | 18 | use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg}; |
dfeec247 | 19 | use rustc_hir as hir; |
3dfed10e | 20 | use rustc_hir::def_id::DefId; |
487cf647 | 21 | use rustc_hir::LangItem; |
60c5eb7d XL |
22 | use rustc_index::vec::Idx; |
23 | use rustc_macros::HashStable; | |
2b03887a | 24 | use rustc_span::symbol::{kw, sym, Symbol}; |
487cf647 | 25 | use rustc_span::Span; |
353b0b11 FG |
26 | use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT}; |
27 | use rustc_target::spec::abi::{self, Abi}; | |
48663c56 | 28 | use std::borrow::Cow; |
476ff2be | 29 | use std::cmp::Ordering; |
5099ac24 | 30 | use std::fmt; |
532ac7d7 | 31 | use std::marker::PhantomData; |
5099ac24 | 32 | use std::ops::{ControlFlow, Deref, Range}; |
f9f354fc | 33 | use ty::util::IntTypeExt; |
e9174d1e | 34 | |
923072b8 FG |
35 | use rustc_type_ir::sty::TyKind::*; |
36 | use rustc_type_ir::RegionKind as IrRegionKind; | |
37 | use rustc_type_ir::TyKind as IrTyKind; | |
38 | ||
39 | // Re-export the `TyKind` from `rustc_type_ir` here for convenience | |
40 | #[rustc_diagnostic_item = "TyKind"] | |
41 | pub type TyKind<'tcx> = IrTyKind<TyCtxt<'tcx>>; | |
42 | pub type RegionKind<'tcx> = IrRegionKind<TyCtxt<'tcx>>; | |
43 | ||
3dfed10e | 44 | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)] |
064997fb | 45 | #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] |
e9174d1e SL |
46 | pub struct TypeAndMut<'tcx> { |
47 | pub ty: Ty<'tcx>, | |
48 | pub mutbl: hir::Mutability, | |
49 | } | |
50 | ||
3dfed10e | 51 | #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, TyEncodable, TyDecodable, Copy)] |
ba9703b0 | 52 | #[derive(HashStable)] |
e9174d1e SL |
53 | /// A "free" region `fr` can be interpreted as "some region |
54 | /// at least as big as the scope `fr.scope`". | |
55 | pub struct FreeRegion { | |
7cac9316 | 56 | pub scope: DefId, |
fc512014 | 57 | pub bound_region: BoundRegionKind, |
e9174d1e SL |
58 | } |
59 | ||
3dfed10e | 60 | #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, TyEncodable, TyDecodable, Copy)] |
ba9703b0 | 61 | #[derive(HashStable)] |
fc512014 | 62 | pub enum BoundRegionKind { |
e9174d1e | 63 | /// An anonymous region parameter for a given fn (&T) |
353b0b11 | 64 | BrAnon(Option<Span>), |
e9174d1e SL |
65 | |
66 | /// Named region parameters for functions (a in &'a T) | |
67 | /// | |
9fa01778 | 68 | /// The `DefId` is needed to distinguish free regions in |
e9174d1e | 69 | /// the event of shadowing. |
e74abb32 | 70 | BrNamed(DefId, Symbol), |
e9174d1e | 71 | |
7cac9316 XL |
72 | /// Anonymous region for the implicit env pointer parameter |
73 | /// to a closure | |
cc61c64b | 74 | BrEnv, |
e9174d1e SL |
75 | } |
76 | ||
fc512014 XL |
77 | #[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Debug, PartialOrd, Ord)] |
78 | #[derive(HashStable)] | |
79 | pub struct BoundRegion { | |
cdc7bbd5 | 80 | pub var: BoundVar, |
fc512014 XL |
81 | pub kind: BoundRegionKind, |
82 | } | |
a1dfa0c6 | 83 | |
fc512014 XL |
84 | impl BoundRegionKind { |
85 | pub fn is_named(&self) -> bool { | |
86 | match *self { | |
487cf647 FG |
87 | BoundRegionKind::BrNamed(_, name) => { |
88 | name != kw::UnderscoreLifetime && name != kw::Empty | |
89 | } | |
fc512014 XL |
90 | _ => false, |
91 | } | |
92 | } | |
2b03887a FG |
93 | |
94 | pub fn get_name(&self) -> Option<Symbol> { | |
95 | if self.is_named() { | |
96 | match *self { | |
97 | BoundRegionKind::BrNamed(_, name) => return Some(name), | |
98 | _ => unreachable!(), | |
99 | } | |
100 | } | |
101 | ||
102 | None | |
103 | } | |
9c376795 FG |
104 | |
105 | pub fn get_id(&self) -> Option<DefId> { | |
106 | match *self { | |
107 | BoundRegionKind::BrNamed(id, _) => return Some(id), | |
108 | _ => None, | |
109 | } | |
110 | } | |
fc512014 XL |
111 | } |
112 | ||
923072b8 FG |
113 | pub trait Article { |
114 | fn article(&self) -> &'static str; | |
e9174d1e SL |
115 | } |
116 | ||
923072b8 | 117 | impl<'tcx> Article for TyKind<'tcx> { |
29967ef6 | 118 | /// Get the article ("a" or "an") to use with this type. |
923072b8 | 119 | fn article(&self) -> &'static str { |
29967ef6 XL |
120 | match self { |
121 | Int(_) | Float(_) | Array(_, _) => "an", | |
122 | Adt(def, _) if def.is_enum() => "an", | |
123 | // This should never happen, but ICEing and causing the user's code | |
124 | // to not compile felt too harsh. | |
125 | Error(_) => "a", | |
126 | _ => "a", | |
127 | } | |
128 | } | |
3dfed10e | 129 | } |
f035d41b | 130 | |
e9174d1e | 131 | /// A closure can be modeled as a struct that looks like: |
04454e1e FG |
132 | /// ```ignore (illustrative) |
133 | /// struct Closure<'l0...'li, T0...Tj, CK, CS, U>(...U); | |
134 | /// ``` | |
ff7c6d11 XL |
135 | /// where: |
136 | /// | |
ba9703b0 | 137 | /// - 'l0...'li and T0...Tj are the generic parameters |
ff7c6d11 XL |
138 | /// in scope on the function that defined the closure, |
139 | /// - CK represents the *closure kind* (Fn vs FnMut vs FnOnce). This | |
140 | /// is rather hackily encoded via a scalar type. See | |
5099ac24 | 141 | /// `Ty::to_opt_closure_kind` for details. |
ff7c6d11 XL |
142 | /// - CS represents the *closure signature*, representing as a `fn()` |
143 | /// type. For example, `fn(u32, u32) -> u32` would mean that the closure | |
144 | /// implements `CK<(u32, u32), Output = u32>`, where `CK` is the trait | |
145 | /// specified above. | |
ba9703b0 | 146 | /// - U is a type parameter representing the types of its upvars, tupled up |
94222f64 | 147 | /// (borrowed, if appropriate; that is, if a U field represents a by-ref upvar, |
ba9703b0 | 148 | /// and the up-var has the type `Foo`, then that field of U will be `&Foo`). |
e9174d1e SL |
149 | /// |
150 | /// So, for example, given this function: | |
04454e1e FG |
151 | /// ```ignore (illustrative) |
152 | /// fn foo<'a, T>(data: &'a mut T) { | |
153 | /// do(|| data.count += 1) | |
154 | /// } | |
155 | /// ``` | |
e9174d1e | 156 | /// the type of the closure would be something like: |
04454e1e FG |
157 | /// ```ignore (illustrative) |
158 | /// struct Closure<'a, T, U>(...U); | |
159 | /// ``` | |
e9174d1e SL |
160 | /// Note that the type of the upvar is not specified in the struct. |
161 | /// You may wonder how the impl would then be able to use the upvar, | |
162 | /// if it doesn't know it's type? The answer is that the impl is | |
163 | /// (conceptually) not fully generic over Closure but rather tied to | |
164 | /// instances with the expected upvar types: | |
04454e1e FG |
165 | /// ```ignore (illustrative) |
166 | /// impl<'b, 'a, T> FnMut() for Closure<'a, T, (&'b mut &'a mut T,)> { | |
167 | /// ... | |
168 | /// } | |
169 | /// ``` | |
e9174d1e SL |
170 | /// You can see that the *impl* fully specified the type of the upvar |
171 | /// and thus knows full well that `data` has type `&'b mut &'a mut T`. | |
172 | /// (Here, I am assuming that `data` is mut-borrowed.) | |
173 | /// | |
174 | /// Now, the last question you may ask is: Why include the upvar types | |
ba9703b0 | 175 | /// in an extra type parameter? The reason for this design is that the |
e9174d1e SL |
176 | /// upvar types can reference lifetimes that are internal to the |
177 | /// creating function. In my example above, for example, the lifetime | |
ea8adc8c XL |
178 | /// `'b` represents the scope of the closure itself; this is some |
179 | /// subset of `foo`, probably just the scope of the call to the to | |
e9174d1e SL |
180 | /// `do()`. If we just had the lifetime/type parameters from the |
181 | /// enclosing function, we couldn't name this lifetime `'b`. Note that | |
182 | /// there can also be lifetimes in the types of the upvars themselves, | |
183 | /// if one of them happens to be a reference to something that the | |
184 | /// creating fn owns. | |
185 | /// | |
186 | /// OK, you say, so why not create a more minimal set of parameters | |
187 | /// that just includes the extra lifetime parameters? The answer is | |
188 | /// primarily that it would be hard --- we don't know at the time when | |
189 | /// we create the closure type what the full types of the upvars are, | |
190 | /// nor do we know which are borrowed and which are not. In this | |
191 | /// design, we can just supply a fresh type parameter and figure that | |
192 | /// out later. | |
193 | /// | |
194 | /// All right, you say, but why include the type parameters from the | |
94b46f34 | 195 | /// original function then? The answer is that codegen may need them |
9fa01778 | 196 | /// when monomorphizing, and they may not appear in the upvars. A |
e9174d1e SL |
197 | /// closure could capture no variables but still make use of some |
198 | /// in-scope type parameter with a bound (e.g., if our example above | |
199 | /// had an extra `U: Default`, and the closure called `U::default()`). | |
200 | /// | |
201 | /// There is another reason. This design (implicitly) prohibits | |
202 | /// closures from capturing themselves (except via a trait | |
203 | /// object). This simplifies closure inference considerably, since it | |
204 | /// means that when we infer the kind of a closure or its upvars, we | |
205 | /// don't have to handle cycles where the decisions we make for | |
206 | /// closure C wind up influencing the decisions we ought to make for | |
207 | /// closure C (which would then require fixed point iteration to | |
208 | /// handle). Plus it fixes an ICE. :P | |
ff7c6d11 XL |
209 | /// |
210 | /// ## Generators | |
211 | /// | |
9c376795 | 212 | /// Generators are handled similarly in `GeneratorSubsts`. The set of |
74b04a01 XL |
213 | /// type parameters is similar, but `CK` and `CS` are replaced by the |
214 | /// following type parameters: | |
215 | /// | |
216 | /// * `GS`: The generator's "resume type", which is the type of the | |
217 | /// argument passed to `resume`, and the type of `yield` expressions | |
218 | /// inside the generator. | |
219 | /// * `GY`: The "yield type", which is the type of values passed to | |
220 | /// `yield` inside the generator. | |
221 | /// * `GR`: The "return type", which is the type of value returned upon | |
222 | /// completion of the generator. | |
223 | /// * `GW`: The "generator witness". | |
9c376795 | 224 | #[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable, Lift)] |
e9174d1e | 225 | pub struct ClosureSubsts<'tcx> { |
476ff2be | 226 | /// Lifetime and type parameters from the enclosing function, |
ba9703b0 | 227 | /// concatenated with a tuple containing the types of the upvars. |
476ff2be | 228 | /// |
94b46f34 | 229 | /// These are separated out because codegen wants to pass them around |
e9174d1e | 230 | /// when monomorphizing. |
532ac7d7 | 231 | pub substs: SubstsRef<'tcx>, |
476ff2be | 232 | } |
e9174d1e | 233 | |
3dfed10e XL |
234 | /// Struct returned by `split()`. |
235 | pub struct ClosureSubstsParts<'tcx, T> { | |
236 | pub parent_substs: &'tcx [GenericArg<'tcx>], | |
237 | pub closure_kind_ty: T, | |
238 | pub closure_sig_as_fn_ptr_ty: T, | |
239 | pub tupled_upvars_ty: T, | |
ff7c6d11 XL |
240 | } |
241 | ||
242 | impl<'tcx> ClosureSubsts<'tcx> { | |
3dfed10e XL |
243 | /// Construct `ClosureSubsts` from `ClosureSubstsParts`, containing `Substs` |
244 | /// for the closure parent, alongside additional closure-specific components. | |
245 | pub fn new( | |
246 | tcx: TyCtxt<'tcx>, | |
247 | parts: ClosureSubstsParts<'tcx, Ty<'tcx>>, | |
248 | ) -> ClosureSubsts<'tcx> { | |
249 | ClosureSubsts { | |
9ffffee4 | 250 | substs: tcx.mk_substs_from_iter( |
3dfed10e XL |
251 | parts.parent_substs.iter().copied().chain( |
252 | [parts.closure_kind_ty, parts.closure_sig_as_fn_ptr_ty, parts.tupled_upvars_ty] | |
253 | .iter() | |
254 | .map(|&ty| ty.into()), | |
255 | ), | |
256 | ), | |
257 | } | |
258 | } | |
259 | ||
260 | /// Divides the closure substs into their respective components. | |
261 | /// The ordering assumed here must match that used by `ClosureSubsts::new` above. | |
262 | fn split(self) -> ClosureSubstsParts<'tcx, GenericArg<'tcx>> { | |
ba9703b0 | 263 | match self.substs[..] { |
a2a8927a XL |
264 | [ |
265 | ref parent_substs @ .., | |
266 | closure_kind_ty, | |
267 | closure_sig_as_fn_ptr_ty, | |
268 | tupled_upvars_ty, | |
269 | ] => ClosureSubstsParts { | |
270 | parent_substs, | |
271 | closure_kind_ty, | |
272 | closure_sig_as_fn_ptr_ty, | |
273 | tupled_upvars_ty, | |
274 | }, | |
ba9703b0 | 275 | _ => bug!("closure substs missing synthetics"), |
ff7c6d11 XL |
276 | } |
277 | } | |
278 | ||
ba9703b0 XL |
279 | /// Returns `true` only if enough of the synthetic types are known to |
280 | /// allow using all of the methods on `ClosureSubsts` without panicking. | |
281 | /// | |
282 | /// Used primarily by `ty::print::pretty` to be able to handle closure | |
283 | /// types that haven't had their synthetic types substituted in. | |
284 | pub fn is_valid(self) -> bool { | |
1b1a35ee XL |
285 | self.substs.len() >= 3 |
286 | && matches!(self.split().tupled_upvars_ty.expect_ty().kind(), Tuple(_)) | |
ba9703b0 XL |
287 | } |
288 | ||
3dfed10e XL |
289 | /// Returns the substitutions of the closure's parent. |
290 | pub fn parent_substs(self) -> &'tcx [GenericArg<'tcx>] { | |
291 | self.split().parent_substs | |
292 | } | |
293 | ||
29967ef6 XL |
294 | /// Returns an iterator over the list of types of captured paths by the closure. |
295 | /// In case there was a type error in figuring out the types of the captured path, an | |
296 | /// empty iterator is returned. | |
476ff2be | 297 | #[inline] |
ba9703b0 | 298 | pub fn upvar_tys(self) -> impl Iterator<Item = Ty<'tcx>> + 'tcx { |
29967ef6 XL |
299 | match self.tupled_upvars_ty().kind() { |
300 | TyKind::Error(_) => None, | |
301 | TyKind::Tuple(..) => Some(self.tupled_upvars_ty().tuple_fields()), | |
302 | TyKind::Infer(_) => bug!("upvar_tys called before capture types are inferred"), | |
303 | ty => bug!("Unexpected representation of upvar types tuple {:?}", ty), | |
304 | } | |
305 | .into_iter() | |
306 | .flatten() | |
3dfed10e XL |
307 | } |
308 | ||
309 | /// Returns the tuple type representing the upvars for this closure. | |
310 | #[inline] | |
311 | pub fn tupled_upvars_ty(self) -> Ty<'tcx> { | |
312 | self.split().tupled_upvars_ty.expect_ty() | |
ff7c6d11 XL |
313 | } |
314 | ||
315 | /// Returns the closure kind for this closure; may return a type | |
316 | /// variable during inference. To get the closure kind during | |
ba9703b0 XL |
317 | /// inference, use `infcx.closure_kind(substs)`. |
318 | pub fn kind_ty(self) -> Ty<'tcx> { | |
319 | self.split().closure_kind_ty.expect_ty() | |
ff7c6d11 XL |
320 | } |
321 | ||
ba9703b0 XL |
322 | /// Returns the `fn` pointer type representing the closure signature for this |
323 | /// closure. | |
324 | // FIXME(eddyb) this should be unnecessary, as the shallowly resolved | |
325 | // type is known at the time of the creation of `ClosureSubsts`, | |
2b03887a | 326 | // see `rustc_hir_analysis::check::closure`. |
ba9703b0 XL |
327 | pub fn sig_as_fn_ptr_ty(self) -> Ty<'tcx> { |
328 | self.split().closure_sig_as_fn_ptr_ty.expect_ty() | |
ff7c6d11 XL |
329 | } |
330 | ||
ff7c6d11 XL |
331 | /// Returns the closure kind for this closure; only usable outside |
332 | /// of an inference context, because in that context we know that | |
333 | /// there are no type variables. | |
334 | /// | |
335 | /// If you have an inference context, use `infcx.closure_kind()`. | |
ba9703b0 XL |
336 | pub fn kind(self) -> ty::ClosureKind { |
337 | self.kind_ty().to_opt_closure_kind().unwrap() | |
ff7c6d11 XL |
338 | } |
339 | ||
ba9703b0 XL |
340 | /// Extracts the signature from the closure. |
341 | pub fn sig(self) -> ty::PolyFnSig<'tcx> { | |
342 | let ty = self.sig_as_fn_ptr_ty(); | |
1b1a35ee XL |
343 | match ty.kind() { |
344 | ty::FnPtr(sig) => *sig, | |
345 | _ => bug!("closure_sig_as_fn_ptr_ty is not a fn-ptr: {:?}", ty.kind()), | |
ff7c6d11 | 346 | } |
476ff2be | 347 | } |
f2b60f7d FG |
348 | |
349 | pub fn print_as_impl_trait(self) -> ty::print::PrintClosureAsImpl<'tcx> { | |
350 | ty::print::PrintClosureAsImpl { closure: self } | |
351 | } | |
a7813a04 | 352 | } |
9cc50fc6 | 353 | |
48663c56 | 354 | /// Similar to `ClosureSubsts`; see the above documentation for more. |
9c376795 | 355 | #[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable, Lift)] |
94b46f34 | 356 | pub struct GeneratorSubsts<'tcx> { |
532ac7d7 | 357 | pub substs: SubstsRef<'tcx>, |
94b46f34 XL |
358 | } |
359 | ||
3dfed10e XL |
360 | pub struct GeneratorSubstsParts<'tcx, T> { |
361 | pub parent_substs: &'tcx [GenericArg<'tcx>], | |
362 | pub resume_ty: T, | |
363 | pub yield_ty: T, | |
364 | pub return_ty: T, | |
365 | pub witness: T, | |
366 | pub tupled_upvars_ty: T, | |
94b46f34 XL |
367 | } |
368 | ||
369 | impl<'tcx> GeneratorSubsts<'tcx> { | |
3dfed10e XL |
370 | /// Construct `GeneratorSubsts` from `GeneratorSubstsParts`, containing `Substs` |
371 | /// for the generator parent, alongside additional generator-specific components. | |
372 | pub fn new( | |
373 | tcx: TyCtxt<'tcx>, | |
374 | parts: GeneratorSubstsParts<'tcx, Ty<'tcx>>, | |
375 | ) -> GeneratorSubsts<'tcx> { | |
376 | GeneratorSubsts { | |
9ffffee4 | 377 | substs: tcx.mk_substs_from_iter( |
3dfed10e XL |
378 | parts.parent_substs.iter().copied().chain( |
379 | [ | |
380 | parts.resume_ty, | |
381 | parts.yield_ty, | |
382 | parts.return_ty, | |
383 | parts.witness, | |
384 | parts.tupled_upvars_ty, | |
385 | ] | |
386 | .iter() | |
387 | .map(|&ty| ty.into()), | |
388 | ), | |
389 | ), | |
390 | } | |
391 | } | |
392 | ||
393 | /// Divides the generator substs into their respective components. | |
394 | /// The ordering assumed here must match that used by `GeneratorSubsts::new` above. | |
395 | fn split(self) -> GeneratorSubstsParts<'tcx, GenericArg<'tcx>> { | |
ba9703b0 | 396 | match self.substs[..] { |
3dfed10e XL |
397 | [ref parent_substs @ .., resume_ty, yield_ty, return_ty, witness, tupled_upvars_ty] => { |
398 | GeneratorSubstsParts { | |
399 | parent_substs, | |
400 | resume_ty, | |
401 | yield_ty, | |
402 | return_ty, | |
403 | witness, | |
404 | tupled_upvars_ty, | |
405 | } | |
ba9703b0 XL |
406 | } |
407 | _ => bug!("generator substs missing synthetics"), | |
94b46f34 XL |
408 | } |
409 | } | |
410 | ||
ba9703b0 XL |
411 | /// Returns `true` only if enough of the synthetic types are known to |
412 | /// allow using all of the methods on `GeneratorSubsts` without panicking. | |
413 | /// | |
414 | /// Used primarily by `ty::print::pretty` to be able to handle generator | |
415 | /// types that haven't had their synthetic types substituted in. | |
416 | pub fn is_valid(self) -> bool { | |
1b1a35ee XL |
417 | self.substs.len() >= 5 |
418 | && matches!(self.split().tupled_upvars_ty.expect_ty().kind(), Tuple(_)) | |
ba9703b0 XL |
419 | } |
420 | ||
3dfed10e XL |
421 | /// Returns the substitutions of the generator's parent. |
422 | pub fn parent_substs(self) -> &'tcx [GenericArg<'tcx>] { | |
423 | self.split().parent_substs | |
424 | } | |
425 | ||
94b46f34 XL |
426 | /// This describes the types that can be contained in a generator. |
427 | /// It will be a type variable initially and unified in the last stages of typeck of a body. | |
428 | /// It contains a tuple of all the types that could end up on a generator frame. | |
429 | /// The state transformation MIR pass may only produce layouts which mention types | |
430 | /// in this tuple. Upvars are not counted here. | |
ba9703b0 XL |
431 | pub fn witness(self) -> Ty<'tcx> { |
432 | self.split().witness.expect_ty() | |
94b46f34 XL |
433 | } |
434 | ||
29967ef6 XL |
435 | /// Returns an iterator over the list of types of captured paths by the generator. |
436 | /// In case there was a type error in figuring out the types of the captured path, an | |
437 | /// empty iterator is returned. | |
94b46f34 | 438 | #[inline] |
ba9703b0 | 439 | pub fn upvar_tys(self) -> impl Iterator<Item = Ty<'tcx>> + 'tcx { |
29967ef6 XL |
440 | match self.tupled_upvars_ty().kind() { |
441 | TyKind::Error(_) => None, | |
442 | TyKind::Tuple(..) => Some(self.tupled_upvars_ty().tuple_fields()), | |
443 | TyKind::Infer(_) => bug!("upvar_tys called before capture types are inferred"), | |
444 | ty => bug!("Unexpected representation of upvar types tuple {:?}", ty), | |
445 | } | |
446 | .into_iter() | |
447 | .flatten() | |
3dfed10e XL |
448 | } |
449 | ||
450 | /// Returns the tuple type representing the upvars for this generator. | |
451 | #[inline] | |
452 | pub fn tupled_upvars_ty(self) -> Ty<'tcx> { | |
453 | self.split().tupled_upvars_ty.expect_ty() | |
94b46f34 XL |
454 | } |
455 | ||
74b04a01 | 456 | /// Returns the type representing the resume type of the generator. |
ba9703b0 XL |
457 | pub fn resume_ty(self) -> Ty<'tcx> { |
458 | self.split().resume_ty.expect_ty() | |
74b04a01 XL |
459 | } |
460 | ||
94b46f34 | 461 | /// Returns the type representing the yield type of the generator. |
ba9703b0 XL |
462 | pub fn yield_ty(self) -> Ty<'tcx> { |
463 | self.split().yield_ty.expect_ty() | |
94b46f34 XL |
464 | } |
465 | ||
466 | /// Returns the type representing the return type of the generator. | |
ba9703b0 XL |
467 | pub fn return_ty(self) -> Ty<'tcx> { |
468 | self.split().return_ty.expect_ty() | |
94b46f34 XL |
469 | } |
470 | ||
9fa01778 | 471 | /// Returns the "generator signature", which consists of its yield |
94b46f34 XL |
472 | /// and return types. |
473 | /// | |
9fa01778 | 474 | /// N.B., some bits of the code prefers to see this wrapped in a |
94b46f34 XL |
475 | /// binder, but it never contains bound regions. Probably this |
476 | /// function should be removed. | |
ba9703b0 XL |
477 | pub fn poly_sig(self) -> PolyGenSig<'tcx> { |
478 | ty::Binder::dummy(self.sig()) | |
94b46f34 XL |
479 | } |
480 | ||
74b04a01 | 481 | /// Returns the "generator signature", which consists of its resume, yield |
94b46f34 | 482 | /// and return types. |
ba9703b0 | 483 | pub fn sig(self) -> GenSig<'tcx> { |
74b04a01 | 484 | ty::GenSig { |
ba9703b0 XL |
485 | resume_ty: self.resume_ty(), |
486 | yield_ty: self.yield_ty(), | |
487 | return_ty: self.return_ty(), | |
74b04a01 | 488 | } |
94b46f34 XL |
489 | } |
490 | } | |
491 | ||
dc9dc135 | 492 | impl<'tcx> GeneratorSubsts<'tcx> { |
60c5eb7d | 493 | /// Generator has not been resumed yet. |
48663c56 | 494 | pub const UNRESUMED: usize = 0; |
60c5eb7d | 495 | /// Generator has returned or is completed. |
48663c56 | 496 | pub const RETURNED: usize = 1; |
60c5eb7d | 497 | /// Generator has been poisoned. |
48663c56 XL |
498 | pub const POISONED: usize = 2; |
499 | ||
500 | const UNRESUMED_NAME: &'static str = "Unresumed"; | |
501 | const RETURNED_NAME: &'static str = "Returned"; | |
502 | const POISONED_NAME: &'static str = "Panicked"; | |
503 | ||
60c5eb7d | 504 | /// The valid variant indices of this generator. |
48663c56 | 505 | #[inline] |
dc9dc135 | 506 | pub fn variant_range(&self, def_id: DefId, tcx: TyCtxt<'tcx>) -> Range<VariantIdx> { |
48663c56 | 507 | // FIXME requires optimized MIR |
353b0b11 | 508 | FIRST_VARIANT..tcx.generator_layout(def_id).unwrap().variant_fields.next_index() |
48663c56 XL |
509 | } |
510 | ||
60c5eb7d | 511 | /// The discriminant for the given variant. Panics if the `variant_index` is |
48663c56 XL |
512 | /// out of range. |
513 | #[inline] | |
514 | pub fn discriminant_for_variant( | |
dc9dc135 XL |
515 | &self, |
516 | def_id: DefId, | |
517 | tcx: TyCtxt<'tcx>, | |
518 | variant_index: VariantIdx, | |
48663c56 XL |
519 | ) -> Discr<'tcx> { |
520 | // Generators don't support explicit discriminant values, so they are | |
521 | // the same as the variant index. | |
522 | assert!(self.variant_range(def_id, tcx).contains(&variant_index)); | |
523 | Discr { val: variant_index.as_usize() as u128, ty: self.discr_ty(tcx) } | |
524 | } | |
525 | ||
60c5eb7d | 526 | /// The set of all discriminants for the generator, enumerated with their |
48663c56 XL |
527 | /// variant indices. |
528 | #[inline] | |
529 | pub fn discriminants( | |
e74abb32 | 530 | self, |
dc9dc135 XL |
531 | def_id: DefId, |
532 | tcx: TyCtxt<'tcx>, | |
533 | ) -> impl Iterator<Item = (VariantIdx, Discr<'tcx>)> + Captures<'tcx> { | |
48663c56 XL |
534 | self.variant_range(def_id, tcx).map(move |index| { |
535 | (index, Discr { val: index.as_usize() as u128, ty: self.discr_ty(tcx) }) | |
536 | }) | |
537 | } | |
538 | ||
539 | /// Calls `f` with a reference to the name of the enumerator for the given | |
540 | /// variant `v`. | |
f035d41b | 541 | pub fn variant_name(v: VariantIdx) -> Cow<'static, str> { |
48663c56 XL |
542 | match v.as_usize() { |
543 | Self::UNRESUMED => Cow::from(Self::UNRESUMED_NAME), | |
544 | Self::RETURNED => Cow::from(Self::RETURNED_NAME), | |
545 | Self::POISONED => Cow::from(Self::POISONED_NAME), | |
dfeec247 | 546 | _ => Cow::from(format!("Suspend{}", v.as_usize() - 3)), |
48663c56 XL |
547 | } |
548 | } | |
549 | ||
550 | /// The type of the state discriminant used in the generator type. | |
551 | #[inline] | |
dc9dc135 | 552 | pub fn discr_ty(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { |
48663c56 XL |
553 | tcx.types.u32 |
554 | } | |
555 | ||
ea8adc8c | 556 | /// This returns the types of the MIR locals which had to be stored across suspension points. |
5e7ed085 | 557 | /// It is calculated in rustc_mir_transform::generator::StateTransform. |
ea8adc8c | 558 | /// All the types here must be in the tuple in GeneratorInterior. |
48663c56 XL |
559 | /// |
560 | /// The locals are grouped by their variant number. Note that some locals may | |
561 | /// be repeated in multiple variants. | |
562 | #[inline] | |
dc9dc135 XL |
563 | pub fn state_tys( |
564 | self, | |
565 | def_id: DefId, | |
566 | tcx: TyCtxt<'tcx>, | |
9ffffee4 | 567 | ) -> impl Iterator<Item: Iterator<Item = Ty<'tcx>> + Captures<'tcx>> { |
5869c6ff | 568 | let layout = tcx.generator_layout(def_id).unwrap(); |
48663c56 | 569 | layout.variant_fields.iter().map(move |variant| { |
9ffffee4 FG |
570 | variant.iter().map(move |field| { |
571 | ty::EarlyBinder(layout.field_tys[*field].ty).subst(tcx, self.substs) | |
572 | }) | |
48663c56 | 573 | }) |
2c00a5a8 XL |
574 | } |
575 | ||
48663c56 XL |
576 | /// This is the types of the fields of a generator which are not stored in a |
577 | /// variant. | |
578 | #[inline] | |
ba9703b0 XL |
579 | pub fn prefix_tys(self) -> impl Iterator<Item = Ty<'tcx>> { |
580 | self.upvar_tys() | |
ea8adc8c XL |
581 | } |
582 | } | |
583 | ||
17df50a5 | 584 | #[derive(Debug, Copy, Clone, HashStable)] |
94b46f34 | 585 | pub enum UpvarSubsts<'tcx> { |
e74abb32 XL |
586 | Closure(SubstsRef<'tcx>), |
587 | Generator(SubstsRef<'tcx>), | |
94b46f34 XL |
588 | } |
589 | ||
590 | impl<'tcx> UpvarSubsts<'tcx> { | |
29967ef6 XL |
591 | /// Returns an iterator over the list of types of captured paths by the closure/generator. |
592 | /// In case there was a type error in figuring out the types of the captured path, an | |
593 | /// empty iterator is returned. | |
94b46f34 | 594 | #[inline] |
ba9703b0 | 595 | pub fn upvar_tys(self) -> impl Iterator<Item = Ty<'tcx>> + 'tcx { |
29967ef6 XL |
596 | let tupled_tys = match self { |
597 | UpvarSubsts::Closure(substs) => substs.as_closure().tupled_upvars_ty(), | |
598 | UpvarSubsts::Generator(substs) => substs.as_generator().tupled_upvars_ty(), | |
94b46f34 | 599 | }; |
29967ef6 XL |
600 | |
601 | match tupled_tys.kind() { | |
602 | TyKind::Error(_) => None, | |
603 | TyKind::Tuple(..) => Some(self.tupled_upvars_ty().tuple_fields()), | |
604 | TyKind::Infer(_) => bug!("upvar_tys called before capture types are inferred"), | |
605 | ty => bug!("Unexpected representation of upvar types tuple {:?}", ty), | |
606 | } | |
607 | .into_iter() | |
608 | .flatten() | |
609 | } | |
610 | ||
611 | #[inline] | |
612 | pub fn tupled_upvars_ty(self) -> Ty<'tcx> { | |
613 | match self { | |
614 | UpvarSubsts::Closure(substs) => substs.as_closure().tupled_upvars_ty(), | |
615 | UpvarSubsts::Generator(substs) => substs.as_generator().tupled_upvars_ty(), | |
616 | } | |
94b46f34 | 617 | } |
ea8adc8c XL |
618 | } |
619 | ||
3c0e092e | 620 | /// An inline const is modeled like |
04454e1e FG |
621 | /// ```ignore (illustrative) |
622 | /// const InlineConst<'l0...'li, T0...Tj, R>: R; | |
623 | /// ``` | |
3c0e092e XL |
624 | /// where: |
625 | /// | |
626 | /// - 'l0...'li and T0...Tj are the generic parameters | |
627 | /// inherited from the item that defined the inline const, | |
628 | /// - R represents the type of the constant. | |
629 | /// | |
630 | /// When the inline const is instantiated, `R` is substituted as the actual inferred | |
631 | /// type of the constant. The reason that `R` is represented as an extra type parameter | |
632 | /// is the same reason that [`ClosureSubsts`] have `CS` and `U` as type parameters: | |
633 | /// inline const can reference lifetimes that are internal to the creating function. | |
064997fb | 634 | #[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable)] |
3c0e092e XL |
635 | pub struct InlineConstSubsts<'tcx> { |
636 | /// Generic parameters from the enclosing item, | |
637 | /// concatenated with the inferred type of the constant. | |
638 | pub substs: SubstsRef<'tcx>, | |
639 | } | |
640 | ||
641 | /// Struct returned by `split()`. | |
642 | pub struct InlineConstSubstsParts<'tcx, T> { | |
643 | pub parent_substs: &'tcx [GenericArg<'tcx>], | |
644 | pub ty: T, | |
645 | } | |
646 | ||
647 | impl<'tcx> InlineConstSubsts<'tcx> { | |
648 | /// Construct `InlineConstSubsts` from `InlineConstSubstsParts`. | |
649 | pub fn new( | |
650 | tcx: TyCtxt<'tcx>, | |
651 | parts: InlineConstSubstsParts<'tcx, Ty<'tcx>>, | |
652 | ) -> InlineConstSubsts<'tcx> { | |
653 | InlineConstSubsts { | |
9ffffee4 | 654 | substs: tcx.mk_substs_from_iter( |
3c0e092e XL |
655 | parts.parent_substs.iter().copied().chain(std::iter::once(parts.ty.into())), |
656 | ), | |
657 | } | |
658 | } | |
659 | ||
660 | /// Divides the inline const substs into their respective components. | |
661 | /// The ordering assumed here must match that used by `InlineConstSubsts::new` above. | |
662 | fn split(self) -> InlineConstSubstsParts<'tcx, GenericArg<'tcx>> { | |
663 | match self.substs[..] { | |
664 | [ref parent_substs @ .., ty] => InlineConstSubstsParts { parent_substs, ty }, | |
665 | _ => bug!("inline const substs missing synthetics"), | |
666 | } | |
667 | } | |
668 | ||
669 | /// Returns the substitutions of the inline const's parent. | |
670 | pub fn parent_substs(self) -> &'tcx [GenericArg<'tcx>] { | |
671 | self.split().parent_substs | |
672 | } | |
673 | ||
674 | /// Returns the type of this inline const. | |
675 | pub fn ty(self) -> Ty<'tcx> { | |
676 | self.split().ty.expect_ty() | |
677 | } | |
678 | } | |
679 | ||
3dfed10e | 680 | #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash, TyEncodable, TyDecodable)] |
f2b60f7d | 681 | #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] |
476ff2be | 682 | pub enum ExistentialPredicate<'tcx> { |
9fa01778 | 683 | /// E.g., `Iterator`. |
476ff2be | 684 | Trait(ExistentialTraitRef<'tcx>), |
9fa01778 | 685 | /// E.g., `Iterator::Item = T`. |
476ff2be | 686 | Projection(ExistentialProjection<'tcx>), |
9fa01778 | 687 | /// E.g., `Send`. |
476ff2be SL |
688 | AutoTrait(DefId), |
689 | } | |
690 | ||
dc9dc135 | 691 | impl<'tcx> ExistentialPredicate<'tcx> { |
94b46f34 XL |
692 | /// Compares via an ordering that will not change if modules are reordered or other changes are |
693 | /// made to the tree. In particular, this ordering is preserved across incremental compilations. | |
dc9dc135 | 694 | pub fn stable_cmp(&self, tcx: TyCtxt<'tcx>, other: &Self) -> Ordering { |
476ff2be SL |
695 | use self::ExistentialPredicate::*; |
696 | match (*self, *other) { | |
697 | (Trait(_), Trait(_)) => Ordering::Equal, | |
dfeec247 | 698 | (Projection(ref a), Projection(ref b)) => { |
9c376795 | 699 | tcx.def_path_hash(a.def_id).cmp(&tcx.def_path_hash(b.def_id)) |
dfeec247 XL |
700 | } |
701 | (AutoTrait(ref a), AutoTrait(ref b)) => { | |
a2a8927a | 702 | tcx.def_path_hash(*a).cmp(&tcx.def_path_hash(*b)) |
dfeec247 | 703 | } |
476ff2be SL |
704 | (Trait(_), _) => Ordering::Less, |
705 | (Projection(_), Trait(_)) => Ordering::Greater, | |
706 | (Projection(_), _) => Ordering::Less, | |
707 | (AutoTrait(_), _) => Ordering::Greater, | |
708 | } | |
709 | } | |
476ff2be SL |
710 | } |
711 | ||
487cf647 FG |
712 | pub type PolyExistentialPredicate<'tcx> = Binder<'tcx, ExistentialPredicate<'tcx>>; |
713 | ||
714 | impl<'tcx> PolyExistentialPredicate<'tcx> { | |
f2b60f7d FG |
715 | /// Given an existential predicate like `?Self: PartialEq<u32>` (e.g., derived from `dyn PartialEq<u32>`), |
716 | /// and a concrete type `self_ty`, returns a full predicate where the existentially quantified variable `?Self` | |
717 | /// has been replaced with `self_ty` (e.g., `self_ty: PartialEq<u32>`, in our example). | |
dc9dc135 | 718 | pub fn with_self_ty(&self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ty::Predicate<'tcx> { |
9fa01778 | 719 | use crate::ty::ToPredicate; |
f035d41b | 720 | match self.skip_binder() { |
dfeec247 | 721 | ExistentialPredicate::Trait(tr) => { |
29967ef6 | 722 | self.rebind(tr).with_self_ty(tcx, self_ty).without_const().to_predicate(tcx) |
dfeec247 XL |
723 | } |
724 | ExistentialPredicate::Projection(p) => { | |
29967ef6 | 725 | self.rebind(p.with_self_ty(tcx, self_ty)).to_predicate(tcx) |
dfeec247 | 726 | } |
476ff2be | 727 | ExistentialPredicate::AutoTrait(did) => { |
487cf647 FG |
728 | let generics = tcx.generics_of(did); |
729 | let trait_ref = if generics.params.len() == 1 { | |
730 | tcx.mk_trait_ref(did, [self_ty]) | |
731 | } else { | |
732 | // If this is an ill-formed auto trait, then synthesize | |
733 | // new error substs for the missing generics. | |
734 | let err_substs = | |
735 | ty::InternalSubsts::extend_with_error(tcx, did, &[self_ty.into()]); | |
736 | tcx.mk_trait_ref(did, err_substs) | |
737 | }; | |
738 | self.rebind(trait_ref).without_const().to_predicate(tcx) | |
476ff2be SL |
739 | } |
740 | } | |
741 | } | |
742 | } | |
743 | ||
487cf647 | 744 | impl<'tcx> List<ty::PolyExistentialPredicate<'tcx>> { |
e1599b0c | 745 | /// Returns the "principal `DefId`" of this set of existential predicates. |
0731742a XL |
746 | /// |
747 | /// A Rust trait object type consists (in addition to a lifetime bound) | |
748 | /// of a set of trait bounds, which are separated into any number | |
416331ca | 749 | /// of auto-trait bounds, and at most one non-auto-trait bound. The |
0731742a XL |
750 | /// non-auto-trait bound is called the "principal" of the trait |
751 | /// object. | |
752 | /// | |
753 | /// Only the principal can have methods or type parameters (because | |
754 | /// auto traits can have neither of them). This is important, because | |
755 | /// it means the auto traits can be treated as an unordered set (methods | |
756 | /// would force an order for the vtable, while relating traits with | |
757 | /// type parameters without knowing the order to relate them in is | |
758 | /// a rather non-trivial task). | |
759 | /// | |
760 | /// For example, in the trait object `dyn fmt::Debug + Sync`, the | |
761 | /// principal bound is `Some(fmt::Debug)`, while the auto-trait bounds | |
762 | /// are the set `{Sync}`. | |
763 | /// | |
764 | /// It is also possible to have a "trivial" trait object that | |
765 | /// consists only of auto traits, with no principal - for example, | |
766 | /// `dyn Send + Sync`. In that case, the set of auto-trait bounds | |
767 | /// is `{Send, Sync}`, while there is no principal. These trait objects | |
768 | /// have a "trivial" vtable consisting of just the size, alignment, | |
769 | /// and destructor. | |
cdc7bbd5 | 770 | pub fn principal(&self) -> Option<ty::Binder<'tcx, ExistentialTraitRef<'tcx>>> { |
fc512014 XL |
771 | self[0] |
772 | .map_bound(|this| match this { | |
773 | ExistentialPredicate::Trait(tr) => Some(tr), | |
774 | _ => None, | |
775 | }) | |
776 | .transpose() | |
476ff2be SL |
777 | } |
778 | ||
0731742a | 779 | pub fn principal_def_id(&self) -> Option<DefId> { |
fc512014 | 780 | self.principal().map(|trait_ref| trait_ref.skip_binder().def_id) |
0731742a XL |
781 | } |
782 | ||
476ff2be | 783 | #[inline] |
dfeec247 XL |
784 | pub fn projection_bounds<'a>( |
785 | &'a self, | |
cdc7bbd5 | 786 | ) -> impl Iterator<Item = ty::Binder<'tcx, ExistentialProjection<'tcx>>> + 'a { |
fc512014 XL |
787 | self.iter().filter_map(|predicate| { |
788 | predicate | |
789 | .map_bound(|pred| match pred { | |
790 | ExistentialPredicate::Projection(projection) => Some(projection), | |
791 | _ => None, | |
792 | }) | |
793 | .transpose() | |
476ff2be SL |
794 | }) |
795 | } | |
796 | ||
797 | #[inline] | |
923072b8 | 798 | pub fn auto_traits<'a>(&'a self) -> impl Iterator<Item = DefId> + Captures<'tcx> + 'a { |
fc512014 | 799 | self.iter().filter_map(|predicate| match predicate.skip_binder() { |
dfeec247 XL |
800 | ExistentialPredicate::AutoTrait(did) => Some(did), |
801 | _ => None, | |
476ff2be SL |
802 | }) |
803 | } | |
804 | } | |
805 | ||
e9174d1e | 806 | /// A complete reference to a trait. These take numerous guises in syntax, |
9fa01778 | 807 | /// but perhaps the most recognizable form is in a where-clause: |
04454e1e FG |
808 | /// ```ignore (illustrative) |
809 | /// T: Foo<U> | |
810 | /// ``` | |
9fa01778 XL |
811 | /// This would be represented by a trait-reference where the `DefId` is the |
812 | /// `DefId` for the trait `Foo` and the substs define `T` as parameter 0, | |
9e0c209e | 813 | /// and `U` as parameter 1. |
e9174d1e SL |
814 | /// |
815 | /// Trait references also appear in object types like `Foo<U>`, but in | |
816 | /// that case the `Self` parameter is absent from the substitutions. | |
3c0e092e | 817 | #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)] |
f2b60f7d | 818 | #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] |
e9174d1e SL |
819 | pub struct TraitRef<'tcx> { |
820 | pub def_id: DefId, | |
532ac7d7 | 821 | pub substs: SubstsRef<'tcx>, |
9c376795 FG |
822 | /// This field exists to prevent the creation of `TraitRef` without |
823 | /// calling [TyCtxt::mk_trait_ref]. | |
824 | pub(super) _use_mk_trait_ref_instead: (), | |
e9174d1e SL |
825 | } |
826 | ||
8bb4bdeb | 827 | impl<'tcx> TraitRef<'tcx> { |
9c376795 | 828 | pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self { |
487cf647 FG |
829 | tcx.mk_trait_ref( |
830 | self.def_id, | |
831 | [self_ty.into()].into_iter().chain(self.substs.iter().skip(1)), | |
832 | ) | |
833 | } | |
834 | ||
a1dfa0c6 | 835 | /// Returns a `TraitRef` of the form `P0: Foo<P1..Pn>` where `Pi` |
8faf50e0 | 836 | /// are the parameters defined on trait. |
c295e0f8 | 837 | pub fn identity(tcx: TyCtxt<'tcx>, def_id: DefId) -> Binder<'tcx, TraitRef<'tcx>> { |
9c376795 | 838 | ty::Binder::dummy(tcx.mk_trait_ref(def_id, InternalSubsts::identity_for_item(tcx, def_id))) |
8faf50e0 XL |
839 | } |
840 | ||
a1dfa0c6 | 841 | #[inline] |
8bb4bdeb XL |
842 | pub fn self_ty(&self) -> Ty<'tcx> { |
843 | self.substs.type_at(0) | |
844 | } | |
845 | ||
dc9dc135 XL |
846 | pub fn from_method( |
847 | tcx: TyCtxt<'tcx>, | |
848 | trait_id: DefId, | |
849 | substs: SubstsRef<'tcx>, | |
850 | ) -> ty::TraitRef<'tcx> { | |
94b46f34 | 851 | let defs = tcx.generics_of(trait_id); |
9ffffee4 | 852 | tcx.mk_trait_ref(trait_id, tcx.mk_substs(&substs[..defs.params.len()])) |
94b46f34 | 853 | } |
8bb4bdeb XL |
854 | } |
855 | ||
cdc7bbd5 | 856 | pub type PolyTraitRef<'tcx> = Binder<'tcx, TraitRef<'tcx>>; |
e9174d1e SL |
857 | |
858 | impl<'tcx> PolyTraitRef<'tcx> { | |
cdc7bbd5 | 859 | pub fn self_ty(&self) -> Binder<'tcx, Ty<'tcx>> { |
f035d41b | 860 | self.map_bound_ref(|tr| tr.self_ty()) |
e9174d1e SL |
861 | } |
862 | ||
863 | pub fn def_id(&self) -> DefId { | |
83c7162d | 864 | self.skip_binder().def_id |
e9174d1e | 865 | } |
e9174d1e SL |
866 | } |
867 | ||
353b0b11 FG |
868 | impl<'tcx> IntoDiagnosticArg for TraitRef<'tcx> { |
869 | fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { | |
f2b60f7d FG |
870 | self.to_string().into_diagnostic_arg() |
871 | } | |
872 | } | |
873 | ||
9e0c209e SL |
874 | /// An existential reference to a trait, where `Self` is erased. |
875 | /// For example, the trait object `Trait<'a, 'b, X, Y>` is: | |
04454e1e FG |
876 | /// ```ignore (illustrative) |
877 | /// exists T. T: Trait<'a, 'b, X, Y> | |
878 | /// ``` | |
9e0c209e SL |
879 | /// The substitutions don't include the erased `Self`, only trait |
880 | /// type and lifetime parameters (`[X, Y]` and `['a, 'b]` above). | |
3dfed10e | 881 | #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)] |
f2b60f7d | 882 | #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] |
9e0c209e SL |
883 | pub struct ExistentialTraitRef<'tcx> { |
884 | pub def_id: DefId, | |
532ac7d7 | 885 | pub substs: SubstsRef<'tcx>, |
9e0c209e SL |
886 | } |
887 | ||
dc9dc135 | 888 | impl<'tcx> ExistentialTraitRef<'tcx> { |
dc9dc135 XL |
889 | pub fn erase_self_ty( |
890 | tcx: TyCtxt<'tcx>, | |
891 | trait_ref: ty::TraitRef<'tcx>, | |
892 | ) -> ty::ExistentialTraitRef<'tcx> { | |
94b46f34 XL |
893 | // Assert there is a Self. |
894 | trait_ref.substs.type_at(0); | |
895 | ||
896 | ty::ExistentialTraitRef { | |
897 | def_id: trait_ref.def_id, | |
9ffffee4 | 898 | substs: tcx.mk_substs(&trait_ref.substs[1..]), |
94b46f34 XL |
899 | } |
900 | } | |
901 | ||
9fa01778 | 902 | /// Object types don't have a self type specified. Therefore, when |
476ff2be | 903 | /// we convert the principal trait-ref into a normal trait-ref, |
9fa01778 | 904 | /// you must give *some* self type. A common choice is `mk_err()` |
0bf4aa26 | 905 | /// or some placeholder type. |
dc9dc135 | 906 | pub fn with_self_ty(&self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ty::TraitRef<'tcx> { |
a1dfa0c6 XL |
907 | // otherwise the escaping vars would be captured by the binder |
908 | // debug_assert!(!self_ty.has_escaping_bound_vars()); | |
476ff2be | 909 | |
487cf647 | 910 | tcx.mk_trait_ref(self.def_id, [self_ty.into()].into_iter().chain(self.substs.iter())) |
476ff2be | 911 | } |
9e0c209e SL |
912 | } |
913 | ||
353b0b11 FG |
914 | impl<'tcx> IntoDiagnosticArg for ExistentialTraitRef<'tcx> { |
915 | fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { | |
916 | self.to_string().into_diagnostic_arg() | |
917 | } | |
918 | } | |
919 | ||
cdc7bbd5 | 920 | pub type PolyExistentialTraitRef<'tcx> = Binder<'tcx, ExistentialTraitRef<'tcx>>; |
9e0c209e SL |
921 | |
922 | impl<'tcx> PolyExistentialTraitRef<'tcx> { | |
923 | pub fn def_id(&self) -> DefId { | |
83c7162d | 924 | self.skip_binder().def_id |
9e0c209e | 925 | } |
94b46f34 | 926 | |
9fa01778 | 927 | /// Object types don't have a self type specified. Therefore, when |
94b46f34 | 928 | /// we convert the principal trait-ref into a normal trait-ref, |
9fa01778 | 929 | /// you must give *some* self type. A common choice is `mk_err()` |
0bf4aa26 | 930 | /// or some placeholder type. |
dc9dc135 | 931 | pub fn with_self_ty(&self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ty::PolyTraitRef<'tcx> { |
94b46f34 XL |
932 | self.map_bound(|trait_ref| trait_ref.with_self_ty(tcx, self_ty)) |
933 | } | |
9e0c209e SL |
934 | } |
935 | ||
cdc7bbd5 XL |
936 | #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)] |
937 | #[derive(HashStable)] | |
938 | pub enum BoundVariableKind { | |
939 | Ty(BoundTyKind), | |
940 | Region(BoundRegionKind), | |
941 | Const, | |
942 | } | |
943 | ||
064997fb FG |
944 | impl BoundVariableKind { |
945 | pub fn expect_region(self) -> BoundRegionKind { | |
946 | match self { | |
947 | BoundVariableKind::Region(lt) => lt, | |
948 | _ => bug!("expected a region, but found another kind"), | |
949 | } | |
950 | } | |
951 | ||
952 | pub fn expect_ty(self) -> BoundTyKind { | |
953 | match self { | |
954 | BoundVariableKind::Ty(ty) => ty, | |
955 | _ => bug!("expected a type, but found another kind"), | |
956 | } | |
957 | } | |
958 | ||
959 | pub fn expect_const(self) { | |
960 | match self { | |
961 | BoundVariableKind::Const => (), | |
962 | _ => bug!("expected a const, but found another kind"), | |
963 | } | |
964 | } | |
965 | } | |
966 | ||
a1dfa0c6 | 967 | /// Binder is a binder for higher-ranked lifetimes or types. It is part of the |
e9174d1e SL |
968 | /// compiler's representation for things like `for<'a> Fn(&'a isize)` |
969 | /// (which would be represented by the type `PolyTraitRef == | |
cdc7bbd5 | 970 | /// Binder<'tcx, TraitRef>`). Note that when we instantiate, |
a1dfa0c6 | 971 | /// erase, or otherwise "discharge" these bound vars, we change the |
cdc7bbd5 | 972 | /// type from `Binder<'tcx, T>` to just `T` (see |
0731742a | 973 | /// e.g., `liberate_late_bound_regions`). |
5869c6ff XL |
974 | /// |
975 | /// `Decodable` and `Encodable` are implemented for `Binder<T>` using the `impl_binder_encode_decode!` macro. | |
976 | #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] | |
f2b60f7d | 977 | #[derive(HashStable, Lift)] |
cdc7bbd5 | 978 | pub struct Binder<'tcx, T>(T, &'tcx List<BoundVariableKind>); |
e9174d1e | 979 | |
cdc7bbd5 XL |
980 | impl<'tcx, T> Binder<'tcx, T> |
981 | where | |
9ffffee4 | 982 | T: TypeVisitable<TyCtxt<'tcx>>, |
cdc7bbd5 | 983 | { |
ff7c6d11 | 984 | /// Wraps `value` in a binder, asserting that `value` does not |
a1dfa0c6 | 985 | /// contain any bound vars that would be bound by the |
ff7c6d11 XL |
986 | /// binder. This is commonly used to 'inject' a value T into a |
987 | /// different binding level. | |
9c376795 | 988 | #[track_caller] |
cdc7bbd5 | 989 | pub fn dummy(value: T) -> Binder<'tcx, T> { |
9c376795 FG |
990 | assert!( |
991 | !value.has_escaping_bound_vars(), | |
992 | "`{value:?}` has escaping bound vars, so it cannot be wrapped in a dummy binder." | |
993 | ); | |
cdc7bbd5 | 994 | Binder(value, ty::List::empty()) |
ff7c6d11 XL |
995 | } |
996 | ||
cdc7bbd5 XL |
997 | pub fn bind_with_vars(value: T, vars: &'tcx List<BoundVariableKind>) -> Binder<'tcx, T> { |
998 | if cfg!(debug_assertions) { | |
999 | let mut validator = ValidateBoundVars::new(vars); | |
1000 | value.visit_with(&mut validator); | |
3dfed10e | 1001 | } |
cdc7bbd5 | 1002 | Binder(value, vars) |
3dfed10e | 1003 | } |
cdc7bbd5 | 1004 | } |
3dfed10e | 1005 | |
cdc7bbd5 | 1006 | impl<'tcx, T> Binder<'tcx, T> { |
e9174d1e SL |
1007 | /// Skips the binder and returns the "bound" value. This is a |
1008 | /// risky thing to do because it's easy to get confused about | |
9fa01778 | 1009 | /// De Bruijn indices and the like. It is usually better to |
a1dfa0c6 | 1010 | /// discharge the binder using `no_bound_vars` or |
e9174d1e SL |
1011 | /// `replace_late_bound_regions` or something like |
1012 | /// that. `skip_binder` is only valid when you are either | |
a1dfa0c6 | 1013 | /// extracting data that has nothing to do with bound vars, you |
e9174d1e SL |
1014 | /// are doing some sort of test that does not involve bound |
1015 | /// regions, or you are being very careful about your depth | |
1016 | /// accounting. | |
1017 | /// | |
1018 | /// Some examples where `skip_binder` is reasonable: | |
ff7c6d11 | 1019 | /// |
9fa01778 | 1020 | /// - extracting the `DefId` from a PolyTraitRef; |
e9174d1e | 1021 | /// - comparing the self type of a PolyTraitRef to see if it is equal to |
a1dfa0c6 | 1022 | /// a type parameter `X`, since the type `X` does not reference any regions |
f035d41b XL |
1023 | pub fn skip_binder(self) -> T { |
1024 | self.0 | |
e9174d1e SL |
1025 | } |
1026 | ||
cdc7bbd5 XL |
1027 | pub fn bound_vars(&self) -> &'tcx List<BoundVariableKind> { |
1028 | self.1 | |
e9174d1e SL |
1029 | } |
1030 | ||
cdc7bbd5 XL |
1031 | pub fn as_ref(&self) -> Binder<'tcx, &T> { |
1032 | Binder(&self.0, self.1) | |
1033 | } | |
1034 | ||
923072b8 FG |
1035 | pub fn as_deref(&self) -> Binder<'tcx, &T::Target> |
1036 | where | |
1037 | T: Deref, | |
1038 | { | |
1039 | Binder(&self.0, self.1) | |
1040 | } | |
1041 | ||
cdc7bbd5 XL |
1042 | pub fn map_bound_ref_unchecked<F, U>(&self, f: F) -> Binder<'tcx, U> |
1043 | where | |
1044 | F: FnOnce(&T) -> U, | |
1045 | { | |
1046 | let value = f(&self.0); | |
1047 | Binder(value, self.1) | |
1048 | } | |
1049 | ||
9ffffee4 | 1050 | pub fn map_bound_ref<F, U: TypeVisitable<TyCtxt<'tcx>>>(&self, f: F) -> Binder<'tcx, U> |
dfeec247 XL |
1051 | where |
1052 | F: FnOnce(&T) -> U, | |
e9174d1e SL |
1053 | { |
1054 | self.as_ref().map_bound(f) | |
1055 | } | |
1056 | ||
9ffffee4 | 1057 | pub fn map_bound<F, U: TypeVisitable<TyCtxt<'tcx>>>(self, f: F) -> Binder<'tcx, U> |
dfeec247 XL |
1058 | where |
1059 | F: FnOnce(T) -> U, | |
e9174d1e | 1060 | { |
cdc7bbd5 XL |
1061 | let value = f(self.0); |
1062 | if cfg!(debug_assertions) { | |
1063 | let mut validator = ValidateBoundVars::new(self.1); | |
1064 | value.visit_with(&mut validator); | |
1065 | } | |
1066 | Binder(value, self.1) | |
e9174d1e | 1067 | } |
ff7c6d11 | 1068 | |
9ffffee4 FG |
1069 | pub fn try_map_bound<F, U: TypeVisitable<TyCtxt<'tcx>>, E>( |
1070 | self, | |
1071 | f: F, | |
1072 | ) -> Result<Binder<'tcx, U>, E> | |
a2a8927a XL |
1073 | where |
1074 | F: FnOnce(T) -> Result<U, E>, | |
1075 | { | |
1076 | let value = f(self.0)?; | |
1077 | if cfg!(debug_assertions) { | |
1078 | let mut validator = ValidateBoundVars::new(self.1); | |
1079 | value.visit_with(&mut validator); | |
1080 | } | |
1081 | Ok(Binder(value, self.1)) | |
1082 | } | |
1083 | ||
29967ef6 XL |
1084 | /// Wraps a `value` in a binder, using the same bound variables as the |
1085 | /// current `Binder`. This should not be used if the new value *changes* | |
1086 | /// the bound variables. Note: the (old or new) value itself does not | |
1087 | /// necessarily need to *name* all the bound variables. | |
1088 | /// | |
1089 | /// This currently doesn't do anything different than `bind`, because we | |
1090 | /// don't actually track bound vars. However, semantically, it is different | |
1091 | /// because bound vars aren't allowed to change here, whereas they are | |
1092 | /// in `bind`. This may be (debug) asserted in the future. | |
cdc7bbd5 XL |
1093 | pub fn rebind<U>(&self, value: U) -> Binder<'tcx, U> |
1094 | where | |
9ffffee4 | 1095 | U: TypeVisitable<TyCtxt<'tcx>>, |
cdc7bbd5 XL |
1096 | { |
1097 | if cfg!(debug_assertions) { | |
1098 | let mut validator = ValidateBoundVars::new(self.bound_vars()); | |
1099 | value.visit_with(&mut validator); | |
1100 | } | |
1101 | Binder(value, self.1) | |
29967ef6 XL |
1102 | } |
1103 | ||
ff7c6d11 | 1104 | /// Unwraps and returns the value within, but only if it contains |
a1dfa0c6 | 1105 | /// no bound vars at all. (In other words, if this binder -- |
ff7c6d11 XL |
1106 | /// and indeed any enclosing binder -- doesn't bind anything at |
1107 | /// all.) Otherwise, returns `None`. | |
1108 | /// | |
1109 | /// (One could imagine having a method that just unwraps a single | |
a1dfa0c6 | 1110 | /// binder, but permits late-bound vars bound by enclosing |
ff7c6d11 XL |
1111 | /// binders, but that would require adjusting the debruijn |
1112 | /// indices, and given the shallow binding structure we often use, | |
1113 | /// would not be that useful.) | |
cdc7bbd5 | 1114 | pub fn no_bound_vars(self) -> Option<T> |
dfeec247 | 1115 | where |
9ffffee4 | 1116 | T: TypeVisitable<TyCtxt<'tcx>>, |
ff7c6d11 | 1117 | { |
f035d41b | 1118 | if self.0.has_escaping_bound_vars() { None } else { Some(self.skip_binder()) } |
ff7c6d11 XL |
1119 | } |
1120 | ||
9fa01778 | 1121 | /// Splits the contents into two things that share the same binder |
ff7c6d11 XL |
1122 | /// level as the original, returning two distinct binders. |
1123 | /// | |
1124 | /// `f` should consider bound regions at depth 1 to be free, and | |
1125 | /// anything it produces with bound regions at depth 1 will be | |
1126 | /// bound in the resulting return values. | |
cdc7bbd5 | 1127 | pub fn split<U, V, F>(self, f: F) -> (Binder<'tcx, U>, Binder<'tcx, V>) |
dfeec247 XL |
1128 | where |
1129 | F: FnOnce(T) -> (U, V), | |
ff7c6d11 XL |
1130 | { |
1131 | let (u, v) = f(self.0); | |
cdc7bbd5 | 1132 | (Binder(u, self.1), Binder(v, self.1)) |
ff7c6d11 | 1133 | } |
e9174d1e SL |
1134 | } |
1135 | ||
cdc7bbd5 XL |
1136 | impl<'tcx, T> Binder<'tcx, Option<T>> { |
1137 | pub fn transpose(self) -> Option<Binder<'tcx, T>> { | |
1138 | let bound_vars = self.1; | |
1139 | self.0.map(|v| Binder(v, bound_vars)) | |
3dfed10e XL |
1140 | } |
1141 | } | |
1142 | ||
9c376795 FG |
1143 | impl<'tcx, T: IntoIterator> Binder<'tcx, T> { |
1144 | pub fn iter(self) -> impl Iterator<Item = ty::Binder<'tcx, T::Item>> { | |
1145 | let bound_vars = self.1; | |
1146 | self.0.into_iter().map(|v| Binder(v, bound_vars)) | |
1147 | } | |
1148 | } | |
1149 | ||
353b0b11 FG |
1150 | impl<'tcx, T> IntoDiagnosticArg for Binder<'tcx, T> |
1151 | where | |
1152 | T: IntoDiagnosticArg, | |
1153 | { | |
1154 | fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { | |
1155 | self.0.into_diagnostic_arg() | |
9c376795 FG |
1156 | } |
1157 | } | |
1158 | ||
1159 | /// Represents the projection of an associated type. | |
1160 | /// | |
1161 | /// For a projection, this would be `<Ty as Trait<...>>::N`. | |
1162 | /// | |
1163 | /// For an opaque type, there is no explicit syntax. | |
1164 | #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)] | |
f2b60f7d | 1165 | #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] |
9c376795 FG |
1166 | pub struct AliasTy<'tcx> { |
1167 | /// The parameters of the associated or opaque item. | |
1168 | /// | |
1169 | /// For a projection, these are the substitutions for the trait and the | |
1170 | /// GAT substitutions, if there are any. | |
1171 | /// | |
1172 | /// For RPIT the substitutions are for the generics of the function, | |
1173 | /// while for TAIT it is used for the generic parameters of the alias. | |
532ac7d7 | 1174 | pub substs: SubstsRef<'tcx>, |
e9174d1e | 1175 | |
9c376795 FG |
1176 | /// The `DefId` of the `TraitItem` for the associated type `N` if this is a projection, |
1177 | /// or the `OpaqueType` item if this is an opaque. | |
7cac9316 | 1178 | /// |
9c376795 FG |
1179 | /// During codegen, `tcx.type_of(def_id)` can be used to get the type of the |
1180 | /// underlying type if the type is an opaque. | |
1181 | /// | |
1182 | /// Note that if this is an associated type, this is not the `DefId` of the | |
1183 | /// `TraitRef` containing this associated type, which is in `tcx.associated_item(def_id).container`, | |
1184 | /// aka. `tcx.parent(def_id)`. | |
1185 | pub def_id: DefId, | |
1186 | ||
1187 | /// This field exists to prevent the creation of `AliasTy` without using | |
1188 | /// [TyCtxt::mk_alias_ty]. | |
1189 | pub(super) _use_mk_alias_ty_instead: (), | |
e9174d1e | 1190 | } |
7cac9316 | 1191 | |
9c376795 FG |
1192 | impl<'tcx> AliasTy<'tcx> { |
1193 | pub fn kind(self, tcx: TyCtxt<'tcx>) -> ty::AliasKind { | |
1194 | match tcx.def_kind(self.def_id) { | |
1195 | DefKind::AssocTy | DefKind::ImplTraitPlaceholder => ty::Projection, | |
1196 | DefKind::OpaqueTy => ty::Opaque, | |
1197 | kind => bug!("unexpected DefKind in AliasTy: {kind:?}"), | |
1198 | } | |
1199 | } | |
1200 | ||
1201 | pub fn to_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { | |
9ffffee4 | 1202 | tcx.mk_alias(self.kind(tcx), self) |
9c376795 FG |
1203 | } |
1204 | } | |
1205 | ||
1206 | /// The following methods work only with associated type projections. | |
1207 | impl<'tcx> AliasTy<'tcx> { | |
1208 | pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId { | |
1209 | match tcx.def_kind(self.def_id) { | |
1210 | DefKind::AssocTy | DefKind::AssocConst => tcx.parent(self.def_id), | |
2b03887a | 1211 | DefKind::ImplTraitPlaceholder => { |
353b0b11 | 1212 | tcx.parent(tcx.impl_trait_in_trait_parent_fn(self.def_id)) |
2b03887a | 1213 | } |
9c376795 | 1214 | kind => bug!("expected a projection AliasTy; found {kind:?}"), |
2b03887a | 1215 | } |
6a06907d | 1216 | } |
7cac9316 | 1217 | |
6a06907d XL |
1218 | /// Extracts the underlying trait reference and own substs from this projection. |
1219 | /// For example, if this is a projection of `<T as StreamingIterator>::Item<'a>`, | |
1220 | /// then this function would return a `T: Iterator` trait reference and `['a]` as the own substs | |
1221 | pub fn trait_ref_and_own_substs( | |
9c376795 | 1222 | self, |
6a06907d XL |
1223 | tcx: TyCtxt<'tcx>, |
1224 | ) -> (ty::TraitRef<'tcx>, &'tcx [ty::GenericArg<'tcx>]) { | |
9c376795 FG |
1225 | debug_assert!(matches!(tcx.def_kind(self.def_id), DefKind::AssocTy | DefKind::AssocConst)); |
1226 | let trait_def_id = self.trait_def_id(tcx); | |
1227 | let trait_generics = tcx.generics_of(trait_def_id); | |
6a06907d | 1228 | ( |
9c376795 | 1229 | tcx.mk_trait_ref(trait_def_id, self.substs.truncate_to(tcx, trait_generics)), |
6a06907d XL |
1230 | &self.substs[trait_generics.count()..], |
1231 | ) | |
7cac9316 XL |
1232 | } |
1233 | ||
041b39d2 XL |
1234 | /// Extracts the underlying trait reference from this projection. |
1235 | /// For example, if this is a projection of `<T as Iterator>::Item`, | |
1236 | /// then this function would return a `T: Iterator` trait reference. | |
6a06907d XL |
1237 | /// |
1238 | /// WARNING: This will drop the substs for generic associated types | |
1239 | /// consider calling [Self::trait_ref_and_own_substs] to get those | |
1240 | /// as well. | |
9c376795 | 1241 | pub fn trait_ref(self, tcx: TyCtxt<'tcx>) -> ty::TraitRef<'tcx> { |
6a06907d | 1242 | let def_id = self.trait_def_id(tcx); |
9c376795 | 1243 | tcx.mk_trait_ref(def_id, self.substs.truncate_to(tcx, tcx.generics_of(def_id))) |
041b39d2 XL |
1244 | } |
1245 | ||
9c376795 | 1246 | pub fn self_ty(self) -> Ty<'tcx> { |
041b39d2 | 1247 | self.substs.type_at(0) |
7cac9316 | 1248 | } |
9c376795 FG |
1249 | |
1250 | pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self { | |
1251 | tcx.mk_alias_ty(self.def_id, [self_ty.into()].into_iter().chain(self.substs.iter().skip(1))) | |
1252 | } | |
7cac9316 XL |
1253 | } |
1254 | ||
f2b60f7d | 1255 | #[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, Lift)] |
ea8adc8c | 1256 | pub struct GenSig<'tcx> { |
74b04a01 | 1257 | pub resume_ty: Ty<'tcx>, |
ea8adc8c XL |
1258 | pub yield_ty: Ty<'tcx>, |
1259 | pub return_ty: Ty<'tcx>, | |
1260 | } | |
1261 | ||
cdc7bbd5 | 1262 | pub type PolyGenSig<'tcx> = Binder<'tcx, GenSig<'tcx>>; |
7cac9316 | 1263 | |
e1599b0c | 1264 | /// Signature of a function type, which we have arbitrarily |
e9174d1e SL |
1265 | /// decided to use to refer to the input/output types. |
1266 | /// | |
532ac7d7 XL |
1267 | /// - `inputs`: is the list of arguments and their modes. |
1268 | /// - `output`: is the return type. | |
1269 | /// - `c_variadic`: indicates whether this is a C-variadic function. | |
3dfed10e | 1270 | #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)] |
f2b60f7d | 1271 | #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] |
e9174d1e | 1272 | pub struct FnSig<'tcx> { |
b7449926 | 1273 | pub inputs_and_output: &'tcx List<Ty<'tcx>>, |
532ac7d7 | 1274 | pub c_variadic: bool, |
8bb4bdeb XL |
1275 | pub unsafety: hir::Unsafety, |
1276 | pub abi: abi::Abi, | |
e9174d1e SL |
1277 | } |
1278 | ||
476ff2be | 1279 | impl<'tcx> FnSig<'tcx> { |
8bb4bdeb | 1280 | pub fn inputs(&self) -> &'tcx [Ty<'tcx>] { |
476ff2be SL |
1281 | &self.inputs_and_output[..self.inputs_and_output.len() - 1] |
1282 | } | |
1283 | ||
1284 | pub fn output(&self) -> Ty<'tcx> { | |
1285 | self.inputs_and_output[self.inputs_and_output.len() - 1] | |
1286 | } | |
48663c56 | 1287 | |
e1599b0c XL |
1288 | // Creates a minimal `FnSig` to be used when encountering a `TyKind::Error` in a fallible |
1289 | // method. | |
48663c56 XL |
1290 | fn fake() -> FnSig<'tcx> { |
1291 | FnSig { | |
1292 | inputs_and_output: List::empty(), | |
1293 | c_variadic: false, | |
1294 | unsafety: hir::Unsafety::Normal, | |
1295 | abi: abi::Abi::Rust, | |
1296 | } | |
1297 | } | |
476ff2be SL |
1298 | } |
1299 | ||
353b0b11 FG |
1300 | impl<'tcx> IntoDiagnosticArg for FnSig<'tcx> { |
1301 | fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { | |
1302 | self.to_string().into_diagnostic_arg() | |
1303 | } | |
1304 | } | |
1305 | ||
cdc7bbd5 | 1306 | pub type PolyFnSig<'tcx> = Binder<'tcx, FnSig<'tcx>>; |
e9174d1e SL |
1307 | |
1308 | impl<'tcx> PolyFnSig<'tcx> { | |
a1dfa0c6 | 1309 | #[inline] |
cdc7bbd5 XL |
1310 | pub fn inputs(&self) -> Binder<'tcx, &'tcx [Ty<'tcx>]> { |
1311 | self.map_bound_ref_unchecked(|fn_sig| fn_sig.inputs()) | |
e9174d1e | 1312 | } |
a1dfa0c6 | 1313 | #[inline] |
cdc7bbd5 | 1314 | pub fn input(&self, index: usize) -> ty::Binder<'tcx, Ty<'tcx>> { |
476ff2be | 1315 | self.map_bound_ref(|fn_sig| fn_sig.inputs()[index]) |
e9174d1e | 1316 | } |
cdc7bbd5 | 1317 | pub fn inputs_and_output(&self) -> ty::Binder<'tcx, &'tcx List<Ty<'tcx>>> { |
ff7c6d11 XL |
1318 | self.map_bound_ref(|fn_sig| fn_sig.inputs_and_output) |
1319 | } | |
a1dfa0c6 | 1320 | #[inline] |
cdc7bbd5 | 1321 | pub fn output(&self) -> ty::Binder<'tcx, Ty<'tcx>> { |
0bf4aa26 | 1322 | self.map_bound_ref(|fn_sig| fn_sig.output()) |
e9174d1e | 1323 | } |
532ac7d7 XL |
1324 | pub fn c_variadic(&self) -> bool { |
1325 | self.skip_binder().c_variadic | |
e9174d1e | 1326 | } |
8bb4bdeb XL |
1327 | pub fn unsafety(&self) -> hir::Unsafety { |
1328 | self.skip_binder().unsafety | |
1329 | } | |
1330 | pub fn abi(&self) -> abi::Abi { | |
1331 | self.skip_binder().abi | |
1332 | } | |
353b0b11 FG |
1333 | |
1334 | pub fn is_fn_trait_compatible(&self) -> bool { | |
1335 | matches!( | |
1336 | self.skip_binder(), | |
1337 | ty::FnSig { | |
1338 | unsafety: rustc_hir::Unsafety::Normal, | |
1339 | abi: Abi::Rust, | |
1340 | c_variadic: false, | |
1341 | .. | |
1342 | } | |
1343 | ) | |
1344 | } | |
e9174d1e SL |
1345 | } |
1346 | ||
cdc7bbd5 | 1347 | pub type CanonicalPolyFnSig<'tcx> = Canonical<'tcx, Binder<'tcx, FnSig<'tcx>>>; |
0bf4aa26 | 1348 | |
3dfed10e | 1349 | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)] |
ba9703b0 | 1350 | #[derive(HashStable)] |
e9174d1e | 1351 | pub struct ParamTy { |
48663c56 | 1352 | pub index: u32, |
e74abb32 | 1353 | pub name: Symbol, |
e9174d1e SL |
1354 | } |
1355 | ||
dc9dc135 | 1356 | impl<'tcx> ParamTy { |
e74abb32 | 1357 | pub fn new(index: u32, name: Symbol) -> ParamTy { |
74b04a01 | 1358 | ParamTy { index, name } |
e9174d1e SL |
1359 | } |
1360 | ||
94b46f34 | 1361 | pub fn for_def(def: &ty::GenericParamDef) -> ParamTy { |
9e0c209e | 1362 | ParamTy::new(def.index, def.name) |
e9174d1e SL |
1363 | } |
1364 | ||
6a06907d | 1365 | #[inline] |
dc9dc135 | 1366 | pub fn to_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { |
48663c56 | 1367 | tcx.mk_ty_param(self.index, self.name) |
e9174d1e | 1368 | } |
487cf647 FG |
1369 | |
1370 | pub fn span_from_generics(&self, tcx: TyCtxt<'tcx>, item_with_generics: DefId) -> Span { | |
1371 | let generics = tcx.generics_of(item_with_generics); | |
1372 | let type_param = generics.type_param(self, tcx); | |
1373 | tcx.def_span(type_param.def_id) | |
1374 | } | |
e9174d1e SL |
1375 | } |
1376 | ||
3dfed10e | 1377 | #[derive(Copy, Clone, Hash, TyEncodable, TyDecodable, Eq, PartialEq, Ord, PartialOrd)] |
ba9703b0 | 1378 | #[derive(HashStable)] |
532ac7d7 XL |
1379 | pub struct ParamConst { |
1380 | pub index: u32, | |
e74abb32 | 1381 | pub name: Symbol, |
532ac7d7 XL |
1382 | } |
1383 | ||
cdc7bbd5 | 1384 | impl ParamConst { |
e74abb32 | 1385 | pub fn new(index: u32, name: Symbol) -> ParamConst { |
532ac7d7 XL |
1386 | ParamConst { index, name } |
1387 | } | |
1388 | ||
1389 | pub fn for_def(def: &ty::GenericParamDef) -> ParamConst { | |
1390 | ParamConst::new(def.index, def.name) | |
1391 | } | |
532ac7d7 XL |
1392 | } |
1393 | ||
923072b8 | 1394 | /// Use this rather than `RegionKind`, whenever possible. |
5099ac24 | 1395 | #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)] |
5e7ed085 | 1396 | #[rustc_pass_by_value] |
923072b8 | 1397 | pub struct Region<'tcx>(pub Interned<'tcx, RegionKind<'tcx>>); |
5099ac24 FG |
1398 | |
1399 | impl<'tcx> Deref for Region<'tcx> { | |
923072b8 | 1400 | type Target = RegionKind<'tcx>; |
5099ac24 | 1401 | |
064997fb | 1402 | #[inline] |
923072b8 | 1403 | fn deref(&self) -> &RegionKind<'tcx> { |
5099ac24 FG |
1404 | &self.0.0 |
1405 | } | |
1406 | } | |
1407 | ||
1408 | impl<'tcx> fmt::Debug for Region<'tcx> { | |
1409 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
1410 | write!(f, "{:?}", self.kind()) | |
1411 | } | |
1412 | } | |
7cac9316 | 1413 | |
923072b8 | 1414 | #[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, PartialOrd, Ord)] |
064997fb | 1415 | #[derive(HashStable)] |
e9174d1e | 1416 | pub struct EarlyBoundRegion { |
7cac9316 | 1417 | pub def_id: DefId, |
e9174d1e | 1418 | pub index: u32, |
e74abb32 | 1419 | pub name: Symbol, |
e9174d1e SL |
1420 | } |
1421 | ||
923072b8 FG |
1422 | impl fmt::Debug for EarlyBoundRegion { |
1423 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
1424 | write!(f, "{}, {}", self.index, self.name) | |
1425 | } | |
1426 | } | |
1427 | ||
5869c6ff | 1428 | /// A **`const`** **v**ariable **ID**. |
064997fb FG |
1429 | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] |
1430 | #[derive(HashStable, TyEncodable, TyDecodable)] | |
532ac7d7 XL |
1431 | pub struct ConstVid<'tcx> { |
1432 | pub index: u32, | |
1433 | pub phantom: PhantomData<&'tcx ()>, | |
1434 | } | |
1435 | ||
e74abb32 | 1436 | rustc_index::newtype_index! { |
5869c6ff | 1437 | /// A **region** (lifetime) **v**ariable **ID**. |
064997fb | 1438 | #[derive(HashStable)] |
9c376795 FG |
1439 | #[debug_format = "'_#{}r"] |
1440 | pub struct RegionVid {} | |
b7449926 | 1441 | } |
abe05a73 | 1442 | |
94b46f34 XL |
1443 | impl Atom for RegionVid { |
1444 | fn index(self) -> usize { | |
1445 | Idx::index(self) | |
1446 | } | |
1447 | } | |
1448 | ||
e74abb32 | 1449 | rustc_index::newtype_index! { |
064997fb | 1450 | #[derive(HashStable)] |
9c376795 | 1451 | pub struct BoundVar {} |
0bf4aa26 XL |
1452 | } |
1453 | ||
3dfed10e | 1454 | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)] |
ba9703b0 | 1455 | #[derive(HashStable)] |
0bf4aa26 | 1456 | pub struct BoundTy { |
a1dfa0c6 XL |
1457 | pub var: BoundVar, |
1458 | pub kind: BoundTyKind, | |
1459 | } | |
1460 | ||
3dfed10e | 1461 | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)] |
ba9703b0 | 1462 | #[derive(HashStable)] |
a1dfa0c6 | 1463 | pub enum BoundTyKind { |
353b0b11 | 1464 | Anon, |
9ffffee4 FG |
1465 | Param(DefId, Symbol), |
1466 | } | |
1467 | ||
a1dfa0c6 XL |
1468 | impl From<BoundVar> for BoundTy { |
1469 | fn from(var: BoundVar) -> Self { | |
353b0b11 | 1470 | BoundTy { var, kind: BoundTyKind::Anon } |
a1dfa0c6 XL |
1471 | } |
1472 | } | |
0bf4aa26 | 1473 | |
9e0c209e | 1474 | /// A `ProjectionPredicate` for an `ExistentialTraitRef`. |
3dfed10e | 1475 | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)] |
f2b60f7d | 1476 | #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] |
9e0c209e | 1477 | pub struct ExistentialProjection<'tcx> { |
9c376795 | 1478 | pub def_id: DefId, |
532ac7d7 | 1479 | pub substs: SubstsRef<'tcx>, |
5099ac24 | 1480 | pub term: Term<'tcx>, |
e9174d1e SL |
1481 | } |
1482 | ||
cdc7bbd5 | 1483 | pub type PolyExistentialProjection<'tcx> = Binder<'tcx, ExistentialProjection<'tcx>>; |
9e0c209e | 1484 | |
dc9dc135 | 1485 | impl<'tcx> ExistentialProjection<'tcx> { |
041b39d2 XL |
1486 | /// Extracts the underlying existential trait reference from this projection. |
1487 | /// For example, if this is a projection of `exists T. <T as Iterator>::Item == X`, | |
94222f64 | 1488 | /// then this function would return an `exists T. T: Iterator` existential trait |
041b39d2 | 1489 | /// reference. |
6a06907d | 1490 | pub fn trait_ref(&self, tcx: TyCtxt<'tcx>) -> ty::ExistentialTraitRef<'tcx> { |
9c376795 | 1491 | let def_id = tcx.parent(self.def_id); |
6a06907d | 1492 | let subst_count = tcx.generics_of(def_id).count() - 1; |
9ffffee4 | 1493 | let substs = tcx.mk_substs(&self.substs[..subst_count]); |
6a06907d | 1494 | ty::ExistentialTraitRef { def_id, substs } |
9e0c209e SL |
1495 | } |
1496 | ||
dc9dc135 XL |
1497 | pub fn with_self_ty( |
1498 | &self, | |
1499 | tcx: TyCtxt<'tcx>, | |
1500 | self_ty: Ty<'tcx>, | |
1501 | ) -> ty::ProjectionPredicate<'tcx> { | |
9e0c209e | 1502 | // otherwise the escaping regions would be captured by the binders |
a1dfa0c6 | 1503 | debug_assert!(!self_ty.has_escaping_bound_vars()); |
9e0c209e | 1504 | |
476ff2be | 1505 | ty::ProjectionPredicate { |
9c376795 FG |
1506 | projection_ty: tcx |
1507 | .mk_alias_ty(self.def_id, [self_ty.into()].into_iter().chain(self.substs)), | |
5099ac24 | 1508 | term: self.term, |
476ff2be | 1509 | } |
e9174d1e | 1510 | } |
6a06907d XL |
1511 | |
1512 | pub fn erase_self_ty( | |
1513 | tcx: TyCtxt<'tcx>, | |
1514 | projection_predicate: ty::ProjectionPredicate<'tcx>, | |
1515 | ) -> Self { | |
1516 | // Assert there is a Self. | |
1517 | projection_predicate.projection_ty.substs.type_at(0); | |
1518 | ||
1519 | Self { | |
9c376795 | 1520 | def_id: projection_predicate.projection_ty.def_id, |
9ffffee4 | 1521 | substs: tcx.mk_substs(&projection_predicate.projection_ty.substs[1..]), |
5099ac24 | 1522 | term: projection_predicate.term, |
6a06907d XL |
1523 | } |
1524 | } | |
e9174d1e SL |
1525 | } |
1526 | ||
dc9dc135 XL |
1527 | impl<'tcx> PolyExistentialProjection<'tcx> { |
1528 | pub fn with_self_ty( | |
1529 | &self, | |
1530 | tcx: TyCtxt<'tcx>, | |
1531 | self_ty: Ty<'tcx>, | |
1532 | ) -> ty::PolyProjectionPredicate<'tcx> { | |
476ff2be | 1533 | self.map_bound(|p| p.with_self_ty(tcx, self_ty)) |
e9174d1e | 1534 | } |
83c7162d XL |
1535 | |
1536 | pub fn item_def_id(&self) -> DefId { | |
9c376795 | 1537 | self.skip_binder().def_id |
83c7162d | 1538 | } |
e9174d1e SL |
1539 | } |
1540 | ||
7cac9316 | 1541 | /// Region utilities |
5099ac24 | 1542 | impl<'tcx> Region<'tcx> { |
923072b8 | 1543 | pub fn kind(self) -> RegionKind<'tcx> { |
5099ac24 FG |
1544 | *self.0.0 |
1545 | } | |
1546 | ||
2b03887a FG |
1547 | pub fn get_name(self) -> Option<Symbol> { |
1548 | if self.has_name() { | |
353b0b11 | 1549 | match *self { |
2b03887a FG |
1550 | ty::ReEarlyBound(ebr) => Some(ebr.name), |
1551 | ty::ReLateBound(_, br) => br.kind.get_name(), | |
1552 | ty::ReFree(fr) => fr.bound_region.get_name(), | |
1553 | ty::ReStatic => Some(kw::StaticLifetime), | |
353b0b11 | 1554 | ty::RePlaceholder(placeholder) => placeholder.bound.kind.get_name(), |
2b03887a | 1555 | _ => None, |
353b0b11 FG |
1556 | } |
1557 | } else { | |
1558 | None | |
2b03887a | 1559 | } |
353b0b11 | 1560 | } |
2b03887a | 1561 | |
353b0b11 FG |
1562 | pub fn get_name_or_anon(self) -> Symbol { |
1563 | match self.get_name() { | |
1564 | Some(name) => name, | |
1565 | None => sym::anon, | |
1566 | } | |
2b03887a FG |
1567 | } |
1568 | ||
0bf4aa26 | 1569 | /// Is this region named by the user? |
5099ac24 | 1570 | pub fn has_name(self) -> bool { |
0bf4aa26 | 1571 | match *self { |
5099ac24 FG |
1572 | ty::ReEarlyBound(ebr) => ebr.has_name(), |
1573 | ty::ReLateBound(_, br) => br.kind.is_named(), | |
1574 | ty::ReFree(fr) => fr.bound_region.is_named(), | |
1575 | ty::ReStatic => true, | |
1576 | ty::ReVar(..) => false, | |
353b0b11 | 1577 | ty::RePlaceholder(placeholder) => placeholder.bound.kind.is_named(), |
5099ac24 | 1578 | ty::ReErased => false, |
9ffffee4 | 1579 | ty::ReError(_) => false, |
0bf4aa26 XL |
1580 | } |
1581 | } | |
1582 | ||
9ffffee4 FG |
1583 | #[inline] |
1584 | pub fn is_error(self) -> bool { | |
1585 | matches!(*self, ty::ReError(_)) | |
1586 | } | |
1587 | ||
6a06907d | 1588 | #[inline] |
5099ac24 FG |
1589 | pub fn is_static(self) -> bool { |
1590 | matches!(*self, ty::ReStatic) | |
1591 | } | |
1592 | ||
1593 | #[inline] | |
1594 | pub fn is_erased(self) -> bool { | |
1595 | matches!(*self, ty::ReErased) | |
1596 | } | |
1597 | ||
1598 | #[inline] | |
1599 | pub fn is_late_bound(self) -> bool { | |
fc512014 | 1600 | matches!(*self, ty::ReLateBound(..)) |
e9174d1e SL |
1601 | } |
1602 | ||
6a06907d | 1603 | #[inline] |
5099ac24 | 1604 | pub fn is_placeholder(self) -> bool { |
fc512014 | 1605 | matches!(*self, ty::RePlaceholder(..)) |
0731742a XL |
1606 | } |
1607 | ||
5099ac24 FG |
1608 | #[inline] |
1609 | pub fn bound_at_or_above_binder(self, index: ty::DebruijnIndex) -> bool { | |
e9174d1e | 1610 | match *self { |
94b46f34 | 1611 | ty::ReLateBound(debruijn, _) => debruijn >= index, |
e9174d1e SL |
1612 | _ => false, |
1613 | } | |
1614 | } | |
1615 | ||
5099ac24 | 1616 | pub fn type_flags(self) -> TypeFlags { |
c30ab7b3 SL |
1617 | let mut flags = TypeFlags::empty(); |
1618 | ||
1619 | match *self { | |
1620 | ty::ReVar(..) => { | |
5099ac24 FG |
1621 | flags = flags | TypeFlags::HAS_FREE_REGIONS; |
1622 | flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS; | |
c30ab7b3 | 1623 | flags = flags | TypeFlags::HAS_RE_INFER; |
c30ab7b3 | 1624 | } |
0bf4aa26 | 1625 | ty::RePlaceholder(..) => { |
5099ac24 FG |
1626 | flags = flags | TypeFlags::HAS_FREE_REGIONS; |
1627 | flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS; | |
a1dfa0c6 | 1628 | flags = flags | TypeFlags::HAS_RE_PLACEHOLDER; |
c30ab7b3 | 1629 | } |
ff7c6d11 | 1630 | ty::ReEarlyBound(..) => { |
5099ac24 FG |
1631 | flags = flags | TypeFlags::HAS_FREE_REGIONS; |
1632 | flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS; | |
1633 | flags = flags | TypeFlags::HAS_RE_PARAM; | |
ff7c6d11 | 1634 | } |
f9f354fc | 1635 | ty::ReFree { .. } => { |
5099ac24 FG |
1636 | flags = flags | TypeFlags::HAS_FREE_REGIONS; |
1637 | flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS; | |
74b04a01 | 1638 | } |
f2b60f7d | 1639 | ty::ReStatic => { |
5099ac24 | 1640 | flags = flags | TypeFlags::HAS_FREE_REGIONS; |
ff7c6d11 | 1641 | } |
74b04a01 XL |
1642 | ty::ReLateBound(..) => { |
1643 | flags = flags | TypeFlags::HAS_RE_LATE_BOUND; | |
1644 | } | |
1645 | ty::ReErased => { | |
1646 | flags = flags | TypeFlags::HAS_RE_ERASED; | |
1647 | } | |
9ffffee4 | 1648 | ty::ReError(_) => {} |
c30ab7b3 SL |
1649 | } |
1650 | ||
1651 | debug!("type_flags({:?}) = {:?}", self, flags); | |
1652 | ||
1653 | flags | |
1654 | } | |
abe05a73 | 1655 | |
9fa01778 | 1656 | /// Given an early-bound or free region, returns the `DefId` where it was bound. |
abe05a73 XL |
1657 | /// For example, consider the regions in this snippet of code: |
1658 | /// | |
04454e1e | 1659 | /// ```ignore (illustrative) |
abe05a73 | 1660 | /// impl<'a> Foo { |
04454e1e | 1661 | /// // ^^ -- early bound, declared on an impl |
abe05a73 XL |
1662 | /// |
1663 | /// fn bar<'b, 'c>(x: &self, y: &'b u32, z: &'c u64) where 'static: 'c | |
04454e1e FG |
1664 | /// // ^^ ^^ ^ anonymous, late-bound |
1665 | /// // | early-bound, appears in where-clauses | |
1666 | /// // late-bound, appears only in fn args | |
abe05a73 XL |
1667 | /// {..} |
1668 | /// } | |
1669 | /// ``` | |
1670 | /// | |
9fa01778 | 1671 | /// Here, `free_region_binding_scope('a)` would return the `DefId` |
abe05a73 | 1672 | /// of the impl, and for all the other highlighted regions, it |
9fa01778 XL |
1673 | /// would return the `DefId` of the function. In other cases (not shown), this |
1674 | /// function might return the `DefId` of a closure. | |
5099ac24 FG |
1675 | pub fn free_region_binding_scope(self, tcx: TyCtxt<'_>) -> DefId { |
1676 | match *self { | |
04454e1e | 1677 | ty::ReEarlyBound(br) => tcx.parent(br.def_id), |
abe05a73 XL |
1678 | ty::ReFree(fr) => fr.scope, |
1679 | _ => bug!("free_region_binding_scope invoked on inappropriate region: {:?}", self), | |
1680 | } | |
1681 | } | |
064997fb FG |
1682 | |
1683 | /// True for free regions other than `'static`. | |
1684 | pub fn is_free(self) -> bool { | |
1685 | matches!(*self, ty::ReEarlyBound(_) | ty::ReFree(_)) | |
1686 | } | |
1687 | ||
1688 | /// True if `self` is a free region or static. | |
1689 | pub fn is_free_or_static(self) -> bool { | |
1690 | match *self { | |
1691 | ty::ReStatic => true, | |
1692 | _ => self.is_free(), | |
1693 | } | |
1694 | } | |
f2b60f7d FG |
1695 | |
1696 | pub fn is_var(self) -> bool { | |
1697 | matches!(self.kind(), ty::ReVar(_)) | |
1698 | } | |
9ffffee4 | 1699 | |
353b0b11 | 1700 | pub fn as_var(self) -> RegionVid { |
9ffffee4 | 1701 | match self.kind() { |
353b0b11 FG |
1702 | ty::ReVar(vid) => vid, |
1703 | _ => bug!("expected region {:?} to be of kind ReVar", self), | |
9ffffee4 FG |
1704 | } |
1705 | } | |
e9174d1e SL |
1706 | } |
1707 | ||
7cac9316 | 1708 | /// Type utilities |
5099ac24 | 1709 | impl<'tcx> Ty<'tcx> { |
1b1a35ee | 1710 | #[inline(always)] |
5099ac24 | 1711 | pub fn kind(self) -> &'tcx TyKind<'tcx> { |
487cf647 | 1712 | &self.0.0 |
1b1a35ee XL |
1713 | } |
1714 | ||
1715 | #[inline(always)] | |
5099ac24 FG |
1716 | pub fn flags(self) -> TypeFlags { |
1717 | self.0.0.flags | |
1b1a35ee XL |
1718 | } |
1719 | ||
dc9dc135 | 1720 | #[inline] |
5099ac24 | 1721 | pub fn is_unit(self) -> bool { |
1b1a35ee | 1722 | match self.kind() { |
b7449926 | 1723 | Tuple(ref tys) => tys.is_empty(), |
cc61c64b | 1724 | _ => false, |
e9174d1e SL |
1725 | } |
1726 | } | |
1727 | ||
dc9dc135 | 1728 | #[inline] |
5099ac24 | 1729 | pub fn is_never(self) -> bool { |
29967ef6 | 1730 | matches!(self.kind(), Never) |
5bcae85e SL |
1731 | } |
1732 | ||
dc9dc135 | 1733 | #[inline] |
5099ac24 | 1734 | pub fn is_primitive(self) -> bool { |
1b1a35ee XL |
1735 | self.kind().is_primitive() |
1736 | } | |
1737 | ||
1738 | #[inline] | |
5099ac24 | 1739 | pub fn is_adt(self) -> bool { |
29967ef6 | 1740 | matches!(self.kind(), Adt(..)) |
1b1a35ee XL |
1741 | } |
1742 | ||
1743 | #[inline] | |
5099ac24 | 1744 | pub fn is_ref(self) -> bool { |
29967ef6 | 1745 | matches!(self.kind(), Ref(..)) |
8bb4bdeb XL |
1746 | } |
1747 | ||
a1dfa0c6 | 1748 | #[inline] |
5099ac24 | 1749 | pub fn is_ty_var(self) -> bool { |
29967ef6 | 1750 | matches!(self.kind(), Infer(TyVar(_))) |
9cc50fc6 SL |
1751 | } |
1752 | ||
c295e0f8 | 1753 | #[inline] |
5099ac24 | 1754 | pub fn ty_vid(self) -> Option<ty::TyVid> { |
c295e0f8 XL |
1755 | match self.kind() { |
1756 | &Infer(TyVar(vid)) => Some(vid), | |
1757 | _ => None, | |
1758 | } | |
1759 | } | |
1760 | ||
dc9dc135 | 1761 | #[inline] |
9c376795 | 1762 | pub fn is_ty_or_numeric_infer(self) -> bool { |
29967ef6 | 1763 | matches!(self.kind(), Infer(_)) |
e9174d1e SL |
1764 | } |
1765 | ||
dc9dc135 | 1766 | #[inline] |
5099ac24 | 1767 | pub fn is_phantom_data(self) -> bool { |
1b1a35ee | 1768 | if let Adt(def, _) = self.kind() { def.is_phantom_data() } else { false } |
b039eaaf SL |
1769 | } |
1770 | ||
dc9dc135 | 1771 | #[inline] |
5099ac24 | 1772 | pub fn is_bool(self) -> bool { |
1b1a35ee | 1773 | *self.kind() == Bool |
dfeec247 | 1774 | } |
e74abb32 XL |
1775 | |
1776 | /// Returns `true` if this type is a `str`. | |
1777 | #[inline] | |
5099ac24 | 1778 | pub fn is_str(self) -> bool { |
1b1a35ee | 1779 | *self.kind() == Str |
dfeec247 | 1780 | } |
e9174d1e | 1781 | |
dc9dc135 | 1782 | #[inline] |
5099ac24 | 1783 | pub fn is_param(self, index: u32) -> bool { |
1b1a35ee | 1784 | match self.kind() { |
48663c56 | 1785 | ty::Param(ref data) => data.index == index, |
e9174d1e SL |
1786 | _ => false, |
1787 | } | |
1788 | } | |
1789 | ||
dc9dc135 | 1790 | #[inline] |
5099ac24 | 1791 | pub fn is_slice(self) -> bool { |
5e7ed085 FG |
1792 | matches!(self.kind(), Slice(_)) |
1793 | } | |
1794 | ||
1795 | #[inline] | |
1796 | pub fn is_array_slice(self) -> bool { | |
1b1a35ee | 1797 | match self.kind() { |
5e7ed085 FG |
1798 | Slice(_) => true, |
1799 | RawPtr(TypeAndMut { ty, .. }) | Ref(_, ty, _) => matches!(ty.kind(), Slice(_)), | |
dfeec247 | 1800 | _ => false, |
e9174d1e SL |
1801 | } |
1802 | } | |
1803 | ||
1b1a35ee | 1804 | #[inline] |
5099ac24 | 1805 | pub fn is_array(self) -> bool { |
29967ef6 | 1806 | matches!(self.kind(), Array(..)) |
1b1a35ee XL |
1807 | } |
1808 | ||
e9174d1e | 1809 | #[inline] |
5099ac24 | 1810 | pub fn is_simd(self) -> bool { |
1b1a35ee | 1811 | match self.kind() { |
5e7ed085 | 1812 | Adt(def, _) => def.repr().simd(), |
cc61c64b | 1813 | _ => false, |
e9174d1e SL |
1814 | } |
1815 | } | |
1816 | ||
5099ac24 | 1817 | pub fn sequence_element_type(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { |
1b1a35ee | 1818 | match self.kind() { |
5099ac24 FG |
1819 | Array(ty, _) | Slice(ty) => *ty, |
1820 | Str => tcx.types.u8, | |
60c5eb7d | 1821 | _ => bug!("`sequence_element_type` called on non-sequence value: {}", self), |
e9174d1e SL |
1822 | } |
1823 | } | |
1824 | ||
5099ac24 | 1825 | pub fn simd_size_and_type(self, tcx: TyCtxt<'tcx>) -> (u64, Ty<'tcx>) { |
1b1a35ee | 1826 | match self.kind() { |
60c5eb7d | 1827 | Adt(def, substs) => { |
5e7ed085 | 1828 | assert!(def.repr().simd(), "`simd_size_and_type` called on non-SIMD type"); |
60c5eb7d | 1829 | let variant = def.non_enum_variant(); |
353b0b11 | 1830 | let f0_ty = variant.fields[FieldIdx::from_u32(0)].ty(tcx, substs); |
fc512014 XL |
1831 | |
1832 | match f0_ty.kind() { | |
3c0e092e XL |
1833 | // If the first field is an array, we assume it is the only field and its |
1834 | // elements are the SIMD components. | |
fc512014 XL |
1835 | Array(f0_elem_ty, f0_len) => { |
1836 | // FIXME(repr_simd): https://github.com/rust-lang/rust/pull/78863#discussion_r522784112 | |
1837 | // The way we evaluate the `N` in `[T; N]` here only works since we use | |
1838 | // `simd_size_and_type` post-monomorphization. It will probably start to ICE | |
1839 | // if we use it in generic code. See the `simd-array-trait` ui test. | |
353b0b11 | 1840 | (f0_len.eval_target_usize(tcx, ParamEnv::empty()), *f0_elem_ty) |
fc512014 | 1841 | } |
3c0e092e XL |
1842 | // Otherwise, the fields of this Adt are the SIMD components (and we assume they |
1843 | // all have the same type). | |
fc512014 XL |
1844 | _ => (variant.fields.len() as u64, f0_ty), |
1845 | } | |
60c5eb7d XL |
1846 | } |
1847 | _ => bug!("`simd_size_and_type` called on invalid type"), | |
e9174d1e SL |
1848 | } |
1849 | } | |
1850 | ||
dc9dc135 | 1851 | #[inline] |
5099ac24 | 1852 | pub fn is_mutable_ptr(self) -> bool { |
29967ef6 XL |
1853 | matches!( |
1854 | self.kind(), | |
dfeec247 | 1855 | RawPtr(TypeAndMut { mutbl: hir::Mutability::Mut, .. }) |
29967ef6 XL |
1856 | | Ref(_, _, hir::Mutability::Mut) |
1857 | ) | |
32a655c1 SL |
1858 | } |
1859 | ||
6a06907d XL |
1860 | /// Get the mutability of the reference or `None` when not a reference |
1861 | #[inline] | |
5099ac24 | 1862 | pub fn ref_mutability(self) -> Option<hir::Mutability> { |
6a06907d XL |
1863 | match self.kind() { |
1864 | Ref(_, _, mutability) => Some(*mutability), | |
1865 | _ => None, | |
1866 | } | |
1867 | } | |
1868 | ||
dc9dc135 | 1869 | #[inline] |
5099ac24 | 1870 | pub fn is_unsafe_ptr(self) -> bool { |
29967ef6 | 1871 | matches!(self.kind(), RawPtr(_)) |
e9174d1e SL |
1872 | } |
1873 | ||
416331ca XL |
1874 | /// Tests if this is any kind of primitive pointer type (reference, raw pointer, fn pointer). |
1875 | #[inline] | |
5099ac24 | 1876 | pub fn is_any_ptr(self) -> bool { |
353b0b11 | 1877 | self.is_ref() || self.is_unsafe_ptr() || self.is_fn_ptr() |
416331ca XL |
1878 | } |
1879 | ||
dc9dc135 | 1880 | #[inline] |
5099ac24 | 1881 | pub fn is_box(self) -> bool { |
1b1a35ee | 1882 | match self.kind() { |
b7449926 | 1883 | Adt(def, _) => def.is_box(), |
32a655c1 SL |
1884 | _ => false, |
1885 | } | |
1886 | } | |
1887 | ||
60c5eb7d | 1888 | /// Panics if called on any type other than `Box<T>`. |
5099ac24 | 1889 | pub fn boxed_ty(self) -> Ty<'tcx> { |
1b1a35ee | 1890 | match self.kind() { |
b7449926 | 1891 | Adt(def, substs) if def.is_box() => substs.type_at(0), |
32a655c1 | 1892 | _ => bug!("`boxed_ty` is called on non-box type {:?}", self), |
e9174d1e SL |
1893 | } |
1894 | } | |
1895 | ||
7cac9316 | 1896 | /// A scalar type is one that denotes an atomic datum, with no sub-components. |
b7449926 | 1897 | /// (A RawPtr is scalar because it represents a non-managed pointer, so its |
7cac9316 | 1898 | /// contents are abstract to rustc.) |
dc9dc135 | 1899 | #[inline] |
5099ac24 | 1900 | pub fn is_scalar(self) -> bool { |
29967ef6 XL |
1901 | matches!( |
1902 | self.kind(), | |
5869c6ff XL |
1903 | Bool | Char |
1904 | | Int(_) | |
1905 | | Float(_) | |
1906 | | Uint(_) | |
1907 | | FnDef(..) | |
1908 | | FnPtr(_) | |
1909 | | RawPtr(_) | |
1910 | | Infer(IntVar(_) | FloatVar(_)) | |
29967ef6 | 1911 | ) |
e9174d1e SL |
1912 | } |
1913 | ||
9fa01778 | 1914 | /// Returns `true` if this type is a floating point type. |
dc9dc135 | 1915 | #[inline] |
5099ac24 | 1916 | pub fn is_floating_point(self) -> bool { |
29967ef6 | 1917 | matches!(self.kind(), Float(_) | Infer(FloatVar(_))) |
e9174d1e SL |
1918 | } |
1919 | ||
dc9dc135 | 1920 | #[inline] |
5099ac24 | 1921 | pub fn is_trait(self) -> bool { |
f2b60f7d FG |
1922 | matches!(self.kind(), Dynamic(_, _, ty::Dyn)) |
1923 | } | |
1924 | ||
1925 | #[inline] | |
1926 | pub fn is_dyn_star(self) -> bool { | |
1927 | matches!(self.kind(), Dynamic(_, _, ty::DynStar)) | |
e9174d1e SL |
1928 | } |
1929 | ||
dc9dc135 | 1930 | #[inline] |
5099ac24 | 1931 | pub fn is_enum(self) -> bool { |
17df50a5 XL |
1932 | matches!(self.kind(), Adt(adt_def, _) if adt_def.is_enum()) |
1933 | } | |
1934 | ||
1935 | #[inline] | |
5099ac24 | 1936 | pub fn is_union(self) -> bool { |
17df50a5 | 1937 | matches!(self.kind(), Adt(adt_def, _) if adt_def.is_union()) |
ff7c6d11 XL |
1938 | } |
1939 | ||
dc9dc135 | 1940 | #[inline] |
5099ac24 | 1941 | pub fn is_closure(self) -> bool { |
29967ef6 | 1942 | matches!(self.kind(), Closure(..)) |
7cac9316 XL |
1943 | } |
1944 | ||
dc9dc135 | 1945 | #[inline] |
5099ac24 | 1946 | pub fn is_generator(self) -> bool { |
29967ef6 | 1947 | matches!(self.kind(), Generator(..)) |
ff7c6d11 XL |
1948 | } |
1949 | ||
a1dfa0c6 | 1950 | #[inline] |
5099ac24 | 1951 | pub fn is_integral(self) -> bool { |
29967ef6 | 1952 | matches!(self.kind(), Infer(IntVar(_)) | Int(_) | Uint(_)) |
e9174d1e SL |
1953 | } |
1954 | ||
dc9dc135 | 1955 | #[inline] |
5099ac24 | 1956 | pub fn is_fresh_ty(self) -> bool { |
29967ef6 | 1957 | matches!(self.kind(), Infer(FreshTy(_))) |
ff7c6d11 XL |
1958 | } |
1959 | ||
dc9dc135 | 1960 | #[inline] |
5099ac24 | 1961 | pub fn is_fresh(self) -> bool { |
29967ef6 | 1962 | matches!(self.kind(), Infer(FreshTy(_) | FreshIntTy(_) | FreshFloatTy(_))) |
e9174d1e SL |
1963 | } |
1964 | ||
dc9dc135 | 1965 | #[inline] |
5099ac24 | 1966 | pub fn is_char(self) -> bool { |
29967ef6 | 1967 | matches!(self.kind(), Char) |
e9174d1e SL |
1968 | } |
1969 | ||
a1dfa0c6 | 1970 | #[inline] |
5099ac24 | 1971 | pub fn is_numeric(self) -> bool { |
dc9dc135 | 1972 | self.is_integral() || self.is_floating_point() |
e9174d1e SL |
1973 | } |
1974 | ||
dc9dc135 | 1975 | #[inline] |
5099ac24 | 1976 | pub fn is_signed(self) -> bool { |
29967ef6 | 1977 | matches!(self.kind(), Int(_)) |
e9174d1e SL |
1978 | } |
1979 | ||
dc9dc135 | 1980 | #[inline] |
5099ac24 | 1981 | pub fn is_ptr_sized_integral(self) -> bool { |
5869c6ff | 1982 | matches!(self.kind(), Int(ty::IntTy::Isize) | Uint(ty::UintTy::Usize)) |
0731742a XL |
1983 | } |
1984 | ||
dc9dc135 | 1985 | #[inline] |
5099ac24 | 1986 | pub fn has_concrete_skeleton(self) -> bool { |
29967ef6 | 1987 | !matches!(self.kind(), Param(_) | Infer(_) | Error(_)) |
54a0048b SL |
1988 | } |
1989 | ||
5099ac24 FG |
1990 | /// Checks whether a type recursively contains another type |
1991 | /// | |
1992 | /// Example: `Option<()>` contains `()` | |
1993 | pub fn contains(self, other: Ty<'tcx>) -> bool { | |
1994 | struct ContainsTyVisitor<'tcx>(Ty<'tcx>); | |
1995 | ||
9ffffee4 | 1996 | impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ContainsTyVisitor<'tcx> { |
5099ac24 FG |
1997 | type BreakTy = (); |
1998 | ||
1999 | fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { | |
9c376795 | 2000 | if self.0 == t { ControlFlow::Break(()) } else { t.super_visit_with(self) } |
5099ac24 FG |
2001 | } |
2002 | } | |
2003 | ||
2004 | let cf = self.visit_with(&mut ContainsTyVisitor(other)); | |
2005 | cf.is_break() | |
2006 | } | |
2007 | ||
9ffffee4 FG |
2008 | /// Checks whether a type recursively contains any closure |
2009 | /// | |
2010 | /// Example: `Option<[closure@file.rs:4:20]>` returns true | |
2011 | pub fn contains_closure(self) -> bool { | |
2012 | struct ContainsClosureVisitor; | |
2013 | ||
2014 | impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ContainsClosureVisitor { | |
2015 | type BreakTy = (); | |
2016 | ||
2017 | fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> { | |
2018 | if let ty::Closure(_, _) = t.kind() { | |
2019 | ControlFlow::Break(()) | |
2020 | } else { | |
2021 | t.super_visit_with(self) | |
2022 | } | |
2023 | } | |
2024 | } | |
2025 | ||
2026 | let cf = self.visit_with(&mut ContainsClosureVisitor); | |
2027 | cf.is_break() | |
2028 | } | |
2029 | ||
0731742a | 2030 | /// Returns the type and mutability of `*ty`. |
7cac9316 XL |
2031 | /// |
2032 | /// The parameter `explicit` indicates if this is an *explicit* dereference. | |
0731742a | 2033 | /// Some types -- notably unsafe ptrs -- can only be dereferenced explicitly. |
5099ac24 | 2034 | pub fn builtin_deref(self, explicit: bool) -> Option<TypeAndMut<'tcx>> { |
1b1a35ee | 2035 | match self.kind() { |
b7449926 | 2036 | Adt(def, _) if def.is_box() => { |
dfeec247 XL |
2037 | Some(TypeAndMut { ty: self.boxed_ty(), mutbl: hir::Mutability::Not }) |
2038 | } | |
5099ac24 | 2039 | Ref(_, ty, mutbl) => Some(TypeAndMut { ty: *ty, mutbl: *mutbl }), |
1b1a35ee | 2040 | RawPtr(mt) if explicit => Some(*mt), |
cc61c64b | 2041 | _ => None, |
e9174d1e SL |
2042 | } |
2043 | } | |
2044 | ||
83c7162d | 2045 | /// Returns the type of `ty[i]`. |
5099ac24 | 2046 | pub fn builtin_index(self) -> Option<Ty<'tcx>> { |
1b1a35ee | 2047 | match self.kind() { |
5099ac24 | 2048 | Array(ty, _) | Slice(ty) => Some(*ty), |
cc61c64b | 2049 | _ => None, |
e9174d1e SL |
2050 | } |
2051 | } | |
2052 | ||
5099ac24 | 2053 | pub fn fn_sig(self, tcx: TyCtxt<'tcx>) -> PolyFnSig<'tcx> { |
1b1a35ee | 2054 | match self.kind() { |
9ffffee4 | 2055 | FnDef(def_id, substs) => tcx.fn_sig(*def_id).subst(tcx, substs), |
1b1a35ee | 2056 | FnPtr(f) => *f, |
f035d41b | 2057 | Error(_) => { |
dfeec247 | 2058 | // ignore errors (#54954) |
48663c56 XL |
2059 | ty::Binder::dummy(FnSig::fake()) |
2060 | } | |
ba9703b0 XL |
2061 | Closure(..) => bug!( |
2062 | "to get the signature of a closure, use `substs.as_closure().sig()` not `fn_sig()`", | |
2063 | ), | |
dfeec247 | 2064 | _ => bug!("Ty::fn_sig() called on non-fn type: {:?}", self), |
e9174d1e SL |
2065 | } |
2066 | } | |
2067 | ||
dc9dc135 | 2068 | #[inline] |
5099ac24 | 2069 | pub fn is_fn(self) -> bool { |
29967ef6 | 2070 | matches!(self.kind(), FnDef(..) | FnPtr(_)) |
e9174d1e SL |
2071 | } |
2072 | ||
dc9dc135 | 2073 | #[inline] |
5099ac24 | 2074 | pub fn is_fn_ptr(self) -> bool { |
29967ef6 | 2075 | matches!(self.kind(), FnPtr(_)) |
dc9dc135 XL |
2076 | } |
2077 | ||
2078 | #[inline] | |
5099ac24 | 2079 | pub fn is_impl_trait(self) -> bool { |
9c376795 | 2080 | matches!(self.kind(), Alias(ty::Opaque, ..)) |
e9174d1e SL |
2081 | } |
2082 | ||
a1dfa0c6 | 2083 | #[inline] |
5e7ed085 | 2084 | pub fn ty_adt_def(self) -> Option<AdtDef<'tcx>> { |
1b1a35ee | 2085 | match self.kind() { |
5e7ed085 | 2086 | Adt(adt, _) => Some(*adt), |
cc61c64b | 2087 | _ => None, |
e9174d1e SL |
2088 | } |
2089 | } | |
2090 | ||
416331ca XL |
2091 | /// Iterates over tuple fields. |
2092 | /// Panics when called on anything but a tuple. | |
5e7ed085 FG |
2093 | #[inline] |
2094 | pub fn tuple_fields(self) -> &'tcx List<Ty<'tcx>> { | |
fc512014 | 2095 | match self.kind() { |
5e7ed085 | 2096 | Tuple(substs) => substs, |
fc512014 XL |
2097 | _ => bug!("tuple_fields called on non-tuple"), |
2098 | } | |
2099 | } | |
2100 | ||
48663c56 | 2101 | /// If the type contains variants, returns the valid range of variant indices. |
60c5eb7d XL |
2102 | // |
2103 | // FIXME: This requires the optimized MIR in the case of generators. | |
48663c56 | 2104 | #[inline] |
5099ac24 | 2105 | pub fn variant_range(self, tcx: TyCtxt<'tcx>) -> Option<Range<VariantIdx>> { |
1b1a35ee | 2106 | match self.kind() { |
48663c56 | 2107 | TyKind::Adt(adt, _) => Some(adt.variant_range()), |
dfeec247 | 2108 | TyKind::Generator(def_id, substs, _) => { |
1b1a35ee | 2109 | Some(substs.as_generator().variant_range(*def_id, tcx)) |
dfeec247 | 2110 | } |
48663c56 XL |
2111 | _ => None, |
2112 | } | |
2113 | } | |
2114 | ||
2115 | /// If the type contains variants, returns the variant for `variant_index`. | |
2116 | /// Panics if `variant_index` is out of range. | |
60c5eb7d XL |
2117 | // |
2118 | // FIXME: This requires the optimized MIR in the case of generators. | |
48663c56 XL |
2119 | #[inline] |
2120 | pub fn discriminant_for_variant( | |
5099ac24 | 2121 | self, |
dc9dc135 XL |
2122 | tcx: TyCtxt<'tcx>, |
2123 | variant_index: VariantIdx, | |
48663c56 | 2124 | ) -> Option<Discr<'tcx>> { |
1b1a35ee | 2125 | match self.kind() { |
5e7ed085 | 2126 | TyKind::Adt(adt, _) if adt.variants().is_empty() => { |
3c0e092e XL |
2127 | // This can actually happen during CTFE, see |
2128 | // https://github.com/rust-lang/rust/issues/89765. | |
2129 | None | |
f035d41b | 2130 | } |
f9f354fc XL |
2131 | TyKind::Adt(adt, _) if adt.is_enum() => { |
2132 | Some(adt.discriminant_for_variant(tcx, variant_index)) | |
2133 | } | |
dfeec247 | 2134 | TyKind::Generator(def_id, substs, _) => { |
1b1a35ee | 2135 | Some(substs.as_generator().discriminant_for_variant(*def_id, tcx, variant_index)) |
dfeec247 | 2136 | } |
48663c56 XL |
2137 | _ => None, |
2138 | } | |
2139 | } | |
2140 | ||
f9f354fc | 2141 | /// Returns the type of the discriminant of this type. |
5099ac24 | 2142 | pub fn discriminant_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { |
1b1a35ee | 2143 | match self.kind() { |
5e7ed085 | 2144 | ty::Adt(adt, _) if adt.is_enum() => adt.repr().discr_type().to_ty(tcx), |
f9f354fc | 2145 | ty::Generator(_, substs, _) => substs.as_generator().discr_ty(tcx), |
fc512014 | 2146 | |
9c376795 | 2147 | ty::Param(_) | ty::Alias(..) | ty::Infer(ty::TyVar(_)) => { |
3c0e092e XL |
2148 | let assoc_items = tcx.associated_item_def_ids( |
2149 | tcx.require_lang_item(hir::LangItem::DiscriminantKind, None), | |
2150 | ); | |
9ffffee4 | 2151 | tcx.mk_projection(assoc_items[0], tcx.mk_substs(&[self.into()])) |
fc512014 XL |
2152 | } |
2153 | ||
2154 | ty::Bool | |
2155 | | ty::Char | |
2156 | | ty::Int(_) | |
2157 | | ty::Uint(_) | |
2158 | | ty::Float(_) | |
2159 | | ty::Adt(..) | |
2160 | | ty::Foreign(_) | |
2161 | | ty::Str | |
2162 | | ty::Array(..) | |
2163 | | ty::Slice(_) | |
2164 | | ty::RawPtr(_) | |
2165 | | ty::Ref(..) | |
2166 | | ty::FnDef(..) | |
2167 | | ty::FnPtr(..) | |
2168 | | ty::Dynamic(..) | |
2169 | | ty::Closure(..) | |
2170 | | ty::GeneratorWitness(..) | |
9ffffee4 | 2171 | | ty::GeneratorWitnessMIR(..) |
fc512014 XL |
2172 | | ty::Never |
2173 | | ty::Tuple(_) | |
2174 | | ty::Error(_) | |
2175 | | ty::Infer(IntVar(_) | FloatVar(_)) => tcx.types.u8, | |
2176 | ||
2177 | ty::Bound(..) | |
2178 | | ty::Placeholder(_) | |
2179 | | ty::Infer(FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => { | |
2180 | bug!("`discriminant_ty` applied to unexpected type: {:?}", self) | |
f9f354fc XL |
2181 | } |
2182 | } | |
2183 | } | |
2184 | ||
5e7ed085 FG |
2185 | /// Returns the type of metadata for (potentially fat) pointers to this type, |
2186 | /// and a boolean signifying if this is conditional on this type being `Sized`. | |
5099ac24 FG |
2187 | pub fn ptr_metadata_ty( |
2188 | self, | |
2189 | tcx: TyCtxt<'tcx>, | |
2190 | normalize: impl FnMut(Ty<'tcx>) -> Ty<'tcx>, | |
5e7ed085 | 2191 | ) -> (Ty<'tcx>, bool) { |
04454e1e | 2192 | let tail = tcx.struct_tail_with_normalize(self, normalize, || {}); |
6a06907d XL |
2193 | match tail.kind() { |
2194 | // Sized types | |
2195 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) | |
2196 | | ty::Uint(_) | |
2197 | | ty::Int(_) | |
2198 | | ty::Bool | |
2199 | | ty::Float(_) | |
2200 | | ty::FnDef(..) | |
2201 | | ty::FnPtr(_) | |
2202 | | ty::RawPtr(..) | |
2203 | | ty::Char | |
2204 | | ty::Ref(..) | |
2205 | | ty::Generator(..) | |
2206 | | ty::GeneratorWitness(..) | |
9ffffee4 | 2207 | | ty::GeneratorWitnessMIR(..) |
6a06907d XL |
2208 | | ty::Array(..) |
2209 | | ty::Closure(..) | |
2210 | | ty::Never | |
2211 | | ty::Error(_) | |
5e7ed085 | 2212 | // Extern types have metadata = (). |
6a06907d XL |
2213 | | ty::Foreign(..) |
2214 | // If returned by `struct_tail_without_normalization` this is a unit struct | |
2215 | // without any fields, or not a struct, and therefore is Sized. | |
2216 | | ty::Adt(..) | |
2217 | // If returned by `struct_tail_without_normalization` this is the empty tuple, | |
2218 | // a.k.a. unit type, which is Sized | |
5e7ed085 | 2219 | | ty::Tuple(..) => (tcx.types.unit, false), |
6a06907d | 2220 | |
5e7ed085 | 2221 | ty::Str | ty::Slice(_) => (tcx.types.usize, false), |
6a06907d | 2222 | ty::Dynamic(..) => { |
487cf647 | 2223 | let dyn_metadata = tcx.require_lang_item(LangItem::DynMetadata, None); |
9ffffee4 | 2224 | (tcx.type_of(dyn_metadata).subst(tcx, &[tail.into()]), false) |
6a06907d XL |
2225 | }, |
2226 | ||
5e7ed085 FG |
2227 | // type parameters only have unit metadata if they're sized, so return true |
2228 | // to make sure we double check this during confirmation | |
9c376795 | 2229 | ty::Param(_) | ty::Alias(..) => (tcx.types.unit, true), |
5e7ed085 FG |
2230 | |
2231 | ty::Infer(ty::TyVar(_)) | |
6a06907d XL |
2232 | | ty::Bound(..) |
2233 | | ty::Placeholder(..) | |
2234 | | ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => { | |
5e7ed085 | 2235 | bug!("`ptr_metadata_ty` applied to unexpected type: {:?} (tail = {:?})", self, tail) |
6a06907d XL |
2236 | } |
2237 | } | |
2238 | } | |
2239 | ||
ff7c6d11 XL |
2240 | /// When we create a closure, we record its kind (i.e., what trait |
2241 | /// it implements) into its `ClosureSubsts` using a type | |
2242 | /// parameter. This is kind of a phantom type, except that the | |
2243 | /// most convenient thing for us to are the integral types. This | |
2244 | /// function converts such a special type into the closure | |
487cf647 | 2245 | /// kind. To go the other way, use `closure_kind.to_ty(tcx)`. |
ff7c6d11 XL |
2246 | /// |
2247 | /// Note that during type checking, we use an inference variable | |
2248 | /// to represent the closure kind, because it has not yet been | |
2b03887a | 2249 | /// inferred. Once upvar inference (in `rustc_hir_analysis/src/check/upvar.rs`) |
ff7c6d11 | 2250 | /// is complete, that type variable will be unified. |
5099ac24 | 2251 | pub fn to_opt_closure_kind(self) -> Option<ty::ClosureKind> { |
1b1a35ee | 2252 | match self.kind() { |
b7449926 | 2253 | Int(int_ty) => match int_ty { |
5869c6ff XL |
2254 | ty::IntTy::I8 => Some(ty::ClosureKind::Fn), |
2255 | ty::IntTy::I16 => Some(ty::ClosureKind::FnMut), | |
2256 | ty::IntTy::I32 => Some(ty::ClosureKind::FnOnce), | |
ff7c6d11 XL |
2257 | _ => bug!("cannot convert type `{:?}` to a closure kind", self), |
2258 | }, | |
2259 | ||
e74abb32 XL |
2260 | // "Bound" types appear in canonical queries when the |
2261 | // closure type is not yet known | |
2262 | Bound(..) | Infer(_) => None, | |
ff7c6d11 | 2263 | |
f035d41b | 2264 | Error(_) => Some(ty::ClosureKind::Fn), |
ff7c6d11 XL |
2265 | |
2266 | _ => bug!("cannot convert type `{:?}` to a closure kind", self), | |
2267 | } | |
2268 | } | |
b7449926 XL |
2269 | |
2270 | /// Fast path helper for testing if a type is `Sized`. | |
2271 | /// | |
2272 | /// Returning true means the type is known to be sized. Returning | |
2273 | /// `false` means nothing -- could be sized, might not be. | |
1b1a35ee XL |
2274 | /// |
2275 | /// Note that we could never rely on the fact that a type such as `[_]` is | |
2276 | /// trivially `!Sized` because we could be in a type environment with a | |
2277 | /// bound such as `[_]: Copy`. A function with such a bound obviously never | |
2278 | /// can be called, but that doesn't mean it shouldn't typecheck. This is why | |
2279 | /// this method doesn't return `Option<bool>`. | |
5099ac24 | 2280 | pub fn is_trivially_sized(self, tcx: TyCtxt<'tcx>) -> bool { |
1b1a35ee | 2281 | match self.kind() { |
ba9703b0 | 2282 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) |
dfeec247 XL |
2283 | | ty::Uint(_) |
2284 | | ty::Int(_) | |
2285 | | ty::Bool | |
2286 | | ty::Float(_) | |
2287 | | ty::FnDef(..) | |
2288 | | ty::FnPtr(_) | |
2289 | | ty::RawPtr(..) | |
2290 | | ty::Char | |
2291 | | ty::Ref(..) | |
2292 | | ty::Generator(..) | |
2293 | | ty::GeneratorWitness(..) | |
9ffffee4 | 2294 | | ty::GeneratorWitnessMIR(..) |
dfeec247 XL |
2295 | | ty::Array(..) |
2296 | | ty::Closure(..) | |
2297 | | ty::Never | |
f035d41b | 2298 | | ty::Error(_) => true, |
dfeec247 XL |
2299 | |
2300 | ty::Str | ty::Slice(_) | ty::Dynamic(..) | ty::Foreign(..) => false, | |
2301 | ||
5e7ed085 | 2302 | ty::Tuple(tys) => tys.iter().all(|ty| ty.is_trivially_sized(tcx)), |
dfeec247 | 2303 | |
064997fb | 2304 | ty::Adt(def, _substs) => def.sized_constraint(tcx).0.is_empty(), |
b7449926 | 2305 | |
9c376795 | 2306 | ty::Alias(..) | ty::Param(_) => false, |
b7449926 XL |
2307 | |
2308 | ty::Infer(ty::TyVar(_)) => false, | |
2309 | ||
dfeec247 XL |
2310 | ty::Bound(..) |
2311 | | ty::Placeholder(..) | |
ba9703b0 | 2312 | | ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => { |
dfeec247 XL |
2313 | bug!("`is_trivially_sized` applied to unexpected type: {:?}", self) |
2314 | } | |
b7449926 XL |
2315 | } |
2316 | } | |
5e7ed085 FG |
2317 | |
2318 | /// Fast path helper for primitives which are always `Copy` and which | |
2319 | /// have a side-effect-free `Clone` impl. | |
2320 | /// | |
2321 | /// Returning true means the type is known to be pure and `Copy+Clone`. | |
2322 | /// Returning `false` means nothing -- could be `Copy`, might not be. | |
2323 | /// | |
2324 | /// This is mostly useful for optimizations, as there are the types | |
2325 | /// on which we can replace cloning with dereferencing. | |
2326 | pub fn is_trivially_pure_clone_copy(self) -> bool { | |
2327 | match self.kind() { | |
2328 | ty::Bool | ty::Char | ty::Never => true, | |
2329 | ||
2330 | // These aren't even `Clone` | |
2331 | ty::Str | ty::Slice(..) | ty::Foreign(..) | ty::Dynamic(..) => false, | |
2332 | ||
2b03887a FG |
2333 | ty::Infer(ty::InferTy::FloatVar(_) | ty::InferTy::IntVar(_)) |
2334 | | ty::Int(..) | |
2335 | | ty::Uint(..) | |
2336 | | ty::Float(..) => true, | |
5e7ed085 FG |
2337 | |
2338 | // The voldemort ZSTs are fine. | |
2339 | ty::FnDef(..) => true, | |
2340 | ||
2341 | ty::Array(element_ty, _len) => element_ty.is_trivially_pure_clone_copy(), | |
2342 | ||
2343 | // A 100-tuple isn't "trivial", so doing this only for reasonable sizes. | |
2344 | ty::Tuple(field_tys) => { | |
2345 | field_tys.len() <= 3 && field_tys.iter().all(Self::is_trivially_pure_clone_copy) | |
2346 | } | |
2347 | ||
2348 | // Sometimes traits aren't implemented for every ABI or arity, | |
2349 | // because we can't be generic over everything yet. | |
2350 | ty::FnPtr(..) => false, | |
2351 | ||
2352 | // Definitely absolutely not copy. | |
2353 | ty::Ref(_, _, hir::Mutability::Mut) => false, | |
2354 | ||
2355 | // Thin pointers & thin shared references are pure-clone-copy, but for | |
2356 | // anything with custom metadata it might be more complicated. | |
2357 | ty::Ref(_, _, hir::Mutability::Not) | ty::RawPtr(..) => false, | |
2358 | ||
9ffffee4 | 2359 | ty::Generator(..) | ty::GeneratorWitness(..) | ty::GeneratorWitnessMIR(..) => false, |
5e7ed085 FG |
2360 | |
2361 | // Might be, but not "trivial" so just giving the safe answer. | |
9c376795 FG |
2362 | ty::Adt(..) | ty::Closure(..) => false, |
2363 | ||
2364 | // Needs normalization or revealing to determine, so no is the safe answer. | |
2365 | ty::Alias(..) => false, | |
5e7ed085 | 2366 | |
9c376795 | 2367 | ty::Param(..) | ty::Infer(..) | ty::Error(..) => false, |
5e7ed085 FG |
2368 | |
2369 | ty::Bound(..) | ty::Placeholder(..) => { | |
2370 | bug!("`is_trivially_pure_clone_copy` applied to unexpected type: {:?}", self); | |
2371 | } | |
2372 | } | |
2373 | } | |
2b03887a | 2374 | |
487cf647 | 2375 | /// If `self` is a primitive, return its [`Symbol`]. |
2b03887a FG |
2376 | pub fn primitive_symbol(self) -> Option<Symbol> { |
2377 | match self.kind() { | |
2378 | ty::Bool => Some(sym::bool), | |
2379 | ty::Char => Some(sym::char), | |
2380 | ty::Float(f) => match f { | |
2381 | ty::FloatTy::F32 => Some(sym::f32), | |
2382 | ty::FloatTy::F64 => Some(sym::f64), | |
2383 | }, | |
2384 | ty::Int(f) => match f { | |
2385 | ty::IntTy::Isize => Some(sym::isize), | |
2386 | ty::IntTy::I8 => Some(sym::i8), | |
2387 | ty::IntTy::I16 => Some(sym::i16), | |
2388 | ty::IntTy::I32 => Some(sym::i32), | |
2389 | ty::IntTy::I64 => Some(sym::i64), | |
2390 | ty::IntTy::I128 => Some(sym::i128), | |
2391 | }, | |
2392 | ty::Uint(f) => match f { | |
2393 | ty::UintTy::Usize => Some(sym::usize), | |
2394 | ty::UintTy::U8 => Some(sym::u8), | |
2395 | ty::UintTy::U16 => Some(sym::u16), | |
2396 | ty::UintTy::U32 => Some(sym::u32), | |
2397 | ty::UintTy::U64 => Some(sym::u64), | |
2398 | ty::UintTy::U128 => Some(sym::u128), | |
2399 | }, | |
2400 | _ => None, | |
2401 | } | |
2402 | } | |
e9174d1e | 2403 | } |
17df50a5 XL |
2404 | |
2405 | /// Extra information about why we ended up with a particular variance. | |
2406 | /// This is only used to add more information to error messages, and | |
2407 | /// has no effect on soundness. While choosing the 'wrong' `VarianceDiagInfo` | |
2408 | /// may lead to confusing notes in error messages, it will never cause | |
2409 | /// a miscompilation or unsoundness. | |
2410 | /// | |
2411 | /// When in doubt, use `VarianceDiagInfo::default()` | |
3c0e092e | 2412 | #[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord)] |
17df50a5 XL |
2413 | pub enum VarianceDiagInfo<'tcx> { |
2414 | /// No additional information - this is the default. | |
2415 | /// We will not add any additional information to error messages. | |
3c0e092e | 2416 | #[default] |
17df50a5 | 2417 | None, |
a2a8927a XL |
2418 | /// We switched our variance because a generic argument occurs inside |
2419 | /// the invariant generic argument of another type. | |
2420 | Invariant { | |
2421 | /// The generic type containing the generic parameter | |
2422 | /// that changes the variance (e.g. `*mut T`, `MyStruct<T>`) | |
17df50a5 | 2423 | ty: Ty<'tcx>, |
a2a8927a XL |
2424 | /// The index of the generic parameter being used |
2425 | /// (e.g. `0` for `*mut T`, `1` for `MyStruct<'CovariantParam, 'InvariantParam>`) | |
2426 | param_index: u32, | |
17df50a5 XL |
2427 | }, |
2428 | } | |
2429 | ||
17df50a5 XL |
2430 | impl<'tcx> VarianceDiagInfo<'tcx> { |
2431 | /// Mirrors `Variance::xform` - used to 'combine' the existing | |
2432 | /// and new `VarianceDiagInfo`s when our variance changes. | |
2433 | pub fn xform(self, other: VarianceDiagInfo<'tcx>) -> VarianceDiagInfo<'tcx> { | |
a2a8927a | 2434 | // For now, just use the first `VarianceDiagInfo::Invariant` that we see |
17df50a5 XL |
2435 | match self { |
2436 | VarianceDiagInfo::None => other, | |
a2a8927a | 2437 | VarianceDiagInfo::Invariant { .. } => self, |
17df50a5 XL |
2438 | } |
2439 | } | |
2440 | } | |
353b0b11 FG |
2441 | |
2442 | // Some types are used a lot. Make sure they don't unintentionally get bigger. | |
2443 | #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] | |
2444 | mod size_asserts { | |
2445 | use super::*; | |
2446 | use rustc_data_structures::static_assert_size; | |
2447 | // tidy-alphabetical-start | |
2448 | static_assert_size!(RegionKind<'_>, 28); | |
2449 | static_assert_size!(TyKind<'_>, 32); | |
2450 | // tidy-alphabetical-end | |
2451 | } |