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<'tcx> Ty<'tcx> {
408 #[allow(rustc::usage_of_ty_tykind)]
411 #[inline]
412 fn new(tcx: TyCtxt<'tcx>, st: TyKind<'tcx>) -> Ty<'tcx> {
413 tcx.mk_ty_from_kind(st)
414 }
415
416 #[inline]
417 pub fn new_infer(tcx: TyCtxt<'tcx>, infer: ty::InferTy) -> Ty<'tcx> {
418 Ty::new(tcx, TyKind::Infer(infer))
419 }
420
421 #[inline]
422 pub fn new_var(tcx: TyCtxt<'tcx>, v: ty::TyVid) -> Ty<'tcx> {
423 tcx.types
425 .ty_vars
426 .get(v.as_usize())
427 .copied()
428 .unwrap_or_else(|| Ty::new(tcx, Infer(TyVar(v))))
429 }
430
431 #[inline]
432 pub fn new_int_var(tcx: TyCtxt<'tcx>, v: ty::IntVid) -> Ty<'tcx> {
433 Ty::new_infer(tcx, IntVar(v))
434 }
435
436 #[inline]
437 pub fn new_float_var(tcx: TyCtxt<'tcx>, v: ty::FloatVid) -> Ty<'tcx> {
438 Ty::new_infer(tcx, FloatVar(v))
439 }
440
441 #[inline]
442 pub fn new_fresh(tcx: TyCtxt<'tcx>, n: u32) -> Ty<'tcx> {
443 tcx.types
445 .fresh_tys
446 .get(n as usize)
447 .copied()
448 .unwrap_or_else(|| Ty::new_infer(tcx, ty::FreshTy(n)))
449 }
450
451 #[inline]
452 pub fn new_fresh_int(tcx: TyCtxt<'tcx>, n: u32) -> Ty<'tcx> {
453 tcx.types
455 .fresh_int_tys
456 .get(n as usize)
457 .copied()
458 .unwrap_or_else(|| Ty::new_infer(tcx, ty::FreshIntTy(n)))
459 }
460
461 #[inline]
462 pub fn new_fresh_float(tcx: TyCtxt<'tcx>, n: u32) -> Ty<'tcx> {
463 tcx.types
465 .fresh_float_tys
466 .get(n as usize)
467 .copied()
468 .unwrap_or_else(|| Ty::new_infer(tcx, ty::FreshFloatTy(n)))
469 }
470
471 #[inline]
472 pub fn new_param(tcx: TyCtxt<'tcx>, index: u32, name: Symbol) -> Ty<'tcx> {
473 Ty::new(tcx, Param(ParamTy { index, name }))
474 }
475
476 #[inline]
477 pub fn new_bound(
478 tcx: TyCtxt<'tcx>,
479 index: ty::DebruijnIndex,
480 bound_ty: ty::BoundTy,
481 ) -> Ty<'tcx> {
482 if let ty::BoundTy { var, kind: ty::BoundTyKind::Anon } = bound_ty
484 && let Some(inner) = tcx.types.anon_bound_tys.get(index.as_usize())
485 && let Some(ty) = inner.get(var.as_usize()).copied()
486 {
487 ty
488 } else {
489 Ty::new(tcx, Bound(index, bound_ty))
490 }
491 }
492
493 #[inline]
494 pub fn new_placeholder(tcx: TyCtxt<'tcx>, placeholder: ty::PlaceholderType) -> Ty<'tcx> {
495 Ty::new(tcx, Placeholder(placeholder))
496 }
497
498 #[inline]
499 pub fn new_alias(
500 tcx: TyCtxt<'tcx>,
501 kind: ty::AliasTyKind,
502 alias_ty: ty::AliasTy<'tcx>,
503 ) -> Ty<'tcx> {
504 debug_assert_matches!(
505 (kind, tcx.def_kind(alias_ty.def_id)),
506 (ty::Opaque, DefKind::OpaqueTy)
507 | (ty::Projection | ty::Inherent, DefKind::AssocTy)
508 | (ty::Free, DefKind::TyAlias)
509 );
510 Ty::new(tcx, Alias(kind, alias_ty))
511 }
512
513 #[inline]
514 pub fn new_pat(tcx: TyCtxt<'tcx>, base: Ty<'tcx>, pat: ty::Pattern<'tcx>) -> Ty<'tcx> {
515 Ty::new(tcx, Pat(base, pat))
516 }
517
518 #[inline]
519 #[instrument(level = "debug", skip(tcx))]
520 pub fn new_opaque(tcx: TyCtxt<'tcx>, def_id: DefId, args: GenericArgsRef<'tcx>) -> Ty<'tcx> {
521 Ty::new_alias(tcx, ty::Opaque, AliasTy::new_from_args(tcx, def_id, args))
522 }
523
524 pub fn new_error(tcx: TyCtxt<'tcx>, guar: ErrorGuaranteed) -> Ty<'tcx> {
526 Ty::new(tcx, Error(guar))
527 }
528
529 #[track_caller]
531 pub fn new_misc_error(tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
532 Ty::new_error_with_message(tcx, DUMMY_SP, "TyKind::Error constructed but no error reported")
533 }
534
535 #[track_caller]
538 pub fn new_error_with_message<S: Into<MultiSpan>>(
539 tcx: TyCtxt<'tcx>,
540 span: S,
541 msg: impl Into<Cow<'static, str>>,
542 ) -> Ty<'tcx> {
543 let reported = tcx.dcx().span_delayed_bug(span, msg);
544 Ty::new(tcx, Error(reported))
545 }
546
547 #[inline]
548 pub fn new_int(tcx: TyCtxt<'tcx>, i: ty::IntTy) -> Ty<'tcx> {
549 use ty::IntTy::*;
550 match i {
551 Isize => tcx.types.isize,
552 I8 => tcx.types.i8,
553 I16 => tcx.types.i16,
554 I32 => tcx.types.i32,
555 I64 => tcx.types.i64,
556 I128 => tcx.types.i128,
557 }
558 }
559
560 #[inline]
561 pub fn new_uint(tcx: TyCtxt<'tcx>, ui: ty::UintTy) -> Ty<'tcx> {
562 use ty::UintTy::*;
563 match ui {
564 Usize => tcx.types.usize,
565 U8 => tcx.types.u8,
566 U16 => tcx.types.u16,
567 U32 => tcx.types.u32,
568 U64 => tcx.types.u64,
569 U128 => tcx.types.u128,
570 }
571 }
572
573 #[inline]
574 pub fn new_float(tcx: TyCtxt<'tcx>, f: ty::FloatTy) -> Ty<'tcx> {
575 use ty::FloatTy::*;
576 match f {
577 F16 => tcx.types.f16,
578 F32 => tcx.types.f32,
579 F64 => tcx.types.f64,
580 F128 => tcx.types.f128,
581 }
582 }
583
584 #[inline]
585 pub fn new_ref(
586 tcx: TyCtxt<'tcx>,
587 r: Region<'tcx>,
588 ty: Ty<'tcx>,
589 mutbl: ty::Mutability,
590 ) -> Ty<'tcx> {
591 Ty::new(tcx, Ref(r, ty, mutbl))
592 }
593
594 #[inline]
595 pub fn new_mut_ref(tcx: TyCtxt<'tcx>, r: Region<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
596 Ty::new_ref(tcx, r, ty, hir::Mutability::Mut)
597 }
598
599 #[inline]
600 pub fn new_imm_ref(tcx: TyCtxt<'tcx>, r: Region<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
601 Ty::new_ref(tcx, r, ty, hir::Mutability::Not)
602 }
603
604 pub fn new_pinned_ref(
605 tcx: TyCtxt<'tcx>,
606 r: Region<'tcx>,
607 ty: Ty<'tcx>,
608 mutbl: ty::Mutability,
609 ) -> Ty<'tcx> {
610 let pin = tcx.adt_def(tcx.require_lang_item(LangItem::Pin, DUMMY_SP));
611 Ty::new_adt(tcx, pin, tcx.mk_args(&[Ty::new_ref(tcx, r, ty, mutbl).into()]))
612 }
613
614 #[inline]
615 pub fn new_ptr(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, mutbl: ty::Mutability) -> Ty<'tcx> {
616 Ty::new(tcx, ty::RawPtr(ty, mutbl))
617 }
618
619 #[inline]
620 pub fn new_mut_ptr(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
621 Ty::new_ptr(tcx, ty, hir::Mutability::Mut)
622 }
623
624 #[inline]
625 pub fn new_imm_ptr(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
626 Ty::new_ptr(tcx, ty, hir::Mutability::Not)
627 }
628
629 #[inline]
630 pub fn new_adt(tcx: TyCtxt<'tcx>, def: AdtDef<'tcx>, args: GenericArgsRef<'tcx>) -> Ty<'tcx> {
631 tcx.debug_assert_args_compatible(def.did(), args);
632 if cfg!(debug_assertions) {
633 match tcx.def_kind(def.did()) {
634 DefKind::Struct | DefKind::Union | DefKind::Enum => {}
635 DefKind::Mod
636 | DefKind::Variant
637 | DefKind::Trait
638 | DefKind::TyAlias
639 | DefKind::ForeignTy
640 | DefKind::TraitAlias
641 | DefKind::AssocTy
642 | DefKind::TyParam
643 | DefKind::Fn
644 | DefKind::Const
645 | DefKind::ConstParam
646 | DefKind::Static { .. }
647 | DefKind::Ctor(..)
648 | DefKind::AssocFn
649 | DefKind::AssocConst
650 | DefKind::Macro(..)
651 | DefKind::ExternCrate
652 | DefKind::Use
653 | DefKind::ForeignMod
654 | DefKind::AnonConst
655 | DefKind::InlineConst
656 | DefKind::OpaqueTy
657 | DefKind::Field
658 | DefKind::LifetimeParam
659 | DefKind::GlobalAsm
660 | DefKind::Impl { .. }
661 | DefKind::Closure
662 | DefKind::SyntheticCoroutineBody => {
663 bug!("not an adt: {def:?} ({:?})", tcx.def_kind(def.did()))
664 }
665 }
666 }
667 Ty::new(tcx, Adt(def, args))
668 }
669
670 #[inline]
671 pub fn new_foreign(tcx: TyCtxt<'tcx>, def_id: DefId) -> Ty<'tcx> {
672 Ty::new(tcx, Foreign(def_id))
673 }
674
675 #[inline]
676 pub fn new_array(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, n: u64) -> Ty<'tcx> {
677 Ty::new(tcx, Array(ty, ty::Const::from_target_usize(tcx, n)))
678 }
679
680 #[inline]
681 pub fn new_array_with_const_len(
682 tcx: TyCtxt<'tcx>,
683 ty: Ty<'tcx>,
684 ct: ty::Const<'tcx>,
685 ) -> Ty<'tcx> {
686 Ty::new(tcx, Array(ty, ct))
687 }
688
689 #[inline]
690 pub fn new_slice(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
691 Ty::new(tcx, Slice(ty))
692 }
693
694 #[inline]
695 pub fn new_tup(tcx: TyCtxt<'tcx>, ts: &[Ty<'tcx>]) -> Ty<'tcx> {
696 if ts.is_empty() { tcx.types.unit } else { Ty::new(tcx, Tuple(tcx.mk_type_list(ts))) }
697 }
698
699 pub fn new_tup_from_iter<I, T>(tcx: TyCtxt<'tcx>, iter: I) -> T::Output
700 where
701 I: Iterator<Item = T>,
702 T: CollectAndApply<Ty<'tcx>, Ty<'tcx>>,
703 {
704 T::collect_and_apply(iter, |ts| Ty::new_tup(tcx, ts))
705 }
706
707 #[inline]
708 pub fn new_fn_def(
709 tcx: TyCtxt<'tcx>,
710 def_id: DefId,
711 args: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
712 ) -> Ty<'tcx> {
713 debug_assert_matches!(
714 tcx.def_kind(def_id),
715 DefKind::AssocFn | DefKind::Fn | DefKind::Ctor(_, CtorKind::Fn)
716 );
717 let args = tcx.check_and_mk_args(def_id, args);
718 Ty::new(tcx, FnDef(def_id, args))
719 }
720
721 #[inline]
722 pub fn new_fn_ptr(tcx: TyCtxt<'tcx>, fty: PolyFnSig<'tcx>) -> Ty<'tcx> {
723 let (sig_tys, hdr) = fty.split();
724 Ty::new(tcx, FnPtr(sig_tys, hdr))
725 }
726
727 #[inline]
728 pub fn new_unsafe_binder(tcx: TyCtxt<'tcx>, b: Binder<'tcx, Ty<'tcx>>) -> Ty<'tcx> {
729 Ty::new(tcx, UnsafeBinder(b.into()))
730 }
731
732 #[inline]
733 pub fn new_dynamic(
734 tcx: TyCtxt<'tcx>,
735 obj: &'tcx List<ty::PolyExistentialPredicate<'tcx>>,
736 reg: ty::Region<'tcx>,
737 repr: DynKind,
738 ) -> Ty<'tcx> {
739 if cfg!(debug_assertions) {
740 let projection_count = obj
741 .projection_bounds()
742 .filter(|item| !tcx.generics_require_sized_self(item.item_def_id()))
743 .count();
744 let expected_count: usize = obj
745 .principal_def_id()
746 .into_iter()
747 .flat_map(|principal_def_id| {
748 elaborate::supertraits(
751 tcx,
752 ty::Binder::dummy(ty::TraitRef::identity(tcx, principal_def_id)),
753 )
754 .map(|principal| {
755 tcx.associated_items(principal.def_id())
756 .in_definition_order()
757 .filter(|item| item.is_type())
758 .filter(|item| !item.is_impl_trait_in_trait())
759 .filter(|item| !tcx.generics_require_sized_self(item.def_id))
760 .count()
761 })
762 })
763 .sum();
764 assert_eq!(
765 projection_count, expected_count,
766 "expected {obj:?} to have {expected_count} projections, \
767 but it has {projection_count}"
768 );
769 }
770 Ty::new(tcx, Dynamic(obj, reg, repr))
771 }
772
773 #[inline]
774 pub fn new_projection_from_args(
775 tcx: TyCtxt<'tcx>,
776 item_def_id: DefId,
777 args: ty::GenericArgsRef<'tcx>,
778 ) -> Ty<'tcx> {
779 Ty::new_alias(tcx, ty::Projection, AliasTy::new_from_args(tcx, item_def_id, args))
780 }
781
782 #[inline]
783 pub fn new_projection(
784 tcx: TyCtxt<'tcx>,
785 item_def_id: DefId,
786 args: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
787 ) -> Ty<'tcx> {
788 Ty::new_alias(tcx, ty::Projection, AliasTy::new(tcx, item_def_id, args))
789 }
790
791 #[inline]
792 pub fn new_closure(
793 tcx: TyCtxt<'tcx>,
794 def_id: DefId,
795 closure_args: GenericArgsRef<'tcx>,
796 ) -> Ty<'tcx> {
797 tcx.debug_assert_args_compatible(def_id, closure_args);
798 Ty::new(tcx, Closure(def_id, closure_args))
799 }
800
801 #[inline]
802 pub fn new_coroutine_closure(
803 tcx: TyCtxt<'tcx>,
804 def_id: DefId,
805 closure_args: GenericArgsRef<'tcx>,
806 ) -> Ty<'tcx> {
807 tcx.debug_assert_args_compatible(def_id, closure_args);
808 Ty::new(tcx, CoroutineClosure(def_id, closure_args))
809 }
810
811 #[inline]
812 pub fn new_coroutine(
813 tcx: TyCtxt<'tcx>,
814 def_id: DefId,
815 coroutine_args: GenericArgsRef<'tcx>,
816 ) -> Ty<'tcx> {
817 tcx.debug_assert_args_compatible(def_id, coroutine_args);
818 Ty::new(tcx, Coroutine(def_id, coroutine_args))
819 }
820
821 #[inline]
822 pub fn new_coroutine_witness(
823 tcx: TyCtxt<'tcx>,
824 id: DefId,
825 args: GenericArgsRef<'tcx>,
826 ) -> Ty<'tcx> {
827 Ty::new(tcx, CoroutineWitness(id, args))
828 }
829
830 #[inline]
833 pub fn new_static_str(tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
834 Ty::new_imm_ref(tcx, tcx.lifetimes.re_static, tcx.types.str_)
835 }
836
837 #[inline]
838 pub fn new_diverging_default(tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
839 if tcx.features().never_type_fallback() { tcx.types.never } else { tcx.types.unit }
840 }
841
842 fn new_generic_adt(tcx: TyCtxt<'tcx>, wrapper_def_id: DefId, ty_param: Ty<'tcx>) -> Ty<'tcx> {
845 let adt_def = tcx.adt_def(wrapper_def_id);
846 let args = GenericArgs::for_item(tcx, wrapper_def_id, |param, args| match param.kind {
847 GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => bug!(),
848 GenericParamDefKind::Type { has_default, .. } => {
849 if param.index == 0 {
850 ty_param.into()
851 } else {
852 assert!(has_default);
853 tcx.type_of(param.def_id).instantiate(tcx, args).into()
854 }
855 }
856 });
857 Ty::new_adt(tcx, adt_def, args)
858 }
859
860 #[inline]
861 pub fn new_lang_item(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, item: LangItem) -> Option<Ty<'tcx>> {
862 let def_id = tcx.lang_items().get(item)?;
863 Some(Ty::new_generic_adt(tcx, def_id, ty))
864 }
865
866 #[inline]
867 pub fn new_diagnostic_item(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, name: Symbol) -> Option<Ty<'tcx>> {
868 let def_id = tcx.get_diagnostic_item(name)?;
869 Some(Ty::new_generic_adt(tcx, def_id, ty))
870 }
871
872 #[inline]
873 pub fn new_box(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
874 let def_id = tcx.require_lang_item(LangItem::OwnedBox, DUMMY_SP);
875 Ty::new_generic_adt(tcx, def_id, ty)
876 }
877
878 #[inline]
879 pub fn new_maybe_uninit(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
880 let def_id = tcx.require_lang_item(LangItem::MaybeUninit, DUMMY_SP);
881 Ty::new_generic_adt(tcx, def_id, ty)
882 }
883
884 pub fn new_task_context(tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
886 let context_did = tcx.require_lang_item(LangItem::Context, DUMMY_SP);
887 let context_adt_ref = tcx.adt_def(context_did);
888 let context_args = tcx.mk_args(&[tcx.lifetimes.re_erased.into()]);
889 let context_ty = Ty::new_adt(tcx, context_adt_ref, context_args);
890 Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, context_ty)
891 }
892}
893
894impl<'tcx> rustc_type_ir::inherent::Ty<TyCtxt<'tcx>> for Ty<'tcx> {
895 fn new_bool(tcx: TyCtxt<'tcx>) -> Self {
896 tcx.types.bool
897 }
898
899 fn new_u8(tcx: TyCtxt<'tcx>) -> Self {
900 tcx.types.u8
901 }
902
903 fn new_infer(tcx: TyCtxt<'tcx>, infer: ty::InferTy) -> Self {
904 Ty::new_infer(tcx, infer)
905 }
906
907 fn new_var(tcx: TyCtxt<'tcx>, vid: ty::TyVid) -> Self {
908 Ty::new_var(tcx, vid)
909 }
910
911 fn new_param(tcx: TyCtxt<'tcx>, param: ty::ParamTy) -> Self {
912 Ty::new_param(tcx, param.index, param.name)
913 }
914
915 fn new_placeholder(tcx: TyCtxt<'tcx>, placeholder: ty::PlaceholderType) -> Self {
916 Ty::new_placeholder(tcx, placeholder)
917 }
918
919 fn new_bound(interner: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundTy) -> Self {
920 Ty::new_bound(interner, debruijn, var)
921 }
922
923 fn new_anon_bound(tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self {
924 Ty::new_bound(tcx, debruijn, ty::BoundTy { var, kind: ty::BoundTyKind::Anon })
925 }
926
927 fn new_alias(
928 interner: TyCtxt<'tcx>,
929 kind: ty::AliasTyKind,
930 alias_ty: ty::AliasTy<'tcx>,
931 ) -> Self {
932 Ty::new_alias(interner, kind, alias_ty)
933 }
934
935 fn new_error(interner: TyCtxt<'tcx>, guar: ErrorGuaranteed) -> Self {
936 Ty::new_error(interner, guar)
937 }
938
939 fn new_adt(
940 interner: TyCtxt<'tcx>,
941 adt_def: ty::AdtDef<'tcx>,
942 args: ty::GenericArgsRef<'tcx>,
943 ) -> Self {
944 Ty::new_adt(interner, adt_def, args)
945 }
946
947 fn new_foreign(interner: TyCtxt<'tcx>, def_id: DefId) -> Self {
948 Ty::new_foreign(interner, def_id)
949 }
950
951 fn new_dynamic(
952 interner: TyCtxt<'tcx>,
953 preds: &'tcx List<ty::PolyExistentialPredicate<'tcx>>,
954 region: ty::Region<'tcx>,
955 kind: ty::DynKind,
956 ) -> Self {
957 Ty::new_dynamic(interner, preds, region, kind)
958 }
959
960 fn new_coroutine(
961 interner: TyCtxt<'tcx>,
962 def_id: DefId,
963 args: ty::GenericArgsRef<'tcx>,
964 ) -> Self {
965 Ty::new_coroutine(interner, def_id, args)
966 }
967
968 fn new_coroutine_closure(
969 interner: TyCtxt<'tcx>,
970 def_id: DefId,
971 args: ty::GenericArgsRef<'tcx>,
972 ) -> Self {
973 Ty::new_coroutine_closure(interner, def_id, args)
974 }
975
976 fn new_closure(interner: TyCtxt<'tcx>, def_id: DefId, args: ty::GenericArgsRef<'tcx>) -> Self {
977 Ty::new_closure(interner, def_id, args)
978 }
979
980 fn new_coroutine_witness(
981 interner: TyCtxt<'tcx>,
982 def_id: DefId,
983 args: ty::GenericArgsRef<'tcx>,
984 ) -> Self {
985 Ty::new_coroutine_witness(interner, def_id, args)
986 }
987
988 fn new_ptr(interner: TyCtxt<'tcx>, ty: Self, mutbl: hir::Mutability) -> Self {
989 Ty::new_ptr(interner, ty, mutbl)
990 }
991
992 fn new_ref(
993 interner: TyCtxt<'tcx>,
994 region: ty::Region<'tcx>,
995 ty: Self,
996 mutbl: hir::Mutability,
997 ) -> Self {
998 Ty::new_ref(interner, region, ty, mutbl)
999 }
1000
1001 fn new_array_with_const_len(interner: TyCtxt<'tcx>, ty: Self, len: ty::Const<'tcx>) -> Self {
1002 Ty::new_array_with_const_len(interner, ty, len)
1003 }
1004
1005 fn new_slice(interner: TyCtxt<'tcx>, ty: Self) -> Self {
1006 Ty::new_slice(interner, ty)
1007 }
1008
1009 fn new_tup(interner: TyCtxt<'tcx>, tys: &[Ty<'tcx>]) -> Self {
1010 Ty::new_tup(interner, tys)
1011 }
1012
1013 fn new_tup_from_iter<It, T>(interner: TyCtxt<'tcx>, iter: It) -> T::Output
1014 where
1015 It: Iterator<Item = T>,
1016 T: CollectAndApply<Self, Self>,
1017 {
1018 Ty::new_tup_from_iter(interner, iter)
1019 }
1020
1021 fn tuple_fields(self) -> &'tcx ty::List<Ty<'tcx>> {
1022 self.tuple_fields()
1023 }
1024
1025 fn to_opt_closure_kind(self) -> Option<ty::ClosureKind> {
1026 self.to_opt_closure_kind()
1027 }
1028
1029 fn from_closure_kind(interner: TyCtxt<'tcx>, kind: ty::ClosureKind) -> Self {
1030 Ty::from_closure_kind(interner, kind)
1031 }
1032
1033 fn from_coroutine_closure_kind(
1034 interner: TyCtxt<'tcx>,
1035 kind: rustc_type_ir::ClosureKind,
1036 ) -> Self {
1037 Ty::from_coroutine_closure_kind(interner, kind)
1038 }
1039
1040 fn new_fn_def(interner: TyCtxt<'tcx>, def_id: DefId, args: ty::GenericArgsRef<'tcx>) -> Self {
1041 Ty::new_fn_def(interner, def_id, args)
1042 }
1043
1044 fn new_fn_ptr(interner: TyCtxt<'tcx>, sig: ty::Binder<'tcx, ty::FnSig<'tcx>>) -> Self {
1045 Ty::new_fn_ptr(interner, sig)
1046 }
1047
1048 fn new_pat(interner: TyCtxt<'tcx>, ty: Self, pat: ty::Pattern<'tcx>) -> Self {
1049 Ty::new_pat(interner, ty, pat)
1050 }
1051
1052 fn new_unsafe_binder(interner: TyCtxt<'tcx>, ty: ty::Binder<'tcx, Ty<'tcx>>) -> Self {
1053 Ty::new_unsafe_binder(interner, ty)
1054 }
1055
1056 fn new_unit(interner: TyCtxt<'tcx>) -> Self {
1057 interner.types.unit
1058 }
1059
1060 fn new_usize(interner: TyCtxt<'tcx>) -> Self {
1061 interner.types.usize
1062 }
1063
1064 fn discriminant_ty(self, interner: TyCtxt<'tcx>) -> Ty<'tcx> {
1065 self.discriminant_ty(interner)
1066 }
1067
1068 fn has_unsafe_fields(self) -> bool {
1069 Ty::has_unsafe_fields(self)
1070 }
1071}
1072
1073impl<'tcx> Ty<'tcx> {
1075 #[inline(always)]
1080 pub fn kind(self) -> &'tcx TyKind<'tcx> {
1081 self.0.0
1082 }
1083
1084 #[inline(always)]
1086 pub fn flags(self) -> TypeFlags {
1087 self.0.0.flags
1088 }
1089
1090 #[inline]
1091 pub fn is_unit(self) -> bool {
1092 match self.kind() {
1093 Tuple(tys) => tys.is_empty(),
1094 _ => false,
1095 }
1096 }
1097
1098 #[inline]
1100 pub fn is_usize(self) -> bool {
1101 matches!(self.kind(), Uint(UintTy::Usize))
1102 }
1103
1104 #[inline]
1106 pub fn is_usize_like(self) -> bool {
1107 matches!(self.kind(), Uint(UintTy::Usize) | Infer(IntVar(_)))
1108 }
1109
1110 #[inline]
1111 pub fn is_never(self) -> bool {
1112 matches!(self.kind(), Never)
1113 }
1114
1115 #[inline]
1116 pub fn is_primitive(self) -> bool {
1117 matches!(self.kind(), Bool | Char | Int(_) | Uint(_) | Float(_))
1118 }
1119
1120 #[inline]
1121 pub fn is_adt(self) -> bool {
1122 matches!(self.kind(), Adt(..))
1123 }
1124
1125 #[inline]
1126 pub fn is_ref(self) -> bool {
1127 matches!(self.kind(), Ref(..))
1128 }
1129
1130 #[inline]
1131 pub fn is_ty_var(self) -> bool {
1132 matches!(self.kind(), Infer(TyVar(_)))
1133 }
1134
1135 #[inline]
1136 pub fn ty_vid(self) -> Option<ty::TyVid> {
1137 match self.kind() {
1138 &Infer(TyVar(vid)) => Some(vid),
1139 _ => None,
1140 }
1141 }
1142
1143 #[inline]
1144 pub fn is_ty_or_numeric_infer(self) -> bool {
1145 matches!(self.kind(), Infer(_))
1146 }
1147
1148 #[inline]
1149 pub fn is_phantom_data(self) -> bool {
1150 if let Adt(def, _) = self.kind() { def.is_phantom_data() } else { false }
1151 }
1152
1153 #[inline]
1154 pub fn is_bool(self) -> bool {
1155 *self.kind() == Bool
1156 }
1157
1158 #[inline]
1160 pub fn is_str(self) -> bool {
1161 *self.kind() == Str
1162 }
1163
1164 #[inline]
1165 pub fn is_param(self, index: u32) -> bool {
1166 match self.kind() {
1167 ty::Param(data) => data.index == index,
1168 _ => false,
1169 }
1170 }
1171
1172 #[inline]
1173 pub fn is_slice(self) -> bool {
1174 matches!(self.kind(), Slice(_))
1175 }
1176
1177 #[inline]
1178 pub fn is_array_slice(self) -> bool {
1179 match self.kind() {
1180 Slice(_) => true,
1181 ty::RawPtr(ty, _) | Ref(_, ty, _) => matches!(ty.kind(), Slice(_)),
1182 _ => false,
1183 }
1184 }
1185
1186 #[inline]
1187 pub fn is_array(self) -> bool {
1188 matches!(self.kind(), Array(..))
1189 }
1190
1191 #[inline]
1192 pub fn is_simd(self) -> bool {
1193 match self.kind() {
1194 Adt(def, _) => def.repr().simd(),
1195 _ => false,
1196 }
1197 }
1198
1199 pub fn sequence_element_type(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
1200 match self.kind() {
1201 Array(ty, _) | Slice(ty) => *ty,
1202 Str => tcx.types.u8,
1203 _ => bug!("`sequence_element_type` called on non-sequence value: {}", self),
1204 }
1205 }
1206
1207 pub fn simd_size_and_type(self, tcx: TyCtxt<'tcx>) -> (u64, Ty<'tcx>) {
1208 let Adt(def, args) = self.kind() else {
1209 bug!("`simd_size_and_type` called on invalid type")
1210 };
1211 assert!(def.repr().simd(), "`simd_size_and_type` called on non-SIMD type");
1212 let variant = def.non_enum_variant();
1213 assert_eq!(variant.fields.len(), 1);
1214 let field_ty = variant.fields[FieldIdx::ZERO].ty(tcx, args);
1215 let Array(f0_elem_ty, f0_len) = field_ty.kind() else {
1216 bug!("Simd type has non-array field type {field_ty:?}")
1217 };
1218 (
1223 f0_len
1224 .try_to_target_usize(tcx)
1225 .expect("expected SIMD field to have definite array size"),
1226 *f0_elem_ty,
1227 )
1228 }
1229
1230 #[inline]
1231 pub fn is_mutable_ptr(self) -> bool {
1232 matches!(self.kind(), RawPtr(_, hir::Mutability::Mut) | Ref(_, _, hir::Mutability::Mut))
1233 }
1234
1235 #[inline]
1237 pub fn ref_mutability(self) -> Option<hir::Mutability> {
1238 match self.kind() {
1239 Ref(_, _, mutability) => Some(*mutability),
1240 _ => None,
1241 }
1242 }
1243
1244 #[inline]
1245 pub fn is_raw_ptr(self) -> bool {
1246 matches!(self.kind(), RawPtr(_, _))
1247 }
1248
1249 #[inline]
1252 pub fn is_any_ptr(self) -> bool {
1253 self.is_ref() || self.is_raw_ptr() || self.is_fn_ptr()
1254 }
1255
1256 #[inline]
1257 pub fn is_box(self) -> bool {
1258 match self.kind() {
1259 Adt(def, _) => def.is_box(),
1260 _ => false,
1261 }
1262 }
1263
1264 #[inline]
1269 pub fn is_box_global(self, tcx: TyCtxt<'tcx>) -> bool {
1270 match self.kind() {
1271 Adt(def, args) if def.is_box() => {
1272 let Some(alloc) = args.get(1) else {
1273 return true;
1275 };
1276 alloc.expect_ty().ty_adt_def().is_some_and(|alloc_adt| {
1277 tcx.is_lang_item(alloc_adt.did(), LangItem::GlobalAlloc)
1278 })
1279 }
1280 _ => false,
1281 }
1282 }
1283
1284 pub fn boxed_ty(self) -> Option<Ty<'tcx>> {
1285 match self.kind() {
1286 Adt(def, args) if def.is_box() => Some(args.type_at(0)),
1287 _ => None,
1288 }
1289 }
1290
1291 pub fn expect_boxed_ty(self) -> Ty<'tcx> {
1293 self.boxed_ty()
1294 .unwrap_or_else(|| bug!("`expect_boxed_ty` is called on non-box type {:?}", self))
1295 }
1296
1297 #[inline]
1301 pub fn is_scalar(self) -> bool {
1302 matches!(
1303 self.kind(),
1304 Bool | Char
1305 | Int(_)
1306 | Float(_)
1307 | Uint(_)
1308 | FnDef(..)
1309 | FnPtr(..)
1310 | RawPtr(_, _)
1311 | Infer(IntVar(_) | FloatVar(_))
1312 )
1313 }
1314
1315 #[inline]
1317 pub fn is_floating_point(self) -> bool {
1318 matches!(self.kind(), Float(_) | Infer(FloatVar(_)))
1319 }
1320
1321 #[inline]
1322 pub fn is_trait(self) -> bool {
1323 matches!(self.kind(), Dynamic(_, _, ty::Dyn))
1324 }
1325
1326 #[inline]
1327 pub fn is_enum(self) -> bool {
1328 matches!(self.kind(), Adt(adt_def, _) if adt_def.is_enum())
1329 }
1330
1331 #[inline]
1332 pub fn is_union(self) -> bool {
1333 matches!(self.kind(), Adt(adt_def, _) if adt_def.is_union())
1334 }
1335
1336 #[inline]
1337 pub fn is_closure(self) -> bool {
1338 matches!(self.kind(), Closure(..))
1339 }
1340
1341 #[inline]
1342 pub fn is_coroutine(self) -> bool {
1343 matches!(self.kind(), Coroutine(..))
1344 }
1345
1346 #[inline]
1347 pub fn is_coroutine_closure(self) -> bool {
1348 matches!(self.kind(), CoroutineClosure(..))
1349 }
1350
1351 #[inline]
1352 pub fn is_integral(self) -> bool {
1353 matches!(self.kind(), Infer(IntVar(_)) | Int(_) | Uint(_))
1354 }
1355
1356 #[inline]
1357 pub fn is_fresh_ty(self) -> bool {
1358 matches!(self.kind(), Infer(FreshTy(_)))
1359 }
1360
1361 #[inline]
1362 pub fn is_fresh(self) -> bool {
1363 matches!(self.kind(), Infer(FreshTy(_) | FreshIntTy(_) | FreshFloatTy(_)))
1364 }
1365
1366 #[inline]
1367 pub fn is_char(self) -> bool {
1368 matches!(self.kind(), Char)
1369 }
1370
1371 #[inline]
1372 pub fn is_numeric(self) -> bool {
1373 self.is_integral() || self.is_floating_point()
1374 }
1375
1376 #[inline]
1377 pub fn is_signed(self) -> bool {
1378 matches!(self.kind(), Int(_))
1379 }
1380
1381 #[inline]
1382 pub fn is_ptr_sized_integral(self) -> bool {
1383 matches!(self.kind(), Int(ty::IntTy::Isize) | Uint(ty::UintTy::Usize))
1384 }
1385
1386 #[inline]
1387 pub fn has_concrete_skeleton(self) -> bool {
1388 !matches!(self.kind(), Param(_) | Infer(_) | Error(_))
1389 }
1390
1391 pub fn contains(self, other: Ty<'tcx>) -> bool {
1395 struct ContainsTyVisitor<'tcx>(Ty<'tcx>);
1396
1397 impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ContainsTyVisitor<'tcx> {
1398 type Result = ControlFlow<()>;
1399
1400 fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
1401 if self.0 == t { ControlFlow::Break(()) } else { t.super_visit_with(self) }
1402 }
1403 }
1404
1405 let cf = self.visit_with(&mut ContainsTyVisitor(other));
1406 cf.is_break()
1407 }
1408
1409 pub fn contains_closure(self) -> bool {
1413 struct ContainsClosureVisitor;
1414
1415 impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ContainsClosureVisitor {
1416 type Result = ControlFlow<()>;
1417
1418 fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
1419 if let ty::Closure(..) = t.kind() {
1420 ControlFlow::Break(())
1421 } else {
1422 t.super_visit_with(self)
1423 }
1424 }
1425 }
1426
1427 let cf = self.visit_with(&mut ContainsClosureVisitor);
1428 cf.is_break()
1429 }
1430
1431 pub fn find_async_drop_impl_coroutine<F: FnMut(Ty<'tcx>)>(
1436 self,
1437 tcx: TyCtxt<'tcx>,
1438 mut f: F,
1439 ) -> Ty<'tcx> {
1440 assert!(self.is_coroutine());
1441 let mut cor_ty = self;
1442 let mut ty = cor_ty;
1443 loop {
1444 if let ty::Coroutine(def_id, args) = ty.kind() {
1445 cor_ty = ty;
1446 f(ty);
1447 if tcx.is_async_drop_in_place_coroutine(*def_id) {
1448 ty = args.first().unwrap().expect_ty();
1449 continue;
1450 } else {
1451 return cor_ty;
1452 }
1453 } else {
1454 return cor_ty;
1455 }
1456 }
1457 }
1458
1459 pub fn builtin_deref(self, explicit: bool) -> Option<Ty<'tcx>> {
1464 match *self.kind() {
1465 _ if let Some(boxed) = self.boxed_ty() => Some(boxed),
1466 Ref(_, ty, _) => Some(ty),
1467 RawPtr(ty, _) if explicit => Some(ty),
1468 _ => None,
1469 }
1470 }
1471
1472 pub fn builtin_index(self) -> Option<Ty<'tcx>> {
1474 match self.kind() {
1475 Array(ty, _) | Slice(ty) => Some(*ty),
1476 _ => None,
1477 }
1478 }
1479
1480 #[tracing::instrument(level = "trace", skip(tcx))]
1481 pub fn fn_sig(self, tcx: TyCtxt<'tcx>) -> PolyFnSig<'tcx> {
1482 self.kind().fn_sig(tcx)
1483 }
1484
1485 #[inline]
1486 pub fn is_fn(self) -> bool {
1487 matches!(self.kind(), FnDef(..) | FnPtr(..))
1488 }
1489
1490 #[inline]
1491 pub fn is_fn_ptr(self) -> bool {
1492 matches!(self.kind(), FnPtr(..))
1493 }
1494
1495 #[inline]
1496 pub fn is_impl_trait(self) -> bool {
1497 matches!(self.kind(), Alias(ty::Opaque, ..))
1498 }
1499
1500 #[inline]
1501 pub fn ty_adt_def(self) -> Option<AdtDef<'tcx>> {
1502 match self.kind() {
1503 Adt(adt, _) => Some(*adt),
1504 _ => None,
1505 }
1506 }
1507
1508 #[inline]
1511 pub fn tuple_fields(self) -> &'tcx List<Ty<'tcx>> {
1512 match self.kind() {
1513 Tuple(args) => args,
1514 _ => bug!("tuple_fields called on non-tuple: {self:?}"),
1515 }
1516 }
1517
1518 #[inline]
1522 pub fn variant_range(self, tcx: TyCtxt<'tcx>) -> Option<Range<VariantIdx>> {
1523 match self.kind() {
1524 TyKind::Adt(adt, _) => Some(adt.variant_range()),
1525 TyKind::Coroutine(def_id, args) => {
1526 Some(args.as_coroutine().variant_range(*def_id, tcx))
1527 }
1528 _ => None,
1529 }
1530 }
1531
1532 #[inline]
1537 pub fn discriminant_for_variant(
1538 self,
1539 tcx: TyCtxt<'tcx>,
1540 variant_index: VariantIdx,
1541 ) -> Option<Discr<'tcx>> {
1542 match self.kind() {
1543 TyKind::Adt(adt, _) if adt.is_enum() => {
1544 Some(adt.discriminant_for_variant(tcx, variant_index))
1545 }
1546 TyKind::Coroutine(def_id, args) => {
1547 Some(args.as_coroutine().discriminant_for_variant(*def_id, tcx, variant_index))
1548 }
1549 _ => None,
1550 }
1551 }
1552
1553 pub fn discriminant_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
1555 match self.kind() {
1556 ty::Adt(adt, _) if adt.is_enum() => adt.repr().discr_type().to_ty(tcx),
1557 ty::Coroutine(_, args) => args.as_coroutine().discr_ty(tcx),
1558
1559 ty::Param(_) | ty::Alias(..) | ty::Infer(ty::TyVar(_)) => {
1560 let assoc_items = tcx.associated_item_def_ids(
1561 tcx.require_lang_item(hir::LangItem::DiscriminantKind, DUMMY_SP),
1562 );
1563 Ty::new_projection_from_args(tcx, assoc_items[0], tcx.mk_args(&[self.into()]))
1564 }
1565
1566 ty::Pat(ty, _) => ty.discriminant_ty(tcx),
1567
1568 ty::Bool
1569 | ty::Char
1570 | ty::Int(_)
1571 | ty::Uint(_)
1572 | ty::Float(_)
1573 | ty::Adt(..)
1574 | ty::Foreign(_)
1575 | ty::Str
1576 | ty::Array(..)
1577 | ty::Slice(_)
1578 | ty::RawPtr(_, _)
1579 | ty::Ref(..)
1580 | ty::FnDef(..)
1581 | ty::FnPtr(..)
1582 | ty::Dynamic(..)
1583 | ty::Closure(..)
1584 | ty::CoroutineClosure(..)
1585 | ty::CoroutineWitness(..)
1586 | ty::Never
1587 | ty::Tuple(_)
1588 | ty::UnsafeBinder(_)
1589 | ty::Error(_)
1590 | ty::Infer(IntVar(_) | FloatVar(_)) => tcx.types.u8,
1591
1592 ty::Bound(..)
1593 | ty::Placeholder(_)
1594 | ty::Infer(FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
1595 bug!("`discriminant_ty` applied to unexpected type: {:?}", self)
1596 }
1597 }
1598 }
1599
1600 pub fn ptr_metadata_ty_or_tail(
1603 self,
1604 tcx: TyCtxt<'tcx>,
1605 normalize: impl FnMut(Ty<'tcx>) -> Ty<'tcx>,
1606 ) -> Result<Ty<'tcx>, Ty<'tcx>> {
1607 let tail = tcx.struct_tail_raw(self, normalize, || {});
1608 match tail.kind() {
1609 ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
1611 | ty::Uint(_)
1612 | ty::Int(_)
1613 | ty::Bool
1614 | ty::Float(_)
1615 | ty::FnDef(..)
1616 | ty::FnPtr(..)
1617 | ty::RawPtr(..)
1618 | ty::Char
1619 | ty::Ref(..)
1620 | ty::Coroutine(..)
1621 | ty::CoroutineWitness(..)
1622 | ty::Array(..)
1623 | ty::Closure(..)
1624 | ty::CoroutineClosure(..)
1625 | ty::Never
1626 | ty::Error(_)
1627 | ty::Foreign(..)
1629 | ty::Adt(..)
1632 | ty::Tuple(..) => Ok(tcx.types.unit),
1635
1636 ty::Str | ty::Slice(_) => Ok(tcx.types.usize),
1637
1638 ty::Dynamic(_, _, ty::Dyn) => {
1639 let dyn_metadata = tcx.require_lang_item(LangItem::DynMetadata, DUMMY_SP);
1640 Ok(tcx.type_of(dyn_metadata).instantiate(tcx, &[tail.into()]))
1641 }
1642
1643 ty::Param(_) | ty::Alias(..) => Err(tail),
1646
1647 | ty::UnsafeBinder(_) => todo!("FIXME(unsafe_binder)"),
1648
1649 ty::Infer(ty::TyVar(_))
1650 | ty::Pat(..)
1651 | ty::Bound(..)
1652 | ty::Placeholder(..)
1653 | ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => bug!(
1654 "`ptr_metadata_ty_or_tail` applied to unexpected type: {self:?} (tail = {tail:?})"
1655 ),
1656 }
1657 }
1658
1659 pub fn ptr_metadata_ty(
1662 self,
1663 tcx: TyCtxt<'tcx>,
1664 normalize: impl FnMut(Ty<'tcx>) -> Ty<'tcx>,
1665 ) -> Ty<'tcx> {
1666 match self.ptr_metadata_ty_or_tail(tcx, normalize) {
1667 Ok(metadata) => metadata,
1668 Err(tail) => bug!(
1669 "`ptr_metadata_ty` failed to get metadata for type: {self:?} (tail = {tail:?})"
1670 ),
1671 }
1672 }
1673
1674 #[track_caller]
1683 pub fn pointee_metadata_ty_or_projection(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
1684 let Some(pointee_ty) = self.builtin_deref(true) else {
1685 bug!("Type {self:?} is not a pointer or reference type")
1686 };
1687 if pointee_ty.has_trivial_sizedness(tcx, SizedTraitKind::Sized) {
1688 tcx.types.unit
1689 } else {
1690 match pointee_ty.ptr_metadata_ty_or_tail(tcx, |x| x) {
1691 Ok(metadata_ty) => metadata_ty,
1692 Err(tail_ty) => {
1693 let metadata_def_id = tcx.require_lang_item(LangItem::Metadata, DUMMY_SP);
1694 Ty::new_projection(tcx, metadata_def_id, [tail_ty])
1695 }
1696 }
1697 }
1698 }
1699
1700 pub fn to_opt_closure_kind(self) -> Option<ty::ClosureKind> {
1740 match self.kind() {
1741 Int(int_ty) => match int_ty {
1742 ty::IntTy::I8 => Some(ty::ClosureKind::Fn),
1743 ty::IntTy::I16 => Some(ty::ClosureKind::FnMut),
1744 ty::IntTy::I32 => Some(ty::ClosureKind::FnOnce),
1745 _ => bug!("cannot convert type `{:?}` to a closure kind", self),
1746 },
1747
1748 Bound(..) | Placeholder(_) | Param(_) | Infer(_) => None,
1752
1753 Error(_) => Some(ty::ClosureKind::Fn),
1754
1755 _ => bug!("cannot convert type `{:?}` to a closure kind", self),
1756 }
1757 }
1758
1759 pub fn from_closure_kind(tcx: TyCtxt<'tcx>, kind: ty::ClosureKind) -> Ty<'tcx> {
1762 match kind {
1763 ty::ClosureKind::Fn => tcx.types.i8,
1764 ty::ClosureKind::FnMut => tcx.types.i16,
1765 ty::ClosureKind::FnOnce => tcx.types.i32,
1766 }
1767 }
1768
1769 pub fn from_coroutine_closure_kind(tcx: TyCtxt<'tcx>, kind: ty::ClosureKind) -> Ty<'tcx> {
1782 match kind {
1783 ty::ClosureKind::Fn | ty::ClosureKind::FnMut => tcx.types.i16,
1784 ty::ClosureKind::FnOnce => tcx.types.i32,
1785 }
1786 }
1787
1788 #[instrument(skip(tcx), level = "debug")]
1798 pub fn has_trivial_sizedness(self, tcx: TyCtxt<'tcx>, sizedness: SizedTraitKind) -> bool {
1799 match self.kind() {
1800 ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
1801 | ty::Uint(_)
1802 | ty::Int(_)
1803 | ty::Bool
1804 | ty::Float(_)
1805 | ty::FnDef(..)
1806 | ty::FnPtr(..)
1807 | ty::UnsafeBinder(_)
1808 | ty::RawPtr(..)
1809 | ty::Char
1810 | ty::Ref(..)
1811 | ty::Coroutine(..)
1812 | ty::CoroutineWitness(..)
1813 | ty::Array(..)
1814 | ty::Pat(..)
1815 | ty::Closure(..)
1816 | ty::CoroutineClosure(..)
1817 | ty::Never
1818 | ty::Error(_) => true,
1819
1820 ty::Str | ty::Slice(_) | ty::Dynamic(_, _, ty::Dyn) => match sizedness {
1821 SizedTraitKind::Sized => false,
1822 SizedTraitKind::MetaSized => true,
1823 },
1824
1825 ty::Foreign(..) => match sizedness {
1826 SizedTraitKind::Sized | SizedTraitKind::MetaSized => false,
1827 },
1828
1829 ty::Tuple(tys) => tys.last().is_none_or(|ty| ty.has_trivial_sizedness(tcx, sizedness)),
1830
1831 ty::Adt(def, args) => def
1832 .sizedness_constraint(tcx, sizedness)
1833 .is_none_or(|ty| ty.instantiate(tcx, args).has_trivial_sizedness(tcx, sizedness)),
1834
1835 ty::Alias(..) | ty::Param(_) | ty::Placeholder(..) | ty::Bound(..) => false,
1836
1837 ty::Infer(ty::TyVar(_)) => false,
1838
1839 ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
1840 bug!("`has_trivial_sizedness` applied to unexpected type: {:?}", self)
1841 }
1842 }
1843 }
1844
1845 pub fn is_trivially_pure_clone_copy(self) -> bool {
1854 match self.kind() {
1855 ty::Bool | ty::Char | ty::Never => true,
1856
1857 ty::Str | ty::Slice(..) | ty::Foreign(..) | ty::Dynamic(..) => false,
1859
1860 ty::Infer(ty::InferTy::FloatVar(_) | ty::InferTy::IntVar(_))
1861 | ty::Int(..)
1862 | ty::Uint(..)
1863 | ty::Float(..) => true,
1864
1865 ty::FnDef(..) => true,
1867
1868 ty::Array(element_ty, _len) => element_ty.is_trivially_pure_clone_copy(),
1869
1870 ty::Tuple(field_tys) => {
1872 field_tys.len() <= 3 && field_tys.iter().all(Self::is_trivially_pure_clone_copy)
1873 }
1874
1875 ty::Pat(ty, _) => ty.is_trivially_pure_clone_copy(),
1876
1877 ty::FnPtr(..) => false,
1880
1881 ty::Ref(_, _, hir::Mutability::Mut) => false,
1883
1884 ty::Ref(_, _, hir::Mutability::Not) | ty::RawPtr(..) => true,
1887
1888 ty::Coroutine(..) | ty::CoroutineWitness(..) => false,
1889
1890 ty::Adt(..) | ty::Closure(..) | ty::CoroutineClosure(..) => false,
1892
1893 ty::UnsafeBinder(_) => false,
1894
1895 ty::Alias(..) => false,
1897
1898 ty::Param(..) | ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error(..) => {
1899 false
1900 }
1901 }
1902 }
1903
1904 pub fn is_trivially_wf(self, tcx: TyCtxt<'tcx>) -> bool {
1905 match *self.kind() {
1906 ty::Bool
1907 | ty::Char
1908 | ty::Int(_)
1909 | ty::Uint(_)
1910 | ty::Float(_)
1911 | ty::Str
1912 | ty::Never
1913 | ty::Param(_)
1914 | ty::Placeholder(_)
1915 | ty::Bound(..) => true,
1916
1917 ty::Slice(ty) => {
1918 ty.is_trivially_wf(tcx) && ty.has_trivial_sizedness(tcx, SizedTraitKind::Sized)
1919 }
1920 ty::RawPtr(ty, _) => ty.is_trivially_wf(tcx),
1921
1922 ty::FnPtr(sig_tys, _) => {
1923 sig_tys.skip_binder().inputs_and_output.iter().all(|ty| ty.is_trivially_wf(tcx))
1924 }
1925 ty::Ref(_, ty, _) => ty.is_global() && ty.is_trivially_wf(tcx),
1926
1927 ty::Infer(infer) => match infer {
1928 ty::TyVar(_) => false,
1929 ty::IntVar(_) | ty::FloatVar(_) => true,
1930 ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => true,
1931 },
1932
1933 ty::Adt(_, _)
1934 | ty::Tuple(_)
1935 | ty::Array(..)
1936 | ty::Foreign(_)
1937 | ty::Pat(_, _)
1938 | ty::FnDef(..)
1939 | ty::UnsafeBinder(..)
1940 | ty::Dynamic(..)
1941 | ty::Closure(..)
1942 | ty::CoroutineClosure(..)
1943 | ty::Coroutine(..)
1944 | ty::CoroutineWitness(..)
1945 | ty::Alias(..)
1946 | ty::Error(_) => false,
1947 }
1948 }
1949
1950 pub fn primitive_symbol(self) -> Option<Symbol> {
1952 match self.kind() {
1953 ty::Bool => Some(sym::bool),
1954 ty::Char => Some(sym::char),
1955 ty::Float(f) => match f {
1956 ty::FloatTy::F16 => Some(sym::f16),
1957 ty::FloatTy::F32 => Some(sym::f32),
1958 ty::FloatTy::F64 => Some(sym::f64),
1959 ty::FloatTy::F128 => Some(sym::f128),
1960 },
1961 ty::Int(f) => match f {
1962 ty::IntTy::Isize => Some(sym::isize),
1963 ty::IntTy::I8 => Some(sym::i8),
1964 ty::IntTy::I16 => Some(sym::i16),
1965 ty::IntTy::I32 => Some(sym::i32),
1966 ty::IntTy::I64 => Some(sym::i64),
1967 ty::IntTy::I128 => Some(sym::i128),
1968 },
1969 ty::Uint(f) => match f {
1970 ty::UintTy::Usize => Some(sym::usize),
1971 ty::UintTy::U8 => Some(sym::u8),
1972 ty::UintTy::U16 => Some(sym::u16),
1973 ty::UintTy::U32 => Some(sym::u32),
1974 ty::UintTy::U64 => Some(sym::u64),
1975 ty::UintTy::U128 => Some(sym::u128),
1976 },
1977 ty::Str => Some(sym::str),
1978 _ => None,
1979 }
1980 }
1981
1982 pub fn is_c_void(self, tcx: TyCtxt<'_>) -> bool {
1983 match self.kind() {
1984 ty::Adt(adt, _) => tcx.is_lang_item(adt.did(), LangItem::CVoid),
1985 _ => false,
1986 }
1987 }
1988
1989 pub fn is_async_drop_in_place_coroutine(self, tcx: TyCtxt<'_>) -> bool {
1990 match self.kind() {
1991 ty::Coroutine(def, ..) => tcx.is_async_drop_in_place_coroutine(*def),
1992 _ => false,
1993 }
1994 }
1995
1996 pub fn is_known_rigid(self) -> bool {
2002 self.kind().is_known_rigid()
2003 }
2004
2005 pub fn walk(self) -> TypeWalker<TyCtxt<'tcx>> {
2016 TypeWalker::new(self.into())
2017 }
2018}
2019
2020impl<'tcx> rustc_type_ir::inherent::Tys<TyCtxt<'tcx>> for &'tcx ty::List<Ty<'tcx>> {
2021 fn inputs(self) -> &'tcx [Ty<'tcx>] {
2022 self.split_last().unwrap().1
2023 }
2024
2025 fn output(self) -> Ty<'tcx> {
2026 *self.split_last().unwrap().0
2027 }
2028}
2029
2030#[cfg(target_pointer_width = "64")]
2032mod size_asserts {
2033 use rustc_data_structures::static_assert_size;
2034
2035 use super::*;
2036 static_assert_size!(TyKind<'_>, 24);
2038 static_assert_size!(ty::WithCachedTypeInfo<TyKind<'_>>, 48);
2039 }