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 def_id: DefId,
825 args: GenericArgsRef<'tcx>,
826 ) -> Ty<'tcx> {
827 if cfg!(debug_assertions) {
828 tcx.debug_assert_args_compatible(tcx.typeck_root_def_id(def_id), args);
829 }
830 Ty::new(tcx, CoroutineWitness(def_id, args))
831 }
832
833 pub fn new_coroutine_witness_for_coroutine(
834 tcx: TyCtxt<'tcx>,
835 def_id: DefId,
836 coroutine_args: GenericArgsRef<'tcx>,
837 ) -> Ty<'tcx> {
838 tcx.debug_assert_args_compatible(def_id, coroutine_args);
839 let args =
848 ty::GenericArgs::for_item(tcx, tcx.typeck_root_def_id(def_id), |def, _| {
849 match def.kind {
850 ty::GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
851 ty::GenericParamDefKind::Type { .. }
852 | ty::GenericParamDefKind::Const { .. } => coroutine_args[def.index as usize],
853 }
854 });
855 Ty::new_coroutine_witness(tcx, def_id, args)
856 }
857
858 #[inline]
861 pub fn new_static_str(tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
862 Ty::new_imm_ref(tcx, tcx.lifetimes.re_static, tcx.types.str_)
863 }
864
865 #[inline]
866 pub fn new_diverging_default(tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
867 if tcx.features().never_type_fallback() { tcx.types.never } else { tcx.types.unit }
868 }
869
870 fn new_generic_adt(tcx: TyCtxt<'tcx>, wrapper_def_id: DefId, ty_param: Ty<'tcx>) -> Ty<'tcx> {
873 let adt_def = tcx.adt_def(wrapper_def_id);
874 let args = GenericArgs::for_item(tcx, wrapper_def_id, |param, args| match param.kind {
875 GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => bug!(),
876 GenericParamDefKind::Type { has_default, .. } => {
877 if param.index == 0 {
878 ty_param.into()
879 } else {
880 assert!(has_default);
881 tcx.type_of(param.def_id).instantiate(tcx, args).into()
882 }
883 }
884 });
885 Ty::new_adt(tcx, adt_def, args)
886 }
887
888 #[inline]
889 pub fn new_lang_item(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, item: LangItem) -> Option<Ty<'tcx>> {
890 let def_id = tcx.lang_items().get(item)?;
891 Some(Ty::new_generic_adt(tcx, def_id, ty))
892 }
893
894 #[inline]
895 pub fn new_diagnostic_item(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, name: Symbol) -> Option<Ty<'tcx>> {
896 let def_id = tcx.get_diagnostic_item(name)?;
897 Some(Ty::new_generic_adt(tcx, def_id, ty))
898 }
899
900 #[inline]
901 pub fn new_box(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
902 let def_id = tcx.require_lang_item(LangItem::OwnedBox, DUMMY_SP);
903 Ty::new_generic_adt(tcx, def_id, ty)
904 }
905
906 #[inline]
907 pub fn new_maybe_uninit(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
908 let def_id = tcx.require_lang_item(LangItem::MaybeUninit, DUMMY_SP);
909 Ty::new_generic_adt(tcx, def_id, ty)
910 }
911
912 pub fn new_task_context(tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
914 let context_did = tcx.require_lang_item(LangItem::Context, DUMMY_SP);
915 let context_adt_ref = tcx.adt_def(context_did);
916 let context_args = tcx.mk_args(&[tcx.lifetimes.re_erased.into()]);
917 let context_ty = Ty::new_adt(tcx, context_adt_ref, context_args);
918 Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, context_ty)
919 }
920}
921
922impl<'tcx> rustc_type_ir::inherent::Ty<TyCtxt<'tcx>> for Ty<'tcx> {
923 fn new_bool(tcx: TyCtxt<'tcx>) -> Self {
924 tcx.types.bool
925 }
926
927 fn new_u8(tcx: TyCtxt<'tcx>) -> Self {
928 tcx.types.u8
929 }
930
931 fn new_infer(tcx: TyCtxt<'tcx>, infer: ty::InferTy) -> Self {
932 Ty::new_infer(tcx, infer)
933 }
934
935 fn new_var(tcx: TyCtxt<'tcx>, vid: ty::TyVid) -> Self {
936 Ty::new_var(tcx, vid)
937 }
938
939 fn new_param(tcx: TyCtxt<'tcx>, param: ty::ParamTy) -> Self {
940 Ty::new_param(tcx, param.index, param.name)
941 }
942
943 fn new_placeholder(tcx: TyCtxt<'tcx>, placeholder: ty::PlaceholderType) -> Self {
944 Ty::new_placeholder(tcx, placeholder)
945 }
946
947 fn new_bound(interner: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundTy) -> Self {
948 Ty::new_bound(interner, debruijn, var)
949 }
950
951 fn new_anon_bound(tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self {
952 Ty::new_bound(tcx, debruijn, ty::BoundTy { var, kind: ty::BoundTyKind::Anon })
953 }
954
955 fn new_alias(
956 interner: TyCtxt<'tcx>,
957 kind: ty::AliasTyKind,
958 alias_ty: ty::AliasTy<'tcx>,
959 ) -> Self {
960 Ty::new_alias(interner, kind, alias_ty)
961 }
962
963 fn new_error(interner: TyCtxt<'tcx>, guar: ErrorGuaranteed) -> Self {
964 Ty::new_error(interner, guar)
965 }
966
967 fn new_adt(
968 interner: TyCtxt<'tcx>,
969 adt_def: ty::AdtDef<'tcx>,
970 args: ty::GenericArgsRef<'tcx>,
971 ) -> Self {
972 Ty::new_adt(interner, adt_def, args)
973 }
974
975 fn new_foreign(interner: TyCtxt<'tcx>, def_id: DefId) -> Self {
976 Ty::new_foreign(interner, def_id)
977 }
978
979 fn new_dynamic(
980 interner: TyCtxt<'tcx>,
981 preds: &'tcx List<ty::PolyExistentialPredicate<'tcx>>,
982 region: ty::Region<'tcx>,
983 kind: ty::DynKind,
984 ) -> Self {
985 Ty::new_dynamic(interner, preds, region, kind)
986 }
987
988 fn new_coroutine(
989 interner: TyCtxt<'tcx>,
990 def_id: DefId,
991 args: ty::GenericArgsRef<'tcx>,
992 ) -> Self {
993 Ty::new_coroutine(interner, def_id, args)
994 }
995
996 fn new_coroutine_closure(
997 interner: TyCtxt<'tcx>,
998 def_id: DefId,
999 args: ty::GenericArgsRef<'tcx>,
1000 ) -> Self {
1001 Ty::new_coroutine_closure(interner, def_id, args)
1002 }
1003
1004 fn new_closure(interner: TyCtxt<'tcx>, def_id: DefId, args: ty::GenericArgsRef<'tcx>) -> Self {
1005 Ty::new_closure(interner, def_id, args)
1006 }
1007
1008 fn new_coroutine_witness(
1009 interner: TyCtxt<'tcx>,
1010 def_id: DefId,
1011 args: ty::GenericArgsRef<'tcx>,
1012 ) -> Self {
1013 Ty::new_coroutine_witness(interner, def_id, args)
1014 }
1015
1016 fn new_coroutine_witness_for_coroutine(
1017 interner: TyCtxt<'tcx>,
1018 def_id: DefId,
1019 coroutine_args: ty::GenericArgsRef<'tcx>,
1020 ) -> Self {
1021 Ty::new_coroutine_witness_for_coroutine(interner, def_id, coroutine_args)
1022 }
1023
1024 fn new_ptr(interner: TyCtxt<'tcx>, ty: Self, mutbl: hir::Mutability) -> Self {
1025 Ty::new_ptr(interner, ty, mutbl)
1026 }
1027
1028 fn new_ref(
1029 interner: TyCtxt<'tcx>,
1030 region: ty::Region<'tcx>,
1031 ty: Self,
1032 mutbl: hir::Mutability,
1033 ) -> Self {
1034 Ty::new_ref(interner, region, ty, mutbl)
1035 }
1036
1037 fn new_array_with_const_len(interner: TyCtxt<'tcx>, ty: Self, len: ty::Const<'tcx>) -> Self {
1038 Ty::new_array_with_const_len(interner, ty, len)
1039 }
1040
1041 fn new_slice(interner: TyCtxt<'tcx>, ty: Self) -> Self {
1042 Ty::new_slice(interner, ty)
1043 }
1044
1045 fn new_tup(interner: TyCtxt<'tcx>, tys: &[Ty<'tcx>]) -> Self {
1046 Ty::new_tup(interner, tys)
1047 }
1048
1049 fn new_tup_from_iter<It, T>(interner: TyCtxt<'tcx>, iter: It) -> T::Output
1050 where
1051 It: Iterator<Item = T>,
1052 T: CollectAndApply<Self, Self>,
1053 {
1054 Ty::new_tup_from_iter(interner, iter)
1055 }
1056
1057 fn tuple_fields(self) -> &'tcx ty::List<Ty<'tcx>> {
1058 self.tuple_fields()
1059 }
1060
1061 fn to_opt_closure_kind(self) -> Option<ty::ClosureKind> {
1062 self.to_opt_closure_kind()
1063 }
1064
1065 fn from_closure_kind(interner: TyCtxt<'tcx>, kind: ty::ClosureKind) -> Self {
1066 Ty::from_closure_kind(interner, kind)
1067 }
1068
1069 fn from_coroutine_closure_kind(
1070 interner: TyCtxt<'tcx>,
1071 kind: rustc_type_ir::ClosureKind,
1072 ) -> Self {
1073 Ty::from_coroutine_closure_kind(interner, kind)
1074 }
1075
1076 fn new_fn_def(interner: TyCtxt<'tcx>, def_id: DefId, args: ty::GenericArgsRef<'tcx>) -> Self {
1077 Ty::new_fn_def(interner, def_id, args)
1078 }
1079
1080 fn new_fn_ptr(interner: TyCtxt<'tcx>, sig: ty::Binder<'tcx, ty::FnSig<'tcx>>) -> Self {
1081 Ty::new_fn_ptr(interner, sig)
1082 }
1083
1084 fn new_pat(interner: TyCtxt<'tcx>, ty: Self, pat: ty::Pattern<'tcx>) -> Self {
1085 Ty::new_pat(interner, ty, pat)
1086 }
1087
1088 fn new_unsafe_binder(interner: TyCtxt<'tcx>, ty: ty::Binder<'tcx, Ty<'tcx>>) -> Self {
1089 Ty::new_unsafe_binder(interner, ty)
1090 }
1091
1092 fn new_unit(interner: TyCtxt<'tcx>) -> Self {
1093 interner.types.unit
1094 }
1095
1096 fn new_usize(interner: TyCtxt<'tcx>) -> Self {
1097 interner.types.usize
1098 }
1099
1100 fn discriminant_ty(self, interner: TyCtxt<'tcx>) -> Ty<'tcx> {
1101 self.discriminant_ty(interner)
1102 }
1103
1104 fn has_unsafe_fields(self) -> bool {
1105 Ty::has_unsafe_fields(self)
1106 }
1107}
1108
1109impl<'tcx> Ty<'tcx> {
1111 #[inline(always)]
1116 pub fn kind(self) -> &'tcx TyKind<'tcx> {
1117 self.0.0
1118 }
1119
1120 #[inline(always)]
1122 pub fn flags(self) -> TypeFlags {
1123 self.0.0.flags
1124 }
1125
1126 #[inline]
1127 pub fn is_unit(self) -> bool {
1128 match self.kind() {
1129 Tuple(tys) => tys.is_empty(),
1130 _ => false,
1131 }
1132 }
1133
1134 #[inline]
1136 pub fn is_usize(self) -> bool {
1137 matches!(self.kind(), Uint(UintTy::Usize))
1138 }
1139
1140 #[inline]
1142 pub fn is_usize_like(self) -> bool {
1143 matches!(self.kind(), Uint(UintTy::Usize) | Infer(IntVar(_)))
1144 }
1145
1146 #[inline]
1147 pub fn is_never(self) -> bool {
1148 matches!(self.kind(), Never)
1149 }
1150
1151 #[inline]
1152 pub fn is_primitive(self) -> bool {
1153 matches!(self.kind(), Bool | Char | Int(_) | Uint(_) | Float(_))
1154 }
1155
1156 #[inline]
1157 pub fn is_adt(self) -> bool {
1158 matches!(self.kind(), Adt(..))
1159 }
1160
1161 #[inline]
1162 pub fn is_ref(self) -> bool {
1163 matches!(self.kind(), Ref(..))
1164 }
1165
1166 #[inline]
1167 pub fn is_ty_var(self) -> bool {
1168 matches!(self.kind(), Infer(TyVar(_)))
1169 }
1170
1171 #[inline]
1172 pub fn ty_vid(self) -> Option<ty::TyVid> {
1173 match self.kind() {
1174 &Infer(TyVar(vid)) => Some(vid),
1175 _ => None,
1176 }
1177 }
1178
1179 #[inline]
1180 pub fn is_ty_or_numeric_infer(self) -> bool {
1181 matches!(self.kind(), Infer(_))
1182 }
1183
1184 #[inline]
1185 pub fn is_phantom_data(self) -> bool {
1186 if let Adt(def, _) = self.kind() { def.is_phantom_data() } else { false }
1187 }
1188
1189 #[inline]
1190 pub fn is_bool(self) -> bool {
1191 *self.kind() == Bool
1192 }
1193
1194 #[inline]
1196 pub fn is_str(self) -> bool {
1197 *self.kind() == Str
1198 }
1199
1200 #[inline]
1201 pub fn is_param(self, index: u32) -> bool {
1202 match self.kind() {
1203 ty::Param(data) => data.index == index,
1204 _ => false,
1205 }
1206 }
1207
1208 #[inline]
1209 pub fn is_slice(self) -> bool {
1210 matches!(self.kind(), Slice(_))
1211 }
1212
1213 #[inline]
1214 pub fn is_array_slice(self) -> bool {
1215 match self.kind() {
1216 Slice(_) => true,
1217 ty::RawPtr(ty, _) | Ref(_, ty, _) => matches!(ty.kind(), Slice(_)),
1218 _ => false,
1219 }
1220 }
1221
1222 #[inline]
1223 pub fn is_array(self) -> bool {
1224 matches!(self.kind(), Array(..))
1225 }
1226
1227 #[inline]
1228 pub fn is_simd(self) -> bool {
1229 match self.kind() {
1230 Adt(def, _) => def.repr().simd(),
1231 _ => false,
1232 }
1233 }
1234
1235 pub fn sequence_element_type(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
1236 match self.kind() {
1237 Array(ty, _) | Slice(ty) => *ty,
1238 Str => tcx.types.u8,
1239 _ => bug!("`sequence_element_type` called on non-sequence value: {}", self),
1240 }
1241 }
1242
1243 pub fn simd_size_and_type(self, tcx: TyCtxt<'tcx>) -> (u64, Ty<'tcx>) {
1244 let Adt(def, args) = self.kind() else {
1245 bug!("`simd_size_and_type` called on invalid type")
1246 };
1247 assert!(def.repr().simd(), "`simd_size_and_type` called on non-SIMD type");
1248 let variant = def.non_enum_variant();
1249 assert_eq!(variant.fields.len(), 1);
1250 let field_ty = variant.fields[FieldIdx::ZERO].ty(tcx, args);
1251 let Array(f0_elem_ty, f0_len) = field_ty.kind() else {
1252 bug!("Simd type has non-array field type {field_ty:?}")
1253 };
1254 (
1259 f0_len
1260 .try_to_target_usize(tcx)
1261 .expect("expected SIMD field to have definite array size"),
1262 *f0_elem_ty,
1263 )
1264 }
1265
1266 #[inline]
1267 pub fn is_mutable_ptr(self) -> bool {
1268 matches!(self.kind(), RawPtr(_, hir::Mutability::Mut) | Ref(_, _, hir::Mutability::Mut))
1269 }
1270
1271 #[inline]
1273 pub fn ref_mutability(self) -> Option<hir::Mutability> {
1274 match self.kind() {
1275 Ref(_, _, mutability) => Some(*mutability),
1276 _ => None,
1277 }
1278 }
1279
1280 #[inline]
1281 pub fn is_raw_ptr(self) -> bool {
1282 matches!(self.kind(), RawPtr(_, _))
1283 }
1284
1285 #[inline]
1288 pub fn is_any_ptr(self) -> bool {
1289 self.is_ref() || self.is_raw_ptr() || self.is_fn_ptr()
1290 }
1291
1292 #[inline]
1293 pub fn is_box(self) -> bool {
1294 match self.kind() {
1295 Adt(def, _) => def.is_box(),
1296 _ => false,
1297 }
1298 }
1299
1300 #[inline]
1305 pub fn is_box_global(self, tcx: TyCtxt<'tcx>) -> bool {
1306 match self.kind() {
1307 Adt(def, args) if def.is_box() => {
1308 let Some(alloc) = args.get(1) else {
1309 return true;
1311 };
1312 alloc.expect_ty().ty_adt_def().is_some_and(|alloc_adt| {
1313 tcx.is_lang_item(alloc_adt.did(), LangItem::GlobalAlloc)
1314 })
1315 }
1316 _ => false,
1317 }
1318 }
1319
1320 pub fn boxed_ty(self) -> Option<Ty<'tcx>> {
1321 match self.kind() {
1322 Adt(def, args) if def.is_box() => Some(args.type_at(0)),
1323 _ => None,
1324 }
1325 }
1326
1327 pub fn expect_boxed_ty(self) -> Ty<'tcx> {
1329 self.boxed_ty()
1330 .unwrap_or_else(|| bug!("`expect_boxed_ty` is called on non-box type {:?}", self))
1331 }
1332
1333 #[inline]
1337 pub fn is_scalar(self) -> bool {
1338 matches!(
1339 self.kind(),
1340 Bool | Char
1341 | Int(_)
1342 | Float(_)
1343 | Uint(_)
1344 | FnDef(..)
1345 | FnPtr(..)
1346 | RawPtr(_, _)
1347 | Infer(IntVar(_) | FloatVar(_))
1348 )
1349 }
1350
1351 #[inline]
1353 pub fn is_floating_point(self) -> bool {
1354 matches!(self.kind(), Float(_) | Infer(FloatVar(_)))
1355 }
1356
1357 #[inline]
1358 pub fn is_trait(self) -> bool {
1359 matches!(self.kind(), Dynamic(_, _, ty::Dyn))
1360 }
1361
1362 #[inline]
1363 pub fn is_enum(self) -> bool {
1364 matches!(self.kind(), Adt(adt_def, _) if adt_def.is_enum())
1365 }
1366
1367 #[inline]
1368 pub fn is_union(self) -> bool {
1369 matches!(self.kind(), Adt(adt_def, _) if adt_def.is_union())
1370 }
1371
1372 #[inline]
1373 pub fn is_closure(self) -> bool {
1374 matches!(self.kind(), Closure(..))
1375 }
1376
1377 #[inline]
1378 pub fn is_coroutine(self) -> bool {
1379 matches!(self.kind(), Coroutine(..))
1380 }
1381
1382 #[inline]
1383 pub fn is_coroutine_closure(self) -> bool {
1384 matches!(self.kind(), CoroutineClosure(..))
1385 }
1386
1387 #[inline]
1388 pub fn is_integral(self) -> bool {
1389 matches!(self.kind(), Infer(IntVar(_)) | Int(_) | Uint(_))
1390 }
1391
1392 #[inline]
1393 pub fn is_fresh_ty(self) -> bool {
1394 matches!(self.kind(), Infer(FreshTy(_)))
1395 }
1396
1397 #[inline]
1398 pub fn is_fresh(self) -> bool {
1399 matches!(self.kind(), Infer(FreshTy(_) | FreshIntTy(_) | FreshFloatTy(_)))
1400 }
1401
1402 #[inline]
1403 pub fn is_char(self) -> bool {
1404 matches!(self.kind(), Char)
1405 }
1406
1407 #[inline]
1408 pub fn is_numeric(self) -> bool {
1409 self.is_integral() || self.is_floating_point()
1410 }
1411
1412 #[inline]
1413 pub fn is_signed(self) -> bool {
1414 matches!(self.kind(), Int(_))
1415 }
1416
1417 #[inline]
1418 pub fn is_ptr_sized_integral(self) -> bool {
1419 matches!(self.kind(), Int(ty::IntTy::Isize) | Uint(ty::UintTy::Usize))
1420 }
1421
1422 #[inline]
1423 pub fn has_concrete_skeleton(self) -> bool {
1424 !matches!(self.kind(), Param(_) | Infer(_) | Error(_))
1425 }
1426
1427 pub fn contains(self, other: Ty<'tcx>) -> bool {
1431 struct ContainsTyVisitor<'tcx>(Ty<'tcx>);
1432
1433 impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ContainsTyVisitor<'tcx> {
1434 type Result = ControlFlow<()>;
1435
1436 fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
1437 if self.0 == t { ControlFlow::Break(()) } else { t.super_visit_with(self) }
1438 }
1439 }
1440
1441 let cf = self.visit_with(&mut ContainsTyVisitor(other));
1442 cf.is_break()
1443 }
1444
1445 pub fn contains_closure(self) -> bool {
1449 struct ContainsClosureVisitor;
1450
1451 impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ContainsClosureVisitor {
1452 type Result = ControlFlow<()>;
1453
1454 fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
1455 if let ty::Closure(..) = t.kind() {
1456 ControlFlow::Break(())
1457 } else {
1458 t.super_visit_with(self)
1459 }
1460 }
1461 }
1462
1463 let cf = self.visit_with(&mut ContainsClosureVisitor);
1464 cf.is_break()
1465 }
1466
1467 pub fn find_async_drop_impl_coroutine<F: FnMut(Ty<'tcx>)>(
1472 self,
1473 tcx: TyCtxt<'tcx>,
1474 mut f: F,
1475 ) -> Ty<'tcx> {
1476 assert!(self.is_coroutine());
1477 let mut cor_ty = self;
1478 let mut ty = cor_ty;
1479 loop {
1480 if let ty::Coroutine(def_id, args) = ty.kind() {
1481 cor_ty = ty;
1482 f(ty);
1483 if tcx.is_async_drop_in_place_coroutine(*def_id) {
1484 ty = args.first().unwrap().expect_ty();
1485 continue;
1486 } else {
1487 return cor_ty;
1488 }
1489 } else {
1490 return cor_ty;
1491 }
1492 }
1493 }
1494
1495 pub fn builtin_deref(self, explicit: bool) -> Option<Ty<'tcx>> {
1500 match *self.kind() {
1501 _ if let Some(boxed) = self.boxed_ty() => Some(boxed),
1502 Ref(_, ty, _) => Some(ty),
1503 RawPtr(ty, _) if explicit => Some(ty),
1504 _ => None,
1505 }
1506 }
1507
1508 pub fn builtin_index(self) -> Option<Ty<'tcx>> {
1510 match self.kind() {
1511 Array(ty, _) | Slice(ty) => Some(*ty),
1512 _ => None,
1513 }
1514 }
1515
1516 #[tracing::instrument(level = "trace", skip(tcx))]
1517 pub fn fn_sig(self, tcx: TyCtxt<'tcx>) -> PolyFnSig<'tcx> {
1518 self.kind().fn_sig(tcx)
1519 }
1520
1521 #[inline]
1522 pub fn is_fn(self) -> bool {
1523 matches!(self.kind(), FnDef(..) | FnPtr(..))
1524 }
1525
1526 #[inline]
1527 pub fn is_fn_ptr(self) -> bool {
1528 matches!(self.kind(), FnPtr(..))
1529 }
1530
1531 #[inline]
1532 pub fn is_impl_trait(self) -> bool {
1533 matches!(self.kind(), Alias(ty::Opaque, ..))
1534 }
1535
1536 #[inline]
1537 pub fn ty_adt_def(self) -> Option<AdtDef<'tcx>> {
1538 match self.kind() {
1539 Adt(adt, _) => Some(*adt),
1540 _ => None,
1541 }
1542 }
1543
1544 #[inline]
1547 pub fn tuple_fields(self) -> &'tcx List<Ty<'tcx>> {
1548 match self.kind() {
1549 Tuple(args) => args,
1550 _ => bug!("tuple_fields called on non-tuple: {self:?}"),
1551 }
1552 }
1553
1554 #[inline]
1558 pub fn variant_range(self, tcx: TyCtxt<'tcx>) -> Option<Range<VariantIdx>> {
1559 match self.kind() {
1560 TyKind::Adt(adt, _) => Some(adt.variant_range()),
1561 TyKind::Coroutine(def_id, args) => {
1562 Some(args.as_coroutine().variant_range(*def_id, tcx))
1563 }
1564 _ => None,
1565 }
1566 }
1567
1568 #[inline]
1573 pub fn discriminant_for_variant(
1574 self,
1575 tcx: TyCtxt<'tcx>,
1576 variant_index: VariantIdx,
1577 ) -> Option<Discr<'tcx>> {
1578 match self.kind() {
1579 TyKind::Adt(adt, _) if adt.is_enum() => {
1580 Some(adt.discriminant_for_variant(tcx, variant_index))
1581 }
1582 TyKind::Coroutine(def_id, args) => {
1583 Some(args.as_coroutine().discriminant_for_variant(*def_id, tcx, variant_index))
1584 }
1585 _ => None,
1586 }
1587 }
1588
1589 pub fn discriminant_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
1591 match self.kind() {
1592 ty::Adt(adt, _) if adt.is_enum() => adt.repr().discr_type().to_ty(tcx),
1593 ty::Coroutine(_, args) => args.as_coroutine().discr_ty(tcx),
1594
1595 ty::Param(_) | ty::Alias(..) | ty::Infer(ty::TyVar(_)) => {
1596 let assoc_items = tcx.associated_item_def_ids(
1597 tcx.require_lang_item(hir::LangItem::DiscriminantKind, DUMMY_SP),
1598 );
1599 Ty::new_projection_from_args(tcx, assoc_items[0], tcx.mk_args(&[self.into()]))
1600 }
1601
1602 ty::Pat(ty, _) => ty.discriminant_ty(tcx),
1603
1604 ty::Bool
1605 | ty::Char
1606 | ty::Int(_)
1607 | ty::Uint(_)
1608 | ty::Float(_)
1609 | ty::Adt(..)
1610 | ty::Foreign(_)
1611 | ty::Str
1612 | ty::Array(..)
1613 | ty::Slice(_)
1614 | ty::RawPtr(_, _)
1615 | ty::Ref(..)
1616 | ty::FnDef(..)
1617 | ty::FnPtr(..)
1618 | ty::Dynamic(..)
1619 | ty::Closure(..)
1620 | ty::CoroutineClosure(..)
1621 | ty::CoroutineWitness(..)
1622 | ty::Never
1623 | ty::Tuple(_)
1624 | ty::UnsafeBinder(_)
1625 | ty::Error(_)
1626 | ty::Infer(IntVar(_) | FloatVar(_)) => tcx.types.u8,
1627
1628 ty::Bound(..)
1629 | ty::Placeholder(_)
1630 | ty::Infer(FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
1631 bug!("`discriminant_ty` applied to unexpected type: {:?}", self)
1632 }
1633 }
1634 }
1635
1636 pub fn ptr_metadata_ty_or_tail(
1639 self,
1640 tcx: TyCtxt<'tcx>,
1641 normalize: impl FnMut(Ty<'tcx>) -> Ty<'tcx>,
1642 ) -> Result<Ty<'tcx>, Ty<'tcx>> {
1643 let tail = tcx.struct_tail_raw(self, normalize, || {});
1644 match tail.kind() {
1645 ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
1647 | ty::Uint(_)
1648 | ty::Int(_)
1649 | ty::Bool
1650 | ty::Float(_)
1651 | ty::FnDef(..)
1652 | ty::FnPtr(..)
1653 | ty::RawPtr(..)
1654 | ty::Char
1655 | ty::Ref(..)
1656 | ty::Coroutine(..)
1657 | ty::CoroutineWitness(..)
1658 | ty::Array(..)
1659 | ty::Closure(..)
1660 | ty::CoroutineClosure(..)
1661 | ty::Never
1662 | ty::Error(_)
1663 | ty::Foreign(..)
1665 | ty::Adt(..)
1668 | ty::Tuple(..) => Ok(tcx.types.unit),
1671
1672 ty::Str | ty::Slice(_) => Ok(tcx.types.usize),
1673
1674 ty::Dynamic(_, _, ty::Dyn) => {
1675 let dyn_metadata = tcx.require_lang_item(LangItem::DynMetadata, DUMMY_SP);
1676 Ok(tcx.type_of(dyn_metadata).instantiate(tcx, &[tail.into()]))
1677 }
1678
1679 ty::Param(_) | ty::Alias(..) => Err(tail),
1682
1683 | ty::UnsafeBinder(_) => todo!("FIXME(unsafe_binder)"),
1684
1685 ty::Infer(ty::TyVar(_))
1686 | ty::Pat(..)
1687 | ty::Bound(..)
1688 | ty::Placeholder(..)
1689 | ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => bug!(
1690 "`ptr_metadata_ty_or_tail` applied to unexpected type: {self:?} (tail = {tail:?})"
1691 ),
1692 }
1693 }
1694
1695 pub fn ptr_metadata_ty(
1698 self,
1699 tcx: TyCtxt<'tcx>,
1700 normalize: impl FnMut(Ty<'tcx>) -> Ty<'tcx>,
1701 ) -> Ty<'tcx> {
1702 match self.ptr_metadata_ty_or_tail(tcx, normalize) {
1703 Ok(metadata) => metadata,
1704 Err(tail) => bug!(
1705 "`ptr_metadata_ty` failed to get metadata for type: {self:?} (tail = {tail:?})"
1706 ),
1707 }
1708 }
1709
1710 #[track_caller]
1719 pub fn pointee_metadata_ty_or_projection(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
1720 let Some(pointee_ty) = self.builtin_deref(true) else {
1721 bug!("Type {self:?} is not a pointer or reference type")
1722 };
1723 if pointee_ty.has_trivial_sizedness(tcx, SizedTraitKind::Sized) {
1724 tcx.types.unit
1725 } else {
1726 match pointee_ty.ptr_metadata_ty_or_tail(tcx, |x| x) {
1727 Ok(metadata_ty) => metadata_ty,
1728 Err(tail_ty) => {
1729 let metadata_def_id = tcx.require_lang_item(LangItem::Metadata, DUMMY_SP);
1730 Ty::new_projection(tcx, metadata_def_id, [tail_ty])
1731 }
1732 }
1733 }
1734 }
1735
1736 pub fn to_opt_closure_kind(self) -> Option<ty::ClosureKind> {
1776 match self.kind() {
1777 Int(int_ty) => match int_ty {
1778 ty::IntTy::I8 => Some(ty::ClosureKind::Fn),
1779 ty::IntTy::I16 => Some(ty::ClosureKind::FnMut),
1780 ty::IntTy::I32 => Some(ty::ClosureKind::FnOnce),
1781 _ => bug!("cannot convert type `{:?}` to a closure kind", self),
1782 },
1783
1784 Bound(..) | Placeholder(_) | Param(_) | Infer(_) => None,
1788
1789 Error(_) => Some(ty::ClosureKind::Fn),
1790
1791 _ => bug!("cannot convert type `{:?}` to a closure kind", self),
1792 }
1793 }
1794
1795 pub fn from_closure_kind(tcx: TyCtxt<'tcx>, kind: ty::ClosureKind) -> Ty<'tcx> {
1798 match kind {
1799 ty::ClosureKind::Fn => tcx.types.i8,
1800 ty::ClosureKind::FnMut => tcx.types.i16,
1801 ty::ClosureKind::FnOnce => tcx.types.i32,
1802 }
1803 }
1804
1805 pub fn from_coroutine_closure_kind(tcx: TyCtxt<'tcx>, kind: ty::ClosureKind) -> Ty<'tcx> {
1818 match kind {
1819 ty::ClosureKind::Fn | ty::ClosureKind::FnMut => tcx.types.i16,
1820 ty::ClosureKind::FnOnce => tcx.types.i32,
1821 }
1822 }
1823
1824 #[instrument(skip(tcx), level = "debug")]
1834 pub fn has_trivial_sizedness(self, tcx: TyCtxt<'tcx>, sizedness: SizedTraitKind) -> bool {
1835 match self.kind() {
1836 ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
1837 | ty::Uint(_)
1838 | ty::Int(_)
1839 | ty::Bool
1840 | ty::Float(_)
1841 | ty::FnDef(..)
1842 | ty::FnPtr(..)
1843 | ty::UnsafeBinder(_)
1844 | ty::RawPtr(..)
1845 | ty::Char
1846 | ty::Ref(..)
1847 | ty::Coroutine(..)
1848 | ty::CoroutineWitness(..)
1849 | ty::Array(..)
1850 | ty::Pat(..)
1851 | ty::Closure(..)
1852 | ty::CoroutineClosure(..)
1853 | ty::Never
1854 | ty::Error(_) => true,
1855
1856 ty::Str | ty::Slice(_) | ty::Dynamic(_, _, ty::Dyn) => match sizedness {
1857 SizedTraitKind::Sized => false,
1858 SizedTraitKind::MetaSized => true,
1859 },
1860
1861 ty::Foreign(..) => match sizedness {
1862 SizedTraitKind::Sized | SizedTraitKind::MetaSized => false,
1863 },
1864
1865 ty::Tuple(tys) => tys.last().is_none_or(|ty| ty.has_trivial_sizedness(tcx, sizedness)),
1866
1867 ty::Adt(def, args) => def
1868 .sizedness_constraint(tcx, sizedness)
1869 .is_none_or(|ty| ty.instantiate(tcx, args).has_trivial_sizedness(tcx, sizedness)),
1870
1871 ty::Alias(..) | ty::Param(_) | ty::Placeholder(..) | ty::Bound(..) => false,
1872
1873 ty::Infer(ty::TyVar(_)) => false,
1874
1875 ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
1876 bug!("`has_trivial_sizedness` applied to unexpected type: {:?}", self)
1877 }
1878 }
1879 }
1880
1881 pub fn is_trivially_pure_clone_copy(self) -> bool {
1890 match self.kind() {
1891 ty::Bool | ty::Char | ty::Never => true,
1892
1893 ty::Str | ty::Slice(..) | ty::Foreign(..) | ty::Dynamic(..) => false,
1895
1896 ty::Infer(ty::InferTy::FloatVar(_) | ty::InferTy::IntVar(_))
1897 | ty::Int(..)
1898 | ty::Uint(..)
1899 | ty::Float(..) => true,
1900
1901 ty::FnDef(..) => true,
1903
1904 ty::Array(element_ty, _len) => element_ty.is_trivially_pure_clone_copy(),
1905
1906 ty::Tuple(field_tys) => {
1908 field_tys.len() <= 3 && field_tys.iter().all(Self::is_trivially_pure_clone_copy)
1909 }
1910
1911 ty::Pat(ty, _) => ty.is_trivially_pure_clone_copy(),
1912
1913 ty::FnPtr(..) => false,
1916
1917 ty::Ref(_, _, hir::Mutability::Mut) => false,
1919
1920 ty::Ref(_, _, hir::Mutability::Not) | ty::RawPtr(..) => true,
1923
1924 ty::Coroutine(..) | ty::CoroutineWitness(..) => false,
1925
1926 ty::Adt(..) | ty::Closure(..) | ty::CoroutineClosure(..) => false,
1928
1929 ty::UnsafeBinder(_) => false,
1930
1931 ty::Alias(..) => false,
1933
1934 ty::Param(..) | ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error(..) => {
1935 false
1936 }
1937 }
1938 }
1939
1940 pub fn is_trivially_wf(self, tcx: TyCtxt<'tcx>) -> bool {
1941 match *self.kind() {
1942 ty::Bool
1943 | ty::Char
1944 | ty::Int(_)
1945 | ty::Uint(_)
1946 | ty::Float(_)
1947 | ty::Str
1948 | ty::Never
1949 | ty::Param(_)
1950 | ty::Placeholder(_)
1951 | ty::Bound(..) => true,
1952
1953 ty::Slice(ty) => {
1954 ty.is_trivially_wf(tcx) && ty.has_trivial_sizedness(tcx, SizedTraitKind::Sized)
1955 }
1956 ty::RawPtr(ty, _) => ty.is_trivially_wf(tcx),
1957
1958 ty::FnPtr(sig_tys, _) => {
1959 sig_tys.skip_binder().inputs_and_output.iter().all(|ty| ty.is_trivially_wf(tcx))
1960 }
1961 ty::Ref(_, ty, _) => ty.is_global() && ty.is_trivially_wf(tcx),
1962
1963 ty::Infer(infer) => match infer {
1964 ty::TyVar(_) => false,
1965 ty::IntVar(_) | ty::FloatVar(_) => true,
1966 ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => true,
1967 },
1968
1969 ty::Adt(_, _)
1970 | ty::Tuple(_)
1971 | ty::Array(..)
1972 | ty::Foreign(_)
1973 | ty::Pat(_, _)
1974 | ty::FnDef(..)
1975 | ty::UnsafeBinder(..)
1976 | ty::Dynamic(..)
1977 | ty::Closure(..)
1978 | ty::CoroutineClosure(..)
1979 | ty::Coroutine(..)
1980 | ty::CoroutineWitness(..)
1981 | ty::Alias(..)
1982 | ty::Error(_) => false,
1983 }
1984 }
1985
1986 pub fn primitive_symbol(self) -> Option<Symbol> {
1988 match self.kind() {
1989 ty::Bool => Some(sym::bool),
1990 ty::Char => Some(sym::char),
1991 ty::Float(f) => match f {
1992 ty::FloatTy::F16 => Some(sym::f16),
1993 ty::FloatTy::F32 => Some(sym::f32),
1994 ty::FloatTy::F64 => Some(sym::f64),
1995 ty::FloatTy::F128 => Some(sym::f128),
1996 },
1997 ty::Int(f) => match f {
1998 ty::IntTy::Isize => Some(sym::isize),
1999 ty::IntTy::I8 => Some(sym::i8),
2000 ty::IntTy::I16 => Some(sym::i16),
2001 ty::IntTy::I32 => Some(sym::i32),
2002 ty::IntTy::I64 => Some(sym::i64),
2003 ty::IntTy::I128 => Some(sym::i128),
2004 },
2005 ty::Uint(f) => match f {
2006 ty::UintTy::Usize => Some(sym::usize),
2007 ty::UintTy::U8 => Some(sym::u8),
2008 ty::UintTy::U16 => Some(sym::u16),
2009 ty::UintTy::U32 => Some(sym::u32),
2010 ty::UintTy::U64 => Some(sym::u64),
2011 ty::UintTy::U128 => Some(sym::u128),
2012 },
2013 ty::Str => Some(sym::str),
2014 _ => None,
2015 }
2016 }
2017
2018 pub fn is_c_void(self, tcx: TyCtxt<'_>) -> bool {
2019 match self.kind() {
2020 ty::Adt(adt, _) => tcx.is_lang_item(adt.did(), LangItem::CVoid),
2021 _ => false,
2022 }
2023 }
2024
2025 pub fn is_async_drop_in_place_coroutine(self, tcx: TyCtxt<'_>) -> bool {
2026 match self.kind() {
2027 ty::Coroutine(def, ..) => tcx.is_async_drop_in_place_coroutine(*def),
2028 _ => false,
2029 }
2030 }
2031
2032 pub fn is_known_rigid(self) -> bool {
2038 self.kind().is_known_rigid()
2039 }
2040
2041 pub fn walk(self) -> TypeWalker<TyCtxt<'tcx>> {
2052 TypeWalker::new(self.into())
2053 }
2054}
2055
2056impl<'tcx> rustc_type_ir::inherent::Tys<TyCtxt<'tcx>> for &'tcx ty::List<Ty<'tcx>> {
2057 fn inputs(self) -> &'tcx [Ty<'tcx>] {
2058 self.split_last().unwrap().1
2059 }
2060
2061 fn output(self) -> Ty<'tcx> {
2062 *self.split_last().unwrap().0
2063 }
2064}
2065
2066#[cfg(target_pointer_width = "64")]
2068mod size_asserts {
2069 use rustc_data_structures::static_assert_size;
2070
2071 use super::*;
2072 static_assert_size!(TyKind<'_>, 24);
2074 static_assert_size!(ty::WithCachedTypeInfo<TyKind<'_>>, 48);
2075 }