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