1#![allow(rustc::usage_of_ty_tykind)]
4
5use std::assert_matches::debug_assert_matches;
6use std::borrow::Cow;
7use std::iter;
8use std::ops::{ControlFlow, Range};
9
10use hir::def::{CtorKind, DefKind};
11use rustc_abi::{ExternAbi, FIRST_VARIANT, FieldIdx, VariantIdx};
12use rustc_data_structures::captures::Captures;
13use rustc_errors::{ErrorGuaranteed, MultiSpan};
14use rustc_hir as hir;
15use rustc_hir::LangItem;
16use rustc_hir::def_id::DefId;
17use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, extension};
18use rustc_span::{DUMMY_SP, Span, Symbol, sym};
19use rustc_type_ir::TyKind::*;
20use rustc_type_ir::visit::TypeVisitableExt;
21use rustc_type_ir::{self as ir, BoundVar, CollectAndApply, DynKind};
22use tracing::instrument;
23use ty::util::{AsyncDropGlueMorphology, IntTypeExt};
24
25use super::GenericParamDefKind;
26use crate::infer::canonical::Canonical;
27use crate::ty::InferTy::*;
28use crate::ty::{
29 self, AdtDef, BoundRegionKind, Discr, GenericArg, GenericArgs, GenericArgsRef, List, ParamEnv,
30 Region, Ty, TyCtxt, TypeFlags, TypeSuperVisitable, TypeVisitable, TypeVisitor, UintTy,
31};
32
33#[rustc_diagnostic_item = "TyKind"]
35pub type TyKind<'tcx> = ir::TyKind<TyCtxt<'tcx>>;
36pub type TypeAndMut<'tcx> = ir::TypeAndMut<TyCtxt<'tcx>>;
37pub type AliasTy<'tcx> = ir::AliasTy<TyCtxt<'tcx>>;
38pub type FnSig<'tcx> = ir::FnSig<TyCtxt<'tcx>>;
39pub type Binder<'tcx, T> = ir::Binder<TyCtxt<'tcx>, T>;
40pub type EarlyBinder<'tcx, T> = ir::EarlyBinder<TyCtxt<'tcx>, T>;
41pub type TypingMode<'tcx> = ir::TypingMode<TyCtxt<'tcx>>;
42
43pub trait Article {
44 fn article(&self) -> &'static str;
45}
46
47impl<'tcx> Article for TyKind<'tcx> {
48 fn article(&self) -> &'static str {
50 match self {
51 Int(_) | Float(_) | Array(_, _) => "an",
52 Adt(def, _) if def.is_enum() => "an",
53 Error(_) => "a",
56 _ => "a",
57 }
58 }
59}
60
61#[extension(pub trait CoroutineArgsExt<'tcx>)]
62impl<'tcx> ty::CoroutineArgs<TyCtxt<'tcx>> {
63 const UNRESUMED: usize = 0;
65 const RETURNED: usize = 1;
67 const POISONED: usize = 2;
69 const RESERVED_VARIANTS: usize = 3;
73
74 const UNRESUMED_NAME: &'static str = "Unresumed";
75 const RETURNED_NAME: &'static str = "Returned";
76 const POISONED_NAME: &'static str = "Panicked";
77
78 #[inline]
80 fn variant_range(&self, def_id: DefId, tcx: TyCtxt<'tcx>) -> Range<VariantIdx> {
81 FIRST_VARIANT
83 ..tcx.coroutine_layout(def_id, tcx.types.unit).unwrap().variant_fields.next_index()
84 }
85
86 #[inline]
89 fn discriminant_for_variant(
90 &self,
91 def_id: DefId,
92 tcx: TyCtxt<'tcx>,
93 variant_index: VariantIdx,
94 ) -> Discr<'tcx> {
95 assert!(self.variant_range(def_id, tcx).contains(&variant_index));
98 Discr { val: variant_index.as_usize() as u128, ty: self.discr_ty(tcx) }
99 }
100
101 #[inline]
104 fn discriminants(
105 self,
106 def_id: DefId,
107 tcx: TyCtxt<'tcx>,
108 ) -> impl Iterator<Item = (VariantIdx, Discr<'tcx>)> + Captures<'tcx> {
109 self.variant_range(def_id, tcx).map(move |index| {
110 (index, Discr { val: index.as_usize() as u128, ty: self.discr_ty(tcx) })
111 })
112 }
113
114 fn variant_name(v: VariantIdx) -> Cow<'static, str> {
117 match v.as_usize() {
118 Self::UNRESUMED => Cow::from(Self::UNRESUMED_NAME),
119 Self::RETURNED => Cow::from(Self::RETURNED_NAME),
120 Self::POISONED => Cow::from(Self::POISONED_NAME),
121 _ => Cow::from(format!("Suspend{}", v.as_usize() - Self::RESERVED_VARIANTS)),
122 }
123 }
124
125 #[inline]
127 fn discr_ty(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
128 tcx.types.u32
129 }
130
131 #[inline]
138 fn state_tys(
139 self,
140 def_id: DefId,
141 tcx: TyCtxt<'tcx>,
142 ) -> impl Iterator<Item: Iterator<Item = Ty<'tcx>> + Captures<'tcx>> {
143 let layout = tcx.coroutine_layout(def_id, self.kind_ty()).unwrap();
144 layout.variant_fields.iter().map(move |variant| {
145 variant.iter().map(move |field| {
146 ty::EarlyBinder::bind(layout.field_tys[*field].ty).instantiate(tcx, self.args)
147 })
148 })
149 }
150
151 #[inline]
154 fn prefix_tys(self) -> &'tcx List<Ty<'tcx>> {
155 self.upvar_tys()
156 }
157}
158
159#[derive(Debug, Copy, Clone, HashStable, TypeFoldable, TypeVisitable)]
160pub enum UpvarArgs<'tcx> {
161 Closure(GenericArgsRef<'tcx>),
162 Coroutine(GenericArgsRef<'tcx>),
163 CoroutineClosure(GenericArgsRef<'tcx>),
164}
165
166impl<'tcx> UpvarArgs<'tcx> {
167 #[inline]
171 pub fn upvar_tys(self) -> &'tcx List<Ty<'tcx>> {
172 let tupled_tys = match self {
173 UpvarArgs::Closure(args) => args.as_closure().tupled_upvars_ty(),
174 UpvarArgs::Coroutine(args) => args.as_coroutine().tupled_upvars_ty(),
175 UpvarArgs::CoroutineClosure(args) => args.as_coroutine_closure().tupled_upvars_ty(),
176 };
177
178 match tupled_tys.kind() {
179 TyKind::Error(_) => ty::List::empty(),
180 TyKind::Tuple(..) => self.tupled_upvars_ty().tuple_fields(),
181 TyKind::Infer(_) => bug!("upvar_tys called before capture types are inferred"),
182 ty => bug!("Unexpected representation of upvar types tuple {:?}", ty),
183 }
184 }
185
186 #[inline]
187 pub fn tupled_upvars_ty(self) -> Ty<'tcx> {
188 match self {
189 UpvarArgs::Closure(args) => args.as_closure().tupled_upvars_ty(),
190 UpvarArgs::Coroutine(args) => args.as_coroutine().tupled_upvars_ty(),
191 UpvarArgs::CoroutineClosure(args) => args.as_coroutine_closure().tupled_upvars_ty(),
192 }
193 }
194}
195
196#[derive(Copy, Clone, Debug)]
211pub struct InlineConstArgs<'tcx> {
212 pub args: GenericArgsRef<'tcx>,
215}
216
217pub struct InlineConstArgsParts<'tcx, T> {
219 pub parent_args: &'tcx [GenericArg<'tcx>],
220 pub ty: T,
221}
222
223impl<'tcx> InlineConstArgs<'tcx> {
224 pub fn new(
226 tcx: TyCtxt<'tcx>,
227 parts: InlineConstArgsParts<'tcx, Ty<'tcx>>,
228 ) -> InlineConstArgs<'tcx> {
229 InlineConstArgs {
230 args: tcx.mk_args_from_iter(
231 parts.parent_args.iter().copied().chain(std::iter::once(parts.ty.into())),
232 ),
233 }
234 }
235
236 fn split(self) -> InlineConstArgsParts<'tcx, GenericArg<'tcx>> {
239 match self.args[..] {
240 [ref parent_args @ .., ty] => InlineConstArgsParts { parent_args, ty },
241 _ => bug!("inline const args missing synthetics"),
242 }
243 }
244
245 pub fn parent_args(self) -> &'tcx [GenericArg<'tcx>] {
247 self.split().parent_args
248 }
249
250 pub fn ty(self) -> Ty<'tcx> {
252 self.split().ty.expect_ty()
253 }
254}
255
256#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
257#[derive(HashStable)]
258pub enum BoundVariableKind {
259 Ty(BoundTyKind),
260 Region(BoundRegionKind),
261 Const,
262}
263
264impl BoundVariableKind {
265 pub fn expect_region(self) -> BoundRegionKind {
266 match self {
267 BoundVariableKind::Region(lt) => lt,
268 _ => bug!("expected a region, but found another kind"),
269 }
270 }
271
272 pub fn expect_ty(self) -> BoundTyKind {
273 match self {
274 BoundVariableKind::Ty(ty) => ty,
275 _ => bug!("expected a type, but found another kind"),
276 }
277 }
278
279 pub fn expect_const(self) {
280 match self {
281 BoundVariableKind::Const => (),
282 _ => bug!("expected a const, but found another kind"),
283 }
284 }
285}
286
287pub type PolyFnSig<'tcx> = Binder<'tcx, FnSig<'tcx>>;
288pub type CanonicalPolyFnSig<'tcx> = Canonical<'tcx, Binder<'tcx, FnSig<'tcx>>>;
289
290#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)]
291#[derive(HashStable)]
292pub struct ParamTy {
293 pub index: u32,
294 pub name: Symbol,
295}
296
297impl rustc_type_ir::inherent::ParamLike for ParamTy {
298 fn index(self) -> u32 {
299 self.index
300 }
301}
302
303impl<'tcx> ParamTy {
304 pub fn new(index: u32, name: Symbol) -> ParamTy {
305 ParamTy { index, name }
306 }
307
308 pub fn for_def(def: &ty::GenericParamDef) -> ParamTy {
309 ParamTy::new(def.index, def.name)
310 }
311
312 #[inline]
313 pub fn to_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
314 Ty::new_param(tcx, self.index, self.name)
315 }
316
317 pub fn span_from_generics(self, tcx: TyCtxt<'tcx>, item_with_generics: DefId) -> Span {
318 let generics = tcx.generics_of(item_with_generics);
319 let type_param = generics.type_param(self, tcx);
320 tcx.def_span(type_param.def_id)
321 }
322}
323
324#[derive(Copy, Clone, Hash, TyEncodable, TyDecodable, Eq, PartialEq, Ord, PartialOrd)]
325#[derive(HashStable)]
326pub struct ParamConst {
327 pub index: u32,
328 pub name: Symbol,
329}
330
331impl rustc_type_ir::inherent::ParamLike for ParamConst {
332 fn index(self) -> u32 {
333 self.index
334 }
335}
336
337impl ParamConst {
338 pub fn new(index: u32, name: Symbol) -> ParamConst {
339 ParamConst { index, name }
340 }
341
342 pub fn for_def(def: &ty::GenericParamDef) -> ParamConst {
343 ParamConst::new(def.index, def.name)
344 }
345
346 pub fn find_ty_from_env<'tcx>(self, env: ParamEnv<'tcx>) -> Ty<'tcx> {
347 let mut candidates = env.caller_bounds().iter().filter_map(|clause| {
348 match clause.kind().skip_binder() {
350 ty::ClauseKind::ConstArgHasType(param_ct, ty) => {
351 assert!(!(param_ct, ty).has_escaping_bound_vars());
352
353 match param_ct.kind() {
354 ty::ConstKind::Param(param_ct) if param_ct.index == self.index => Some(ty),
355 _ => None,
356 }
357 }
358 _ => None,
359 }
360 });
361
362 let ty = candidates.next().unwrap();
363 assert!(candidates.next().is_none());
364 ty
365 }
366}
367
368#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
369#[derive(HashStable)]
370pub struct BoundTy {
371 pub var: BoundVar,
372 pub kind: BoundTyKind,
373}
374
375impl<'tcx> rustc_type_ir::inherent::BoundVarLike<TyCtxt<'tcx>> for BoundTy {
376 fn var(self) -> BoundVar {
377 self.var
378 }
379
380 fn assert_eq(self, var: ty::BoundVariableKind) {
381 assert_eq!(self.kind, var.expect_ty())
382 }
383}
384
385#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
386#[derive(HashStable)]
387pub enum BoundTyKind {
388 Anon,
389 Param(DefId, Symbol),
390}
391
392impl From<BoundVar> for BoundTy {
393 fn from(var: BoundVar) -> Self {
394 BoundTy { var, kind: BoundTyKind::Anon }
395 }
396}
397
398impl<'tcx> Ty<'tcx> {
400 #[allow(rustc::usage_of_ty_tykind)]
403 #[inline]
404 fn new(tcx: TyCtxt<'tcx>, st: TyKind<'tcx>) -> Ty<'tcx> {
405 tcx.mk_ty_from_kind(st)
406 }
407
408 #[inline]
409 pub fn new_infer(tcx: TyCtxt<'tcx>, infer: ty::InferTy) -> Ty<'tcx> {
410 Ty::new(tcx, TyKind::Infer(infer))
411 }
412
413 #[inline]
414 pub fn new_var(tcx: TyCtxt<'tcx>, v: ty::TyVid) -> Ty<'tcx> {
415 tcx.types
417 .ty_vars
418 .get(v.as_usize())
419 .copied()
420 .unwrap_or_else(|| Ty::new(tcx, Infer(TyVar(v))))
421 }
422
423 #[inline]
424 pub fn new_int_var(tcx: TyCtxt<'tcx>, v: ty::IntVid) -> Ty<'tcx> {
425 Ty::new_infer(tcx, IntVar(v))
426 }
427
428 #[inline]
429 pub fn new_float_var(tcx: TyCtxt<'tcx>, v: ty::FloatVid) -> Ty<'tcx> {
430 Ty::new_infer(tcx, FloatVar(v))
431 }
432
433 #[inline]
434 pub fn new_fresh(tcx: TyCtxt<'tcx>, n: u32) -> Ty<'tcx> {
435 tcx.types
437 .fresh_tys
438 .get(n as usize)
439 .copied()
440 .unwrap_or_else(|| Ty::new_infer(tcx, ty::FreshTy(n)))
441 }
442
443 #[inline]
444 pub fn new_fresh_int(tcx: TyCtxt<'tcx>, n: u32) -> Ty<'tcx> {
445 tcx.types
447 .fresh_int_tys
448 .get(n as usize)
449 .copied()
450 .unwrap_or_else(|| Ty::new_infer(tcx, ty::FreshIntTy(n)))
451 }
452
453 #[inline]
454 pub fn new_fresh_float(tcx: TyCtxt<'tcx>, n: u32) -> Ty<'tcx> {
455 tcx.types
457 .fresh_float_tys
458 .get(n as usize)
459 .copied()
460 .unwrap_or_else(|| Ty::new_infer(tcx, ty::FreshFloatTy(n)))
461 }
462
463 #[inline]
464 pub fn new_param(tcx: TyCtxt<'tcx>, index: u32, name: Symbol) -> Ty<'tcx> {
465 tcx.mk_ty_from_kind(Param(ParamTy { index, name }))
466 }
467
468 #[inline]
469 pub fn new_bound(
470 tcx: TyCtxt<'tcx>,
471 index: ty::DebruijnIndex,
472 bound_ty: ty::BoundTy,
473 ) -> Ty<'tcx> {
474 Ty::new(tcx, Bound(index, bound_ty))
475 }
476
477 #[inline]
478 pub fn new_placeholder(tcx: TyCtxt<'tcx>, placeholder: ty::PlaceholderType) -> Ty<'tcx> {
479 Ty::new(tcx, Placeholder(placeholder))
480 }
481
482 #[inline]
483 pub fn new_alias(
484 tcx: TyCtxt<'tcx>,
485 kind: ty::AliasTyKind,
486 alias_ty: ty::AliasTy<'tcx>,
487 ) -> Ty<'tcx> {
488 debug_assert_matches!(
489 (kind, tcx.def_kind(alias_ty.def_id)),
490 (ty::Opaque, DefKind::OpaqueTy)
491 | (ty::Projection | ty::Inherent, DefKind::AssocTy)
492 | (ty::Weak, DefKind::TyAlias)
493 );
494 Ty::new(tcx, Alias(kind, alias_ty))
495 }
496
497 #[inline]
498 pub fn new_pat(tcx: TyCtxt<'tcx>, base: Ty<'tcx>, pat: ty::Pattern<'tcx>) -> Ty<'tcx> {
499 Ty::new(tcx, Pat(base, pat))
500 }
501
502 #[inline]
503 #[instrument(level = "debug", skip(tcx))]
504 pub fn new_opaque(tcx: TyCtxt<'tcx>, def_id: DefId, args: GenericArgsRef<'tcx>) -> Ty<'tcx> {
505 Ty::new_alias(tcx, ty::Opaque, AliasTy::new_from_args(tcx, def_id, args))
506 }
507
508 pub fn new_error(tcx: TyCtxt<'tcx>, guar: ErrorGuaranteed) -> Ty<'tcx> {
510 Ty::new(tcx, Error(guar))
511 }
512
513 #[track_caller]
515 pub fn new_misc_error(tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
516 Ty::new_error_with_message(tcx, DUMMY_SP, "TyKind::Error constructed but no error reported")
517 }
518
519 #[track_caller]
522 pub fn new_error_with_message<S: Into<MultiSpan>>(
523 tcx: TyCtxt<'tcx>,
524 span: S,
525 msg: impl Into<Cow<'static, str>>,
526 ) -> Ty<'tcx> {
527 let reported = tcx.dcx().span_delayed_bug(span, msg);
528 Ty::new(tcx, Error(reported))
529 }
530
531 #[inline]
532 pub fn new_int(tcx: TyCtxt<'tcx>, i: ty::IntTy) -> Ty<'tcx> {
533 use ty::IntTy::*;
534 match i {
535 Isize => tcx.types.isize,
536 I8 => tcx.types.i8,
537 I16 => tcx.types.i16,
538 I32 => tcx.types.i32,
539 I64 => tcx.types.i64,
540 I128 => tcx.types.i128,
541 }
542 }
543
544 #[inline]
545 pub fn new_uint(tcx: TyCtxt<'tcx>, ui: ty::UintTy) -> Ty<'tcx> {
546 use ty::UintTy::*;
547 match ui {
548 Usize => tcx.types.usize,
549 U8 => tcx.types.u8,
550 U16 => tcx.types.u16,
551 U32 => tcx.types.u32,
552 U64 => tcx.types.u64,
553 U128 => tcx.types.u128,
554 }
555 }
556
557 #[inline]
558 pub fn new_float(tcx: TyCtxt<'tcx>, f: ty::FloatTy) -> Ty<'tcx> {
559 use ty::FloatTy::*;
560 match f {
561 F16 => tcx.types.f16,
562 F32 => tcx.types.f32,
563 F64 => tcx.types.f64,
564 F128 => tcx.types.f128,
565 }
566 }
567
568 #[inline]
569 pub fn new_ref(
570 tcx: TyCtxt<'tcx>,
571 r: Region<'tcx>,
572 ty: Ty<'tcx>,
573 mutbl: ty::Mutability,
574 ) -> Ty<'tcx> {
575 Ty::new(tcx, Ref(r, ty, mutbl))
576 }
577
578 #[inline]
579 pub fn new_mut_ref(tcx: TyCtxt<'tcx>, r: Region<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
580 Ty::new_ref(tcx, r, ty, hir::Mutability::Mut)
581 }
582
583 #[inline]
584 pub fn new_imm_ref(tcx: TyCtxt<'tcx>, r: Region<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
585 Ty::new_ref(tcx, r, ty, hir::Mutability::Not)
586 }
587
588 pub fn new_pinned_ref(
589 tcx: TyCtxt<'tcx>,
590 r: Region<'tcx>,
591 ty: Ty<'tcx>,
592 mutbl: ty::Mutability,
593 ) -> Ty<'tcx> {
594 let pin = tcx.adt_def(tcx.require_lang_item(LangItem::Pin, None));
595 Ty::new_adt(tcx, pin, tcx.mk_args(&[Ty::new_ref(tcx, r, ty, mutbl).into()]))
596 }
597
598 #[inline]
599 pub fn new_ptr(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, mutbl: ty::Mutability) -> Ty<'tcx> {
600 Ty::new(tcx, ty::RawPtr(ty, mutbl))
601 }
602
603 #[inline]
604 pub fn new_mut_ptr(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
605 Ty::new_ptr(tcx, ty, hir::Mutability::Mut)
606 }
607
608 #[inline]
609 pub fn new_imm_ptr(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
610 Ty::new_ptr(tcx, ty, hir::Mutability::Not)
611 }
612
613 #[inline]
614 pub fn new_adt(tcx: TyCtxt<'tcx>, def: AdtDef<'tcx>, args: GenericArgsRef<'tcx>) -> Ty<'tcx> {
615 tcx.debug_assert_args_compatible(def.did(), args);
616 if cfg!(debug_assertions) {
617 match tcx.def_kind(def.did()) {
618 DefKind::Struct | DefKind::Union | DefKind::Enum => {}
619 DefKind::Mod
620 | DefKind::Variant
621 | DefKind::Trait
622 | DefKind::TyAlias
623 | DefKind::ForeignTy
624 | DefKind::TraitAlias
625 | DefKind::AssocTy
626 | DefKind::TyParam
627 | DefKind::Fn
628 | DefKind::Const
629 | DefKind::ConstParam
630 | DefKind::Static { .. }
631 | DefKind::Ctor(..)
632 | DefKind::AssocFn
633 | DefKind::AssocConst
634 | DefKind::Macro(..)
635 | DefKind::ExternCrate
636 | DefKind::Use
637 | DefKind::ForeignMod
638 | DefKind::AnonConst
639 | DefKind::InlineConst
640 | DefKind::OpaqueTy
641 | DefKind::Field
642 | DefKind::LifetimeParam
643 | DefKind::GlobalAsm
644 | DefKind::Impl { .. }
645 | DefKind::Closure
646 | DefKind::SyntheticCoroutineBody => {
647 bug!("not an adt: {def:?} ({:?})", tcx.def_kind(def.did()))
648 }
649 }
650 }
651 Ty::new(tcx, Adt(def, args))
652 }
653
654 #[inline]
655 pub fn new_foreign(tcx: TyCtxt<'tcx>, def_id: DefId) -> Ty<'tcx> {
656 Ty::new(tcx, Foreign(def_id))
657 }
658
659 #[inline]
660 pub fn new_array(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, n: u64) -> Ty<'tcx> {
661 Ty::new(tcx, Array(ty, ty::Const::from_target_usize(tcx, n)))
662 }
663
664 #[inline]
665 pub fn new_array_with_const_len(
666 tcx: TyCtxt<'tcx>,
667 ty: Ty<'tcx>,
668 ct: ty::Const<'tcx>,
669 ) -> Ty<'tcx> {
670 Ty::new(tcx, Array(ty, ct))
671 }
672
673 #[inline]
674 pub fn new_slice(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
675 Ty::new(tcx, Slice(ty))
676 }
677
678 #[inline]
679 pub fn new_tup(tcx: TyCtxt<'tcx>, ts: &[Ty<'tcx>]) -> Ty<'tcx> {
680 if ts.is_empty() { tcx.types.unit } else { Ty::new(tcx, Tuple(tcx.mk_type_list(ts))) }
681 }
682
683 pub fn new_tup_from_iter<I, T>(tcx: TyCtxt<'tcx>, iter: I) -> T::Output
684 where
685 I: Iterator<Item = T>,
686 T: CollectAndApply<Ty<'tcx>, Ty<'tcx>>,
687 {
688 T::collect_and_apply(iter, |ts| Ty::new_tup(tcx, ts))
689 }
690
691 #[inline]
692 pub fn new_fn_def(
693 tcx: TyCtxt<'tcx>,
694 def_id: DefId,
695 args: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
696 ) -> Ty<'tcx> {
697 debug_assert_matches!(
698 tcx.def_kind(def_id),
699 DefKind::AssocFn | DefKind::Fn | DefKind::Ctor(_, CtorKind::Fn)
700 );
701 let args = tcx.check_and_mk_args(def_id, args);
702 Ty::new(tcx, FnDef(def_id, args))
703 }
704
705 #[inline]
706 pub fn new_fn_ptr(tcx: TyCtxt<'tcx>, fty: PolyFnSig<'tcx>) -> Ty<'tcx> {
707 let (sig_tys, hdr) = fty.split();
708 Ty::new(tcx, FnPtr(sig_tys, hdr))
709 }
710
711 #[inline]
712 pub fn new_unsafe_binder(tcx: TyCtxt<'tcx>, b: Binder<'tcx, Ty<'tcx>>) -> Ty<'tcx> {
713 Ty::new(tcx, UnsafeBinder(b.into()))
714 }
715
716 #[inline]
717 pub fn new_dynamic(
718 tcx: TyCtxt<'tcx>,
719 obj: &'tcx List<ty::PolyExistentialPredicate<'tcx>>,
720 reg: ty::Region<'tcx>,
721 repr: DynKind,
722 ) -> Ty<'tcx> {
723 Ty::new(tcx, Dynamic(obj, reg, repr))
724 }
725
726 #[inline]
727 pub fn new_projection_from_args(
728 tcx: TyCtxt<'tcx>,
729 item_def_id: DefId,
730 args: ty::GenericArgsRef<'tcx>,
731 ) -> Ty<'tcx> {
732 Ty::new_alias(tcx, ty::Projection, AliasTy::new_from_args(tcx, item_def_id, args))
733 }
734
735 #[inline]
736 pub fn new_projection(
737 tcx: TyCtxt<'tcx>,
738 item_def_id: DefId,
739 args: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
740 ) -> Ty<'tcx> {
741 Ty::new_alias(tcx, ty::Projection, AliasTy::new(tcx, item_def_id, args))
742 }
743
744 #[inline]
745 pub fn new_closure(
746 tcx: TyCtxt<'tcx>,
747 def_id: DefId,
748 closure_args: GenericArgsRef<'tcx>,
749 ) -> Ty<'tcx> {
750 tcx.debug_assert_args_compatible(def_id, closure_args);
751 Ty::new(tcx, Closure(def_id, closure_args))
752 }
753
754 #[inline]
755 pub fn new_coroutine_closure(
756 tcx: TyCtxt<'tcx>,
757 def_id: DefId,
758 closure_args: GenericArgsRef<'tcx>,
759 ) -> Ty<'tcx> {
760 tcx.debug_assert_args_compatible(def_id, closure_args);
761 Ty::new(tcx, CoroutineClosure(def_id, closure_args))
762 }
763
764 #[inline]
765 pub fn new_coroutine(
766 tcx: TyCtxt<'tcx>,
767 def_id: DefId,
768 coroutine_args: GenericArgsRef<'tcx>,
769 ) -> Ty<'tcx> {
770 tcx.debug_assert_args_compatible(def_id, coroutine_args);
771 Ty::new(tcx, Coroutine(def_id, coroutine_args))
772 }
773
774 #[inline]
775 pub fn new_coroutine_witness(
776 tcx: TyCtxt<'tcx>,
777 id: DefId,
778 args: GenericArgsRef<'tcx>,
779 ) -> Ty<'tcx> {
780 Ty::new(tcx, CoroutineWitness(id, args))
781 }
782
783 #[inline]
786 pub fn new_static_str(tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
787 Ty::new_imm_ref(tcx, tcx.lifetimes.re_static, tcx.types.str_)
788 }
789
790 #[inline]
791 pub fn new_diverging_default(tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
792 if tcx.features().never_type_fallback() { tcx.types.never } else { tcx.types.unit }
793 }
794
795 fn new_generic_adt(tcx: TyCtxt<'tcx>, wrapper_def_id: DefId, ty_param: Ty<'tcx>) -> Ty<'tcx> {
798 let adt_def = tcx.adt_def(wrapper_def_id);
799 let args = GenericArgs::for_item(tcx, wrapper_def_id, |param, args| match param.kind {
800 GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => bug!(),
801 GenericParamDefKind::Type { has_default, .. } => {
802 if param.index == 0 {
803 ty_param.into()
804 } else {
805 assert!(has_default);
806 tcx.type_of(param.def_id).instantiate(tcx, args).into()
807 }
808 }
809 });
810 Ty::new_adt(tcx, adt_def, args)
811 }
812
813 #[inline]
814 pub fn new_lang_item(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, item: LangItem) -> Option<Ty<'tcx>> {
815 let def_id = tcx.lang_items().get(item)?;
816 Some(Ty::new_generic_adt(tcx, def_id, ty))
817 }
818
819 #[inline]
820 pub fn new_diagnostic_item(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, name: Symbol) -> Option<Ty<'tcx>> {
821 let def_id = tcx.get_diagnostic_item(name)?;
822 Some(Ty::new_generic_adt(tcx, def_id, ty))
823 }
824
825 #[inline]
826 pub fn new_box(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
827 let def_id = tcx.require_lang_item(LangItem::OwnedBox, None);
828 Ty::new_generic_adt(tcx, def_id, ty)
829 }
830
831 #[inline]
832 pub fn new_maybe_uninit(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
833 let def_id = tcx.require_lang_item(LangItem::MaybeUninit, None);
834 Ty::new_generic_adt(tcx, def_id, ty)
835 }
836
837 pub fn new_task_context(tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
839 let context_did = tcx.require_lang_item(LangItem::Context, None);
840 let context_adt_ref = tcx.adt_def(context_did);
841 let context_args = tcx.mk_args(&[tcx.lifetimes.re_erased.into()]);
842 let context_ty = Ty::new_adt(tcx, context_adt_ref, context_args);
843 Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, context_ty)
844 }
845}
846
847impl<'tcx> rustc_type_ir::inherent::Ty<TyCtxt<'tcx>> for Ty<'tcx> {
848 fn new_bool(tcx: TyCtxt<'tcx>) -> Self {
849 tcx.types.bool
850 }
851
852 fn new_u8(tcx: TyCtxt<'tcx>) -> Self {
853 tcx.types.u8
854 }
855
856 fn new_infer(tcx: TyCtxt<'tcx>, infer: ty::InferTy) -> Self {
857 Ty::new_infer(tcx, infer)
858 }
859
860 fn new_var(tcx: TyCtxt<'tcx>, vid: ty::TyVid) -> Self {
861 Ty::new_var(tcx, vid)
862 }
863
864 fn new_param(tcx: TyCtxt<'tcx>, param: ty::ParamTy) -> Self {
865 Ty::new_param(tcx, param.index, param.name)
866 }
867
868 fn new_placeholder(tcx: TyCtxt<'tcx>, placeholder: ty::PlaceholderType) -> Self {
869 Ty::new_placeholder(tcx, placeholder)
870 }
871
872 fn new_bound(interner: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundTy) -> Self {
873 Ty::new_bound(interner, debruijn, var)
874 }
875
876 fn new_anon_bound(tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self {
877 Ty::new_bound(tcx, debruijn, ty::BoundTy { var, kind: ty::BoundTyKind::Anon })
878 }
879
880 fn new_alias(
881 interner: TyCtxt<'tcx>,
882 kind: ty::AliasTyKind,
883 alias_ty: ty::AliasTy<'tcx>,
884 ) -> Self {
885 Ty::new_alias(interner, kind, alias_ty)
886 }
887
888 fn new_error(interner: TyCtxt<'tcx>, guar: ErrorGuaranteed) -> Self {
889 Ty::new_error(interner, guar)
890 }
891
892 fn new_adt(
893 interner: TyCtxt<'tcx>,
894 adt_def: ty::AdtDef<'tcx>,
895 args: ty::GenericArgsRef<'tcx>,
896 ) -> Self {
897 Ty::new_adt(interner, adt_def, args)
898 }
899
900 fn new_foreign(interner: TyCtxt<'tcx>, def_id: DefId) -> Self {
901 Ty::new_foreign(interner, def_id)
902 }
903
904 fn new_dynamic(
905 interner: TyCtxt<'tcx>,
906 preds: &'tcx List<ty::PolyExistentialPredicate<'tcx>>,
907 region: ty::Region<'tcx>,
908 kind: ty::DynKind,
909 ) -> Self {
910 Ty::new_dynamic(interner, preds, region, kind)
911 }
912
913 fn new_coroutine(
914 interner: TyCtxt<'tcx>,
915 def_id: DefId,
916 args: ty::GenericArgsRef<'tcx>,
917 ) -> Self {
918 Ty::new_coroutine(interner, def_id, args)
919 }
920
921 fn new_coroutine_closure(
922 interner: TyCtxt<'tcx>,
923 def_id: DefId,
924 args: ty::GenericArgsRef<'tcx>,
925 ) -> Self {
926 Ty::new_coroutine_closure(interner, def_id, args)
927 }
928
929 fn new_closure(interner: TyCtxt<'tcx>, def_id: DefId, args: ty::GenericArgsRef<'tcx>) -> Self {
930 Ty::new_closure(interner, def_id, args)
931 }
932
933 fn new_coroutine_witness(
934 interner: TyCtxt<'tcx>,
935 def_id: DefId,
936 args: ty::GenericArgsRef<'tcx>,
937 ) -> Self {
938 Ty::new_coroutine_witness(interner, def_id, args)
939 }
940
941 fn new_ptr(interner: TyCtxt<'tcx>, ty: Self, mutbl: hir::Mutability) -> Self {
942 Ty::new_ptr(interner, ty, mutbl)
943 }
944
945 fn new_ref(
946 interner: TyCtxt<'tcx>,
947 region: ty::Region<'tcx>,
948 ty: Self,
949 mutbl: hir::Mutability,
950 ) -> Self {
951 Ty::new_ref(interner, region, ty, mutbl)
952 }
953
954 fn new_array_with_const_len(interner: TyCtxt<'tcx>, ty: Self, len: ty::Const<'tcx>) -> Self {
955 Ty::new_array_with_const_len(interner, ty, len)
956 }
957
958 fn new_slice(interner: TyCtxt<'tcx>, ty: Self) -> Self {
959 Ty::new_slice(interner, ty)
960 }
961
962 fn new_tup(interner: TyCtxt<'tcx>, tys: &[Ty<'tcx>]) -> Self {
963 Ty::new_tup(interner, tys)
964 }
965
966 fn new_tup_from_iter<It, T>(interner: TyCtxt<'tcx>, iter: It) -> T::Output
967 where
968 It: Iterator<Item = T>,
969 T: CollectAndApply<Self, Self>,
970 {
971 Ty::new_tup_from_iter(interner, iter)
972 }
973
974 fn tuple_fields(self) -> &'tcx ty::List<Ty<'tcx>> {
975 self.tuple_fields()
976 }
977
978 fn to_opt_closure_kind(self) -> Option<ty::ClosureKind> {
979 self.to_opt_closure_kind()
980 }
981
982 fn from_closure_kind(interner: TyCtxt<'tcx>, kind: ty::ClosureKind) -> Self {
983 Ty::from_closure_kind(interner, kind)
984 }
985
986 fn from_coroutine_closure_kind(
987 interner: TyCtxt<'tcx>,
988 kind: rustc_type_ir::ClosureKind,
989 ) -> Self {
990 Ty::from_coroutine_closure_kind(interner, kind)
991 }
992
993 fn new_fn_def(interner: TyCtxt<'tcx>, def_id: DefId, args: ty::GenericArgsRef<'tcx>) -> Self {
994 Ty::new_fn_def(interner, def_id, args)
995 }
996
997 fn new_fn_ptr(interner: TyCtxt<'tcx>, sig: ty::Binder<'tcx, ty::FnSig<'tcx>>) -> Self {
998 Ty::new_fn_ptr(interner, sig)
999 }
1000
1001 fn new_pat(interner: TyCtxt<'tcx>, ty: Self, pat: ty::Pattern<'tcx>) -> Self {
1002 Ty::new_pat(interner, ty, pat)
1003 }
1004
1005 fn new_unsafe_binder(interner: TyCtxt<'tcx>, ty: ty::Binder<'tcx, Ty<'tcx>>) -> Self {
1006 Ty::new_unsafe_binder(interner, ty)
1007 }
1008
1009 fn new_unit(interner: TyCtxt<'tcx>) -> Self {
1010 interner.types.unit
1011 }
1012
1013 fn new_usize(interner: TyCtxt<'tcx>) -> Self {
1014 interner.types.usize
1015 }
1016
1017 fn discriminant_ty(self, interner: TyCtxt<'tcx>) -> Ty<'tcx> {
1018 self.discriminant_ty(interner)
1019 }
1020
1021 fn async_destructor_ty(self, interner: TyCtxt<'tcx>) -> Ty<'tcx> {
1022 self.async_destructor_ty(interner)
1023 }
1024
1025 fn has_unsafe_fields(self) -> bool {
1026 Ty::has_unsafe_fields(self)
1027 }
1028}
1029
1030impl<'tcx> Ty<'tcx> {
1032 #[inline(always)]
1037 pub fn kind(self) -> &'tcx TyKind<'tcx> {
1038 self.0.0
1039 }
1040
1041 #[inline(always)]
1043 pub fn flags(self) -> TypeFlags {
1044 self.0.0.flags
1045 }
1046
1047 #[inline]
1048 pub fn is_unit(self) -> bool {
1049 match self.kind() {
1050 Tuple(tys) => tys.is_empty(),
1051 _ => false,
1052 }
1053 }
1054
1055 #[inline]
1057 pub fn is_usize(self) -> bool {
1058 matches!(self.kind(), Uint(UintTy::Usize))
1059 }
1060
1061 #[inline]
1063 pub fn is_usize_like(self) -> bool {
1064 matches!(self.kind(), Uint(UintTy::Usize) | Infer(IntVar(_)))
1065 }
1066
1067 #[inline]
1068 pub fn is_never(self) -> bool {
1069 matches!(self.kind(), Never)
1070 }
1071
1072 #[inline]
1073 pub fn is_primitive(self) -> bool {
1074 matches!(self.kind(), Bool | Char | Int(_) | Uint(_) | Float(_))
1075 }
1076
1077 #[inline]
1078 pub fn is_adt(self) -> bool {
1079 matches!(self.kind(), Adt(..))
1080 }
1081
1082 #[inline]
1083 pub fn is_ref(self) -> bool {
1084 matches!(self.kind(), Ref(..))
1085 }
1086
1087 #[inline]
1088 pub fn is_ty_var(self) -> bool {
1089 matches!(self.kind(), Infer(TyVar(_)))
1090 }
1091
1092 #[inline]
1093 pub fn ty_vid(self) -> Option<ty::TyVid> {
1094 match self.kind() {
1095 &Infer(TyVar(vid)) => Some(vid),
1096 _ => None,
1097 }
1098 }
1099
1100 #[inline]
1101 pub fn is_ty_or_numeric_infer(self) -> bool {
1102 matches!(self.kind(), Infer(_))
1103 }
1104
1105 #[inline]
1106 pub fn is_phantom_data(self) -> bool {
1107 if let Adt(def, _) = self.kind() { def.is_phantom_data() } else { false }
1108 }
1109
1110 #[inline]
1111 pub fn is_bool(self) -> bool {
1112 *self.kind() == Bool
1113 }
1114
1115 #[inline]
1117 pub fn is_str(self) -> bool {
1118 *self.kind() == Str
1119 }
1120
1121 #[inline]
1122 pub fn is_param(self, index: u32) -> bool {
1123 match self.kind() {
1124 ty::Param(ref data) => data.index == index,
1125 _ => false,
1126 }
1127 }
1128
1129 #[inline]
1130 pub fn is_slice(self) -> bool {
1131 matches!(self.kind(), Slice(_))
1132 }
1133
1134 #[inline]
1135 pub fn is_array_slice(self) -> bool {
1136 match self.kind() {
1137 Slice(_) => true,
1138 ty::RawPtr(ty, _) | Ref(_, ty, _) => matches!(ty.kind(), Slice(_)),
1139 _ => false,
1140 }
1141 }
1142
1143 #[inline]
1144 pub fn is_array(self) -> bool {
1145 matches!(self.kind(), Array(..))
1146 }
1147
1148 #[inline]
1149 pub fn is_simd(self) -> bool {
1150 match self.kind() {
1151 Adt(def, _) => def.repr().simd(),
1152 _ => false,
1153 }
1154 }
1155
1156 pub fn sequence_element_type(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
1157 match self.kind() {
1158 Array(ty, _) | Slice(ty) => *ty,
1159 Str => tcx.types.u8,
1160 _ => bug!("`sequence_element_type` called on non-sequence value: {}", self),
1161 }
1162 }
1163
1164 pub fn simd_size_and_type(self, tcx: TyCtxt<'tcx>) -> (u64, Ty<'tcx>) {
1165 let Adt(def, args) = self.kind() else {
1166 bug!("`simd_size_and_type` called on invalid type")
1167 };
1168 assert!(def.repr().simd(), "`simd_size_and_type` called on non-SIMD type");
1169 let variant = def.non_enum_variant();
1170 assert_eq!(variant.fields.len(), 1);
1171 let field_ty = variant.fields[FieldIdx::ZERO].ty(tcx, args);
1172 let Array(f0_elem_ty, f0_len) = field_ty.kind() else {
1173 bug!("Simd type has non-array field type {field_ty:?}")
1174 };
1175 (
1180 f0_len
1181 .try_to_target_usize(tcx)
1182 .expect("expected SIMD field to have definite array size"),
1183 *f0_elem_ty,
1184 )
1185 }
1186
1187 #[inline]
1188 pub fn is_mutable_ptr(self) -> bool {
1189 matches!(self.kind(), RawPtr(_, hir::Mutability::Mut) | Ref(_, _, hir::Mutability::Mut))
1190 }
1191
1192 #[inline]
1194 pub fn ref_mutability(self) -> Option<hir::Mutability> {
1195 match self.kind() {
1196 Ref(_, _, mutability) => Some(*mutability),
1197 _ => None,
1198 }
1199 }
1200
1201 #[inline]
1202 pub fn is_raw_ptr(self) -> bool {
1203 matches!(self.kind(), RawPtr(_, _))
1204 }
1205
1206 #[inline]
1209 pub fn is_any_ptr(self) -> bool {
1210 self.is_ref() || self.is_raw_ptr() || self.is_fn_ptr()
1211 }
1212
1213 #[inline]
1214 pub fn is_box(self) -> bool {
1215 match self.kind() {
1216 Adt(def, _) => def.is_box(),
1217 _ => false,
1218 }
1219 }
1220
1221 #[inline]
1226 pub fn is_box_global(self, tcx: TyCtxt<'tcx>) -> bool {
1227 match self.kind() {
1228 Adt(def, args) if def.is_box() => {
1229 let Some(alloc) = args.get(1) else {
1230 return true;
1232 };
1233 alloc.expect_ty().ty_adt_def().is_some_and(|alloc_adt| {
1234 let global_alloc = tcx.require_lang_item(LangItem::GlobalAlloc, None);
1235 alloc_adt.did() == global_alloc
1236 })
1237 }
1238 _ => false,
1239 }
1240 }
1241
1242 pub fn boxed_ty(self) -> Option<Ty<'tcx>> {
1243 match self.kind() {
1244 Adt(def, args) if def.is_box() => Some(args.type_at(0)),
1245 _ => None,
1246 }
1247 }
1248
1249 pub fn expect_boxed_ty(self) -> Ty<'tcx> {
1251 self.boxed_ty()
1252 .unwrap_or_else(|| bug!("`expect_boxed_ty` is called on non-box type {:?}", self))
1253 }
1254
1255 #[inline]
1259 pub fn is_scalar(self) -> bool {
1260 matches!(
1261 self.kind(),
1262 Bool | Char
1263 | Int(_)
1264 | Float(_)
1265 | Uint(_)
1266 | FnDef(..)
1267 | FnPtr(..)
1268 | RawPtr(_, _)
1269 | Infer(IntVar(_) | FloatVar(_))
1270 )
1271 }
1272
1273 #[inline]
1275 pub fn is_floating_point(self) -> bool {
1276 matches!(self.kind(), Float(_) | Infer(FloatVar(_)))
1277 }
1278
1279 #[inline]
1280 pub fn is_trait(self) -> bool {
1281 matches!(self.kind(), Dynamic(_, _, ty::Dyn))
1282 }
1283
1284 #[inline]
1285 pub fn is_dyn_star(self) -> bool {
1286 matches!(self.kind(), Dynamic(_, _, ty::DynStar))
1287 }
1288
1289 #[inline]
1290 pub fn is_enum(self) -> bool {
1291 matches!(self.kind(), Adt(adt_def, _) if adt_def.is_enum())
1292 }
1293
1294 #[inline]
1295 pub fn is_union(self) -> bool {
1296 matches!(self.kind(), Adt(adt_def, _) if adt_def.is_union())
1297 }
1298
1299 #[inline]
1300 pub fn is_closure(self) -> bool {
1301 matches!(self.kind(), Closure(..))
1302 }
1303
1304 #[inline]
1305 pub fn is_coroutine(self) -> bool {
1306 matches!(self.kind(), Coroutine(..))
1307 }
1308
1309 #[inline]
1310 pub fn is_coroutine_closure(self) -> bool {
1311 matches!(self.kind(), CoroutineClosure(..))
1312 }
1313
1314 #[inline]
1315 pub fn is_integral(self) -> bool {
1316 matches!(self.kind(), Infer(IntVar(_)) | Int(_) | Uint(_))
1317 }
1318
1319 #[inline]
1320 pub fn is_fresh_ty(self) -> bool {
1321 matches!(self.kind(), Infer(FreshTy(_)))
1322 }
1323
1324 #[inline]
1325 pub fn is_fresh(self) -> bool {
1326 matches!(self.kind(), Infer(FreshTy(_) | FreshIntTy(_) | FreshFloatTy(_)))
1327 }
1328
1329 #[inline]
1330 pub fn is_char(self) -> bool {
1331 matches!(self.kind(), Char)
1332 }
1333
1334 #[inline]
1335 pub fn is_numeric(self) -> bool {
1336 self.is_integral() || self.is_floating_point()
1337 }
1338
1339 #[inline]
1340 pub fn is_signed(self) -> bool {
1341 matches!(self.kind(), Int(_))
1342 }
1343
1344 #[inline]
1345 pub fn is_ptr_sized_integral(self) -> bool {
1346 matches!(self.kind(), Int(ty::IntTy::Isize) | Uint(ty::UintTy::Usize))
1347 }
1348
1349 #[inline]
1350 pub fn has_concrete_skeleton(self) -> bool {
1351 !matches!(self.kind(), Param(_) | Infer(_) | Error(_))
1352 }
1353
1354 pub fn contains(self, other: Ty<'tcx>) -> bool {
1358 struct ContainsTyVisitor<'tcx>(Ty<'tcx>);
1359
1360 impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ContainsTyVisitor<'tcx> {
1361 type Result = ControlFlow<()>;
1362
1363 fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
1364 if self.0 == t { ControlFlow::Break(()) } else { t.super_visit_with(self) }
1365 }
1366 }
1367
1368 let cf = self.visit_with(&mut ContainsTyVisitor(other));
1369 cf.is_break()
1370 }
1371
1372 pub fn contains_closure(self) -> bool {
1376 struct ContainsClosureVisitor;
1377
1378 impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ContainsClosureVisitor {
1379 type Result = ControlFlow<()>;
1380
1381 fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
1382 if let ty::Closure(..) = t.kind() {
1383 ControlFlow::Break(())
1384 } else {
1385 t.super_visit_with(self)
1386 }
1387 }
1388 }
1389
1390 let cf = self.visit_with(&mut ContainsClosureVisitor);
1391 cf.is_break()
1392 }
1393
1394 pub fn builtin_deref(self, explicit: bool) -> Option<Ty<'tcx>> {
1399 match *self.kind() {
1400 _ if let Some(boxed) = self.boxed_ty() => Some(boxed),
1401 Ref(_, ty, _) => Some(ty),
1402 RawPtr(ty, _) if explicit => Some(ty),
1403 _ => None,
1404 }
1405 }
1406
1407 pub fn builtin_index(self) -> Option<Ty<'tcx>> {
1409 match self.kind() {
1410 Array(ty, _) | Slice(ty) => Some(*ty),
1411 _ => None,
1412 }
1413 }
1414
1415 #[tracing::instrument(level = "trace", skip(tcx))]
1416 pub fn fn_sig(self, tcx: TyCtxt<'tcx>) -> PolyFnSig<'tcx> {
1417 match self.kind() {
1418 FnDef(def_id, args) => tcx.fn_sig(*def_id).instantiate(tcx, args),
1419 FnPtr(sig_tys, hdr) => sig_tys.with(*hdr),
1420 Error(_) => {
1421 Binder::dummy(ty::FnSig {
1423 inputs_and_output: ty::List::empty(),
1424 c_variadic: false,
1425 safety: hir::Safety::Safe,
1426 abi: ExternAbi::Rust,
1427 })
1428 }
1429 Closure(..) => bug!(
1430 "to get the signature of a closure, use `args.as_closure().sig()` not `fn_sig()`",
1431 ),
1432 _ => bug!("Ty::fn_sig() called on non-fn type: {:?}", self),
1433 }
1434 }
1435
1436 #[inline]
1437 pub fn is_fn(self) -> bool {
1438 matches!(self.kind(), FnDef(..) | FnPtr(..))
1439 }
1440
1441 #[inline]
1442 pub fn is_fn_ptr(self) -> bool {
1443 matches!(self.kind(), FnPtr(..))
1444 }
1445
1446 #[inline]
1447 pub fn is_impl_trait(self) -> bool {
1448 matches!(self.kind(), Alias(ty::Opaque, ..))
1449 }
1450
1451 #[inline]
1452 pub fn ty_adt_def(self) -> Option<AdtDef<'tcx>> {
1453 match self.kind() {
1454 Adt(adt, _) => Some(*adt),
1455 _ => None,
1456 }
1457 }
1458
1459 #[inline]
1462 pub fn tuple_fields(self) -> &'tcx List<Ty<'tcx>> {
1463 match self.kind() {
1464 Tuple(args) => args,
1465 _ => bug!("tuple_fields called on non-tuple: {self:?}"),
1466 }
1467 }
1468
1469 #[inline]
1473 pub fn variant_range(self, tcx: TyCtxt<'tcx>) -> Option<Range<VariantIdx>> {
1474 match self.kind() {
1475 TyKind::Adt(adt, _) => Some(adt.variant_range()),
1476 TyKind::Coroutine(def_id, args) => {
1477 Some(args.as_coroutine().variant_range(*def_id, tcx))
1478 }
1479 _ => None,
1480 }
1481 }
1482
1483 #[inline]
1488 pub fn discriminant_for_variant(
1489 self,
1490 tcx: TyCtxt<'tcx>,
1491 variant_index: VariantIdx,
1492 ) -> Option<Discr<'tcx>> {
1493 match self.kind() {
1494 TyKind::Adt(adt, _) if adt.is_enum() => {
1495 Some(adt.discriminant_for_variant(tcx, variant_index))
1496 }
1497 TyKind::Coroutine(def_id, args) => {
1498 Some(args.as_coroutine().discriminant_for_variant(*def_id, tcx, variant_index))
1499 }
1500 _ => None,
1501 }
1502 }
1503
1504 pub fn discriminant_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
1506 match self.kind() {
1507 ty::Adt(adt, _) if adt.is_enum() => adt.repr().discr_type().to_ty(tcx),
1508 ty::Coroutine(_, args) => args.as_coroutine().discr_ty(tcx),
1509
1510 ty::Param(_) | ty::Alias(..) | ty::Infer(ty::TyVar(_)) => {
1511 let assoc_items = tcx.associated_item_def_ids(
1512 tcx.require_lang_item(hir::LangItem::DiscriminantKind, None),
1513 );
1514 Ty::new_projection_from_args(tcx, assoc_items[0], tcx.mk_args(&[self.into()]))
1515 }
1516
1517 ty::Pat(ty, _) => ty.discriminant_ty(tcx),
1518
1519 ty::Bool
1520 | ty::Char
1521 | ty::Int(_)
1522 | ty::Uint(_)
1523 | ty::Float(_)
1524 | ty::Adt(..)
1525 | ty::Foreign(_)
1526 | ty::Str
1527 | ty::Array(..)
1528 | ty::Slice(_)
1529 | ty::RawPtr(_, _)
1530 | ty::Ref(..)
1531 | ty::FnDef(..)
1532 | ty::FnPtr(..)
1533 | ty::Dynamic(..)
1534 | ty::Closure(..)
1535 | ty::CoroutineClosure(..)
1536 | ty::CoroutineWitness(..)
1537 | ty::Never
1538 | ty::Tuple(_)
1539 | ty::UnsafeBinder(_)
1540 | ty::Error(_)
1541 | ty::Infer(IntVar(_) | FloatVar(_)) => tcx.types.u8,
1542
1543 ty::Bound(..)
1544 | ty::Placeholder(_)
1545 | ty::Infer(FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
1546 bug!("`discriminant_ty` applied to unexpected type: {:?}", self)
1547 }
1548 }
1549 }
1550
1551 pub fn async_destructor_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
1553 match self.async_drop_glue_morphology(tcx) {
1554 AsyncDropGlueMorphology::Noop => {
1555 return Ty::async_destructor_combinator(tcx, LangItem::AsyncDropNoop)
1556 .instantiate_identity();
1557 }
1558 AsyncDropGlueMorphology::DeferredDropInPlace => {
1559 let drop_in_place =
1560 Ty::async_destructor_combinator(tcx, LangItem::AsyncDropDeferredDropInPlace)
1561 .instantiate(tcx, &[self.into()]);
1562 return Ty::async_destructor_combinator(tcx, LangItem::AsyncDropFuse)
1563 .instantiate(tcx, &[drop_in_place.into()]);
1564 }
1565 AsyncDropGlueMorphology::Custom => (),
1566 }
1567
1568 match *self.kind() {
1569 ty::Param(_) | ty::Alias(..) | ty::Infer(ty::TyVar(_)) => {
1570 let assoc_items = tcx
1571 .associated_item_def_ids(tcx.require_lang_item(LangItem::AsyncDestruct, None));
1572 Ty::new_projection(tcx, assoc_items[0], [self])
1573 }
1574
1575 ty::Array(elem_ty, _) | ty::Slice(elem_ty) => {
1576 let dtor = Ty::async_destructor_combinator(tcx, LangItem::AsyncDropSlice)
1577 .instantiate(tcx, &[elem_ty.into()]);
1578 Ty::async_destructor_combinator(tcx, LangItem::AsyncDropFuse)
1579 .instantiate(tcx, &[dtor.into()])
1580 }
1581
1582 ty::Adt(adt_def, args) if adt_def.is_enum() || adt_def.is_struct() => self
1583 .adt_async_destructor_ty(
1584 tcx,
1585 adt_def.variants().iter().map(|v| v.fields.iter().map(|f| f.ty(tcx, args))),
1586 ),
1587 ty::Tuple(tys) => self.adt_async_destructor_ty(tcx, iter::once(tys)),
1588 ty::Closure(_, args) => {
1589 self.adt_async_destructor_ty(tcx, iter::once(args.as_closure().upvar_tys()))
1590 }
1591 ty::CoroutineClosure(_, args) => self
1592 .adt_async_destructor_ty(tcx, iter::once(args.as_coroutine_closure().upvar_tys())),
1593
1594 ty::Adt(adt_def, _) => {
1595 assert!(adt_def.is_union());
1596
1597 let surface_drop = self.surface_async_dropper_ty(tcx).unwrap();
1598
1599 Ty::async_destructor_combinator(tcx, LangItem::AsyncDropFuse)
1600 .instantiate(tcx, &[surface_drop.into()])
1601 }
1602
1603 ty::Bound(..)
1604 | ty::Foreign(_)
1605 | ty::Placeholder(_)
1606 | ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
1607 bug!("`async_destructor_ty` applied to unexpected type: {self:?}")
1608 }
1609
1610 _ => bug!("`async_destructor_ty` is not yet implemented for type: {self:?}"),
1611 }
1612 }
1613
1614 fn adt_async_destructor_ty<I>(self, tcx: TyCtxt<'tcx>, variants: I) -> Ty<'tcx>
1615 where
1616 I: Iterator + ExactSizeIterator,
1617 I::Item: IntoIterator<Item = Ty<'tcx>>,
1618 {
1619 debug_assert_eq!(self.async_drop_glue_morphology(tcx), AsyncDropGlueMorphology::Custom);
1620
1621 let defer = Ty::async_destructor_combinator(tcx, LangItem::AsyncDropDefer);
1622 let chain = Ty::async_destructor_combinator(tcx, LangItem::AsyncDropChain);
1623
1624 let noop =
1625 Ty::async_destructor_combinator(tcx, LangItem::AsyncDropNoop).instantiate_identity();
1626 let either = Ty::async_destructor_combinator(tcx, LangItem::AsyncDropEither);
1627
1628 let variants_dtor = variants
1629 .into_iter()
1630 .map(|variant| {
1631 variant
1632 .into_iter()
1633 .map(|ty| defer.instantiate(tcx, &[ty.into()]))
1634 .reduce(|acc, next| chain.instantiate(tcx, &[acc.into(), next.into()]))
1635 .unwrap_or(noop)
1636 })
1637 .reduce(|other, matched| {
1638 either.instantiate(tcx, &[other.into(), matched.into(), self.into()])
1639 })
1640 .unwrap();
1641
1642 let dtor = if let Some(dropper_ty) = self.surface_async_dropper_ty(tcx) {
1643 Ty::async_destructor_combinator(tcx, LangItem::AsyncDropChain)
1644 .instantiate(tcx, &[dropper_ty.into(), variants_dtor.into()])
1645 } else {
1646 variants_dtor
1647 };
1648
1649 Ty::async_destructor_combinator(tcx, LangItem::AsyncDropFuse)
1650 .instantiate(tcx, &[dtor.into()])
1651 }
1652
1653 fn surface_async_dropper_ty(self, tcx: TyCtxt<'tcx>) -> Option<Ty<'tcx>> {
1654 let adt_def = self.ty_adt_def()?;
1655 let dropper = adt_def
1656 .async_destructor(tcx)
1657 .map(|_| LangItem::SurfaceAsyncDropInPlace)
1658 .or_else(|| adt_def.destructor(tcx).map(|_| LangItem::AsyncDropSurfaceDropInPlace))?;
1659 Some(Ty::async_destructor_combinator(tcx, dropper).instantiate(tcx, &[self.into()]))
1660 }
1661
1662 fn async_destructor_combinator(
1663 tcx: TyCtxt<'tcx>,
1664 lang_item: LangItem,
1665 ) -> ty::EarlyBinder<'tcx, Ty<'tcx>> {
1666 tcx.fn_sig(tcx.require_lang_item(lang_item, None))
1667 .map_bound(|fn_sig| fn_sig.output().no_bound_vars().unwrap())
1668 }
1669
1670 pub fn ptr_metadata_ty_or_tail(
1673 self,
1674 tcx: TyCtxt<'tcx>,
1675 normalize: impl FnMut(Ty<'tcx>) -> Ty<'tcx>,
1676 ) -> Result<Ty<'tcx>, Ty<'tcx>> {
1677 let tail = tcx.struct_tail_raw(self, normalize, || {});
1678 match tail.kind() {
1679 ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
1681 | ty::Uint(_)
1682 | ty::Int(_)
1683 | ty::Bool
1684 | ty::Float(_)
1685 | ty::FnDef(..)
1686 | ty::FnPtr(..)
1687 | ty::RawPtr(..)
1688 | ty::Char
1689 | ty::Ref(..)
1690 | ty::Coroutine(..)
1691 | ty::CoroutineWitness(..)
1692 | ty::Array(..)
1693 | ty::Closure(..)
1694 | ty::CoroutineClosure(..)
1695 | ty::Never
1696 | ty::Error(_)
1697 | ty::Foreign(..)
1699 | ty::Dynamic(_, _, ty::DynStar)
1701 | ty::Adt(..)
1704 | ty::Tuple(..) => Ok(tcx.types.unit),
1707
1708 ty::Str | ty::Slice(_) => Ok(tcx.types.usize),
1709
1710 ty::Dynamic(_, _, ty::Dyn) => {
1711 let dyn_metadata = tcx.require_lang_item(LangItem::DynMetadata, None);
1712 Ok(tcx.type_of(dyn_metadata).instantiate(tcx, &[tail.into()]))
1713 }
1714
1715 ty::Param(_) | ty::Alias(..) => Err(tail),
1718
1719 | ty::UnsafeBinder(_) => todo!("FIXME(unsafe_binder)"),
1720
1721 ty::Infer(ty::TyVar(_))
1722 | ty::Pat(..)
1723 | ty::Bound(..)
1724 | ty::Placeholder(..)
1725 | ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => bug!(
1726 "`ptr_metadata_ty_or_tail` applied to unexpected type: {self:?} (tail = {tail:?})"
1727 ),
1728 }
1729 }
1730
1731 pub fn ptr_metadata_ty(
1734 self,
1735 tcx: TyCtxt<'tcx>,
1736 normalize: impl FnMut(Ty<'tcx>) -> Ty<'tcx>,
1737 ) -> Ty<'tcx> {
1738 match self.ptr_metadata_ty_or_tail(tcx, normalize) {
1739 Ok(metadata) => metadata,
1740 Err(tail) => bug!(
1741 "`ptr_metadata_ty` failed to get metadata for type: {self:?} (tail = {tail:?})"
1742 ),
1743 }
1744 }
1745
1746 #[track_caller]
1755 pub fn pointee_metadata_ty_or_projection(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
1756 let Some(pointee_ty) = self.builtin_deref(true) else {
1757 bug!("Type {self:?} is not a pointer or reference type")
1758 };
1759 if pointee_ty.is_trivially_sized(tcx) {
1760 tcx.types.unit
1761 } else {
1762 match pointee_ty.ptr_metadata_ty_or_tail(tcx, |x| x) {
1763 Ok(metadata_ty) => metadata_ty,
1764 Err(tail_ty) => {
1765 let Some(metadata_def_id) = tcx.lang_items().metadata_type() else {
1766 bug!("No metadata_type lang item while looking at {self:?}")
1767 };
1768 Ty::new_projection(tcx, metadata_def_id, [tail_ty])
1769 }
1770 }
1771 }
1772 }
1773
1774 pub fn to_opt_closure_kind(self) -> Option<ty::ClosureKind> {
1814 match self.kind() {
1815 Int(int_ty) => match int_ty {
1816 ty::IntTy::I8 => Some(ty::ClosureKind::Fn),
1817 ty::IntTy::I16 => Some(ty::ClosureKind::FnMut),
1818 ty::IntTy::I32 => Some(ty::ClosureKind::FnOnce),
1819 _ => bug!("cannot convert type `{:?}` to a closure kind", self),
1820 },
1821
1822 Bound(..) | Placeholder(_) | Param(_) | Infer(_) => None,
1826
1827 Error(_) => Some(ty::ClosureKind::Fn),
1828
1829 _ => bug!("cannot convert type `{:?}` to a closure kind", self),
1830 }
1831 }
1832
1833 pub fn from_closure_kind(tcx: TyCtxt<'tcx>, kind: ty::ClosureKind) -> Ty<'tcx> {
1836 match kind {
1837 ty::ClosureKind::Fn => tcx.types.i8,
1838 ty::ClosureKind::FnMut => tcx.types.i16,
1839 ty::ClosureKind::FnOnce => tcx.types.i32,
1840 }
1841 }
1842
1843 pub fn from_coroutine_closure_kind(tcx: TyCtxt<'tcx>, kind: ty::ClosureKind) -> Ty<'tcx> {
1856 match kind {
1857 ty::ClosureKind::Fn | ty::ClosureKind::FnMut => tcx.types.i16,
1858 ty::ClosureKind::FnOnce => tcx.types.i32,
1859 }
1860 }
1861
1862 pub fn is_trivially_sized(self, tcx: TyCtxt<'tcx>) -> bool {
1873 match self.kind() {
1874 ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
1875 | ty::Uint(_)
1876 | ty::Int(_)
1877 | ty::Bool
1878 | ty::Float(_)
1879 | ty::FnDef(..)
1880 | ty::FnPtr(..)
1881 | ty::UnsafeBinder(_)
1882 | ty::RawPtr(..)
1883 | ty::Char
1884 | ty::Ref(..)
1885 | ty::Coroutine(..)
1886 | ty::CoroutineWitness(..)
1887 | ty::Array(..)
1888 | ty::Pat(..)
1889 | ty::Closure(..)
1890 | ty::CoroutineClosure(..)
1891 | ty::Never
1892 | ty::Error(_)
1893 | ty::Dynamic(_, _, ty::DynStar) => true,
1894
1895 ty::Str | ty::Slice(_) | ty::Dynamic(_, _, ty::Dyn) | ty::Foreign(..) => false,
1896
1897 ty::Tuple(tys) => tys.last().is_none_or(|ty| ty.is_trivially_sized(tcx)),
1898
1899 ty::Adt(def, args) => def
1900 .sized_constraint(tcx)
1901 .is_none_or(|ty| ty.instantiate(tcx, args).is_trivially_sized(tcx)),
1902
1903 ty::Alias(..) | ty::Param(_) | ty::Placeholder(..) | ty::Bound(..) => false,
1904
1905 ty::Infer(ty::TyVar(_)) => false,
1906
1907 ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
1908 bug!("`is_trivially_sized` applied to unexpected type: {:?}", self)
1909 }
1910 }
1911 }
1912
1913 pub fn is_trivially_pure_clone_copy(self) -> bool {
1922 match self.kind() {
1923 ty::Bool | ty::Char | ty::Never => true,
1924
1925 ty::Str | ty::Slice(..) | ty::Foreign(..) | ty::Dynamic(..) => false,
1927
1928 ty::Infer(ty::InferTy::FloatVar(_) | ty::InferTy::IntVar(_))
1929 | ty::Int(..)
1930 | ty::Uint(..)
1931 | ty::Float(..) => true,
1932
1933 ty::FnDef(..) => true,
1935
1936 ty::Array(element_ty, _len) => element_ty.is_trivially_pure_clone_copy(),
1937
1938 ty::Tuple(field_tys) => {
1940 field_tys.len() <= 3 && field_tys.iter().all(Self::is_trivially_pure_clone_copy)
1941 }
1942
1943 ty::Pat(ty, _) => ty.is_trivially_pure_clone_copy(),
1944
1945 ty::FnPtr(..) => false,
1948
1949 ty::Ref(_, _, hir::Mutability::Mut) => false,
1951
1952 ty::Ref(_, _, hir::Mutability::Not) | ty::RawPtr(..) => true,
1955
1956 ty::Coroutine(..) | ty::CoroutineWitness(..) => false,
1957
1958 ty::Adt(..) | ty::Closure(..) | ty::CoroutineClosure(..) => false,
1960
1961 ty::UnsafeBinder(_) => false,
1962
1963 ty::Alias(..) => false,
1965
1966 ty::Param(..) | ty::Infer(..) | ty::Error(..) => false,
1967
1968 ty::Bound(..) | ty::Placeholder(..) => {
1969 bug!("`is_trivially_pure_clone_copy` applied to unexpected type: {:?}", self);
1970 }
1971 }
1972 }
1973
1974 pub fn primitive_symbol(self) -> Option<Symbol> {
1976 match self.kind() {
1977 ty::Bool => Some(sym::bool),
1978 ty::Char => Some(sym::char),
1979 ty::Float(f) => match f {
1980 ty::FloatTy::F16 => Some(sym::f16),
1981 ty::FloatTy::F32 => Some(sym::f32),
1982 ty::FloatTy::F64 => Some(sym::f64),
1983 ty::FloatTy::F128 => Some(sym::f128),
1984 },
1985 ty::Int(f) => match f {
1986 ty::IntTy::Isize => Some(sym::isize),
1987 ty::IntTy::I8 => Some(sym::i8),
1988 ty::IntTy::I16 => Some(sym::i16),
1989 ty::IntTy::I32 => Some(sym::i32),
1990 ty::IntTy::I64 => Some(sym::i64),
1991 ty::IntTy::I128 => Some(sym::i128),
1992 },
1993 ty::Uint(f) => match f {
1994 ty::UintTy::Usize => Some(sym::usize),
1995 ty::UintTy::U8 => Some(sym::u8),
1996 ty::UintTy::U16 => Some(sym::u16),
1997 ty::UintTy::U32 => Some(sym::u32),
1998 ty::UintTy::U64 => Some(sym::u64),
1999 ty::UintTy::U128 => Some(sym::u128),
2000 },
2001 ty::Str => Some(sym::str),
2002 _ => None,
2003 }
2004 }
2005
2006 pub fn is_c_void(self, tcx: TyCtxt<'_>) -> bool {
2007 match self.kind() {
2008 ty::Adt(adt, _) => tcx.is_lang_item(adt.did(), LangItem::CVoid),
2009 _ => false,
2010 }
2011 }
2012
2013 pub fn is_known_rigid(self) -> bool {
2019 match self.kind() {
2020 Bool
2021 | Char
2022 | Int(_)
2023 | Uint(_)
2024 | Float(_)
2025 | Adt(_, _)
2026 | Foreign(_)
2027 | Str
2028 | Array(_, _)
2029 | Pat(_, _)
2030 | Slice(_)
2031 | RawPtr(_, _)
2032 | Ref(_, _, _)
2033 | FnDef(_, _)
2034 | FnPtr(..)
2035 | Dynamic(_, _, _)
2036 | Closure(_, _)
2037 | CoroutineClosure(_, _)
2038 | Coroutine(_, _)
2039 | CoroutineWitness(..)
2040 | Never
2041 | Tuple(_)
2042 | UnsafeBinder(_) => true,
2043 Error(_) | Infer(_) | Alias(_, _) | Param(_) | Bound(_, _) | Placeholder(_) => false,
2044 }
2045 }
2046}
2047
2048impl<'tcx> rustc_type_ir::inherent::Tys<TyCtxt<'tcx>> for &'tcx ty::List<Ty<'tcx>> {
2049 fn inputs(self) -> &'tcx [Ty<'tcx>] {
2050 self.split_last().unwrap().1
2051 }
2052
2053 fn output(self) -> Ty<'tcx> {
2054 *self.split_last().unwrap().0
2055 }
2056}
2057
2058#[cfg(target_pointer_width = "64")]
2060mod size_asserts {
2061 use rustc_data_structures::static_assert_size;
2062
2063 use super::*;
2064 static_assert_size!(ty::RegionKind<'_>, 24);
2066 static_assert_size!(ty::TyKind<'_>, 24);
2067 }