diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 03:57:31 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 03:57:31 +0000 |
commit | dc0db358abe19481e475e10c32149b53370f1a1c (patch) | |
tree | ab8ce99c4b255ce46f99ef402c27916055b899ee /compiler/rustc_middle/src/ty/sty.rs | |
parent | Releasing progress-linux version 1.71.1+dfsg1-2~progress7.99u1. (diff) | |
download | rustc-dc0db358abe19481e475e10c32149b53370f1a1c.tar.xz rustc-dc0db358abe19481e475e10c32149b53370f1a1c.zip |
Merging upstream version 1.72.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_middle/src/ty/sty.rs')
-rw-r--r-- | compiler/rustc_middle/src/ty/sty.rs | 573 |
1 files changed, 532 insertions, 41 deletions
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index e6d51c4ec..94746fbdc 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -15,16 +15,18 @@ use hir::def::DefKind; use polonius_engine::Atom; use rustc_data_structures::captures::Captures; use rustc_data_structures::intern::Interned; -use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg}; +use rustc_error_messages::DiagnosticMessage; +use rustc_errors::{DiagnosticArgValue, ErrorGuaranteed, IntoDiagnosticArg, MultiSpan}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::LangItem; use rustc_index::Idx; use rustc_macros::HashStable; use rustc_span::symbol::{kw, sym, Symbol}; -use rustc_span::Span; +use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT}; use rustc_target::spec::abi::{self, Abi}; +use std::assert_matches::debug_assert_matches; use std::borrow::Cow; use std::cmp::Ordering; use std::fmt; @@ -33,13 +35,17 @@ use std::ops::{ControlFlow, Deref, Range}; use ty::util::IntTypeExt; use rustc_type_ir::sty::TyKind::*; -use rustc_type_ir::RegionKind as IrRegionKind; use rustc_type_ir::TyKind as IrTyKind; +use rustc_type_ir::{CollectAndApply, ConstKind as IrConstKind}; +use rustc_type_ir::{DynKind, RegionKind as IrRegionKind}; + +use super::GenericParamDefKind; // Re-export the `TyKind` from `rustc_type_ir` here for convenience #[rustc_diagnostic_item = "TyKind"] pub type TyKind<'tcx> = IrTyKind<TyCtxt<'tcx>>; pub type RegionKind<'tcx> = IrRegionKind<TyCtxt<'tcx>>; +pub type ConstKind<'tcx> = IrConstKind<TyCtxt<'tcx>>; #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)] #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] @@ -568,7 +574,7 @@ impl<'tcx> GeneratorSubsts<'tcx> { let layout = tcx.generator_layout(def_id).unwrap(); layout.variant_fields.iter().map(move |variant| { variant.iter().map(move |field| { - ty::EarlyBinder(layout.field_tys[*field].ty).subst(tcx, self.substs) + ty::EarlyBinder::bind(layout.field_tys[*field].ty).subst(tcx, self.substs) }) }) } @@ -715,7 +721,7 @@ impl<'tcx> PolyExistentialPredicate<'tcx> { /// Given an existential predicate like `?Self: PartialEq<u32>` (e.g., derived from `dyn PartialEq<u32>`), /// and a concrete type `self_ty`, returns a full predicate where the existentially quantified variable `?Self` /// has been replaced with `self_ty` (e.g., `self_ty: PartialEq<u32>`, in our example). - pub fn with_self_ty(&self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ty::Predicate<'tcx> { + pub fn with_self_ty(&self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ty::Clause<'tcx> { use crate::ty::ToPredicate; match self.skip_binder() { ExistentialPredicate::Trait(tr) => { @@ -1007,7 +1013,10 @@ impl BoundVariableKind { /// `Decodable` and `Encodable` are implemented for `Binder<T>` using the `impl_binder_encode_decode!` macro. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] #[derive(HashStable, Lift)] -pub struct Binder<'tcx, T>(T, &'tcx List<BoundVariableKind>); +pub struct Binder<'tcx, T> { + value: T, + bound_vars: &'tcx List<BoundVariableKind>, +} impl<'tcx, T> Binder<'tcx, T> where @@ -1023,15 +1032,15 @@ where !value.has_escaping_bound_vars(), "`{value:?}` has escaping bound vars, so it cannot be wrapped in a dummy binder." ); - Binder(value, ty::List::empty()) + Binder { value, bound_vars: ty::List::empty() } } - pub fn bind_with_vars(value: T, vars: &'tcx List<BoundVariableKind>) -> Binder<'tcx, T> { + pub fn bind_with_vars(value: T, bound_vars: &'tcx List<BoundVariableKind>) -> Binder<'tcx, T> { if cfg!(debug_assertions) { - let mut validator = ValidateBoundVars::new(vars); + let mut validator = ValidateBoundVars::new(bound_vars); value.visit_with(&mut validator); } - Binder(value, vars) + Binder { value, bound_vars } } } @@ -1053,30 +1062,30 @@ impl<'tcx, T> Binder<'tcx, T> { /// - comparing the self type of a PolyTraitRef to see if it is equal to /// a type parameter `X`, since the type `X` does not reference any regions pub fn skip_binder(self) -> T { - self.0 + self.value } pub fn bound_vars(&self) -> &'tcx List<BoundVariableKind> { - self.1 + self.bound_vars } pub fn as_ref(&self) -> Binder<'tcx, &T> { - Binder(&self.0, self.1) + Binder { value: &self.value, bound_vars: self.bound_vars } } pub fn as_deref(&self) -> Binder<'tcx, &T::Target> where T: Deref, { - Binder(&self.0, self.1) + Binder { value: &self.value, bound_vars: self.bound_vars } } pub fn map_bound_ref_unchecked<F, U>(&self, f: F) -> Binder<'tcx, U> where F: FnOnce(&T) -> U, { - let value = f(&self.0); - Binder(value, self.1) + let value = f(&self.value); + Binder { value, bound_vars: self.bound_vars } } pub fn map_bound_ref<F, U: TypeVisitable<TyCtxt<'tcx>>>(&self, f: F) -> Binder<'tcx, U> @@ -1090,12 +1099,13 @@ impl<'tcx, T> Binder<'tcx, T> { where F: FnOnce(T) -> U, { - let value = f(self.0); + let Binder { value, bound_vars } = self; + let value = f(value); if cfg!(debug_assertions) { - let mut validator = ValidateBoundVars::new(self.1); + let mut validator = ValidateBoundVars::new(bound_vars); value.visit_with(&mut validator); } - Binder(value, self.1) + Binder { value, bound_vars } } pub fn try_map_bound<F, U: TypeVisitable<TyCtxt<'tcx>>, E>( @@ -1105,12 +1115,13 @@ impl<'tcx, T> Binder<'tcx, T> { where F: FnOnce(T) -> Result<U, E>, { - let value = f(self.0)?; + let Binder { value, bound_vars } = self; + let value = f(value)?; if cfg!(debug_assertions) { - let mut validator = ValidateBoundVars::new(self.1); + let mut validator = ValidateBoundVars::new(bound_vars); value.visit_with(&mut validator); } - Ok(Binder(value, self.1)) + Ok(Binder { value, bound_vars }) } /// Wraps a `value` in a binder, using the same bound variables as the @@ -1126,11 +1137,7 @@ impl<'tcx, T> Binder<'tcx, T> { where U: TypeVisitable<TyCtxt<'tcx>>, { - if cfg!(debug_assertions) { - let mut validator = ValidateBoundVars::new(self.bound_vars()); - value.visit_with(&mut validator); - } - Binder(value, self.1) + Binder::bind_with_vars(value, self.bound_vars) } /// Unwraps and returns the value within, but only if it contains @@ -1147,7 +1154,7 @@ impl<'tcx, T> Binder<'tcx, T> { where T: TypeVisitable<TyCtxt<'tcx>>, { - if self.0.has_escaping_bound_vars() { None } else { Some(self.skip_binder()) } + if self.value.has_escaping_bound_vars() { None } else { Some(self.skip_binder()) } } /// Splits the contents into two things that share the same binder @@ -1160,22 +1167,23 @@ impl<'tcx, T> Binder<'tcx, T> { where F: FnOnce(T) -> (U, V), { - let (u, v) = f(self.0); - (Binder(u, self.1), Binder(v, self.1)) + let Binder { value, bound_vars } = self; + let (u, v) = f(value); + (Binder { value: u, bound_vars }, Binder { value: v, bound_vars }) } } impl<'tcx, T> Binder<'tcx, Option<T>> { pub fn transpose(self) -> Option<Binder<'tcx, T>> { - let bound_vars = self.1; - self.0.map(|v| Binder(v, bound_vars)) + let Binder { value, bound_vars } = self; + value.map(|value| Binder { value, bound_vars }) } } impl<'tcx, T: IntoIterator> Binder<'tcx, T> { pub fn iter(self) -> impl Iterator<Item = ty::Binder<'tcx, T::Item>> { - let bound_vars = self.1; - self.0.into_iter().map(|v| Binder(v, bound_vars)) + let Binder { value, bound_vars } = self; + value.into_iter().map(|value| Binder { value, bound_vars }) } } @@ -1184,7 +1192,7 @@ where T: IntoDiagnosticArg, { fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { - self.0.into_diagnostic_arg() + self.value.into_diagnostic_arg() } } @@ -1231,12 +1239,13 @@ impl<'tcx> AliasTy<'tcx> { DefKind::AssocTy if let DefKind::Impl { of_trait: false } = tcx.def_kind(tcx.parent(self.def_id)) => ty::Inherent, DefKind::AssocTy | DefKind::ImplTraitPlaceholder => ty::Projection, DefKind::OpaqueTy => ty::Opaque, + DefKind::TyAlias => ty::Weak, kind => bug!("unexpected DefKind in AliasTy: {kind:?}"), } } pub fn to_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { - tcx.mk_alias(self.kind(tcx), self) + Ty::new_alias(tcx, self.kind(tcx), self) } } @@ -1427,7 +1436,7 @@ impl<'tcx> ParamTy { #[inline] pub fn to_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { - tcx.mk_ty_param(self.index, self.name) + Ty::new_param(tcx, self.index, self.name) } pub fn span_from_generics(&self, tcx: TyCtxt<'tcx>, item_with_generics: DefId) -> Span { @@ -1459,6 +1468,103 @@ impl ParamConst { #[rustc_pass_by_value] pub struct Region<'tcx>(pub Interned<'tcx, RegionKind<'tcx>>); +impl<'tcx> Region<'tcx> { + #[inline] + pub fn new_early_bound( + tcx: TyCtxt<'tcx>, + early_bound_region: ty::EarlyBoundRegion, + ) -> Region<'tcx> { + tcx.intern_region(ty::ReEarlyBound(early_bound_region)) + } + + #[inline] + pub fn new_late_bound( + tcx: TyCtxt<'tcx>, + debruijn: ty::DebruijnIndex, + bound_region: ty::BoundRegion, + ) -> Region<'tcx> { + // Use a pre-interned one when possible. + if let ty::BoundRegion { var, kind: ty::BrAnon(None) } = bound_region + && let Some(inner) = tcx.lifetimes.re_late_bounds.get(debruijn.as_usize()) + && let Some(re) = inner.get(var.as_usize()).copied() + { + re + } else { + tcx.intern_region(ty::ReLateBound(debruijn, bound_region)) + } + } + + #[inline] + pub fn new_free( + tcx: TyCtxt<'tcx>, + scope: DefId, + bound_region: ty::BoundRegionKind, + ) -> Region<'tcx> { + tcx.intern_region(ty::ReFree(ty::FreeRegion { scope, bound_region })) + } + + #[inline] + pub fn new_var(tcx: TyCtxt<'tcx>, v: ty::RegionVid) -> Region<'tcx> { + // Use a pre-interned one when possible. + tcx.lifetimes + .re_vars + .get(v.as_usize()) + .copied() + .unwrap_or_else(|| tcx.intern_region(ty::ReVar(v))) + } + + #[inline] + pub fn new_placeholder(tcx: TyCtxt<'tcx>, placeholder: ty::PlaceholderRegion) -> Region<'tcx> { + tcx.intern_region(ty::RePlaceholder(placeholder)) + } + + /// Constructs a `RegionKind::ReError` region. + #[track_caller] + pub fn new_error(tcx: TyCtxt<'tcx>, reported: ErrorGuaranteed) -> Region<'tcx> { + tcx.intern_region(ty::ReError(reported)) + } + + /// Constructs a `RegionKind::ReError` region and registers a `delay_span_bug` to ensure it + /// gets used. + #[track_caller] + pub fn new_error_misc(tcx: TyCtxt<'tcx>) -> Region<'tcx> { + Region::new_error_with_message( + tcx, + DUMMY_SP, + "RegionKind::ReError constructed but no error reported", + ) + } + + /// Constructs a `RegionKind::ReError` region and registers a `delay_span_bug` with the given + /// `msg` to ensure it gets used. + #[track_caller] + pub fn new_error_with_message<S: Into<MultiSpan>>( + tcx: TyCtxt<'tcx>, + span: S, + msg: &'static str, + ) -> Region<'tcx> { + let reported = tcx.sess.delay_span_bug(span, msg); + Region::new_error(tcx, reported) + } + + /// Avoid this in favour of more specific `new_*` methods, where possible, + /// to avoid the cost of the `match`. + pub fn new_from_kind(tcx: TyCtxt<'tcx>, kind: RegionKind<'tcx>) -> Region<'tcx> { + match kind { + ty::ReEarlyBound(region) => Region::new_early_bound(tcx, region), + ty::ReLateBound(debruijn, region) => Region::new_late_bound(tcx, debruijn, region), + ty::ReFree(ty::FreeRegion { scope, bound_region }) => { + Region::new_free(tcx, scope, bound_region) + } + ty::ReStatic => tcx.lifetimes.re_static, + ty::ReVar(vid) => Region::new_var(tcx, vid), + ty::RePlaceholder(region) => Region::new_placeholder(tcx, region), + ty::ReErased => tcx.lifetimes.re_erased, + ty::ReError(reported) => Region::new_error(tcx, reported), + } + } +} + impl<'tcx> Deref for Region<'tcx> { type Target = RegionKind<'tcx>; @@ -1484,7 +1590,7 @@ pub struct EarlyBoundRegion { impl fmt::Debug for EarlyBoundRegion { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}, {}", self.index, self.name) + write!(f, "{:?}, {}, {}", self.def_id, self.index, self.name) } } @@ -1511,10 +1617,11 @@ impl Atom for RegionVid { rustc_index::newtype_index! { #[derive(HashStable)] + #[debug_format = "{}"] pub struct BoundVar {} } -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)] #[derive(HashStable)] pub struct BoundTy { pub var: BoundVar, @@ -1770,6 +1877,390 @@ impl<'tcx> Region<'tcx> { } } +/// Constructors for `Ty` +impl<'tcx> Ty<'tcx> { + // Avoid this in favour of more specific `new_*` methods, where possible. + #[allow(rustc::usage_of_ty_tykind)] + #[inline] + pub fn new(tcx: TyCtxt<'tcx>, st: TyKind<'tcx>) -> Ty<'tcx> { + tcx.mk_ty_from_kind(st) + } + + #[inline] + pub fn new_infer(tcx: TyCtxt<'tcx>, infer: ty::InferTy) -> Ty<'tcx> { + Ty::new(tcx, TyKind::Infer(infer)) + } + + #[inline] + pub fn new_var(tcx: TyCtxt<'tcx>, v: ty::TyVid) -> Ty<'tcx> { + // Use a pre-interned one when possible. + tcx.types + .ty_vars + .get(v.as_usize()) + .copied() + .unwrap_or_else(|| Ty::new(tcx, Infer(TyVar(v)))) + } + + #[inline] + pub fn new_int_var(tcx: TyCtxt<'tcx>, v: ty::IntVid) -> Ty<'tcx> { + Ty::new_infer(tcx, IntVar(v)) + } + + #[inline] + pub fn new_float_var(tcx: TyCtxt<'tcx>, v: ty::FloatVid) -> Ty<'tcx> { + Ty::new_infer(tcx, FloatVar(v)) + } + + #[inline] + pub fn new_fresh(tcx: TyCtxt<'tcx>, n: u32) -> Ty<'tcx> { + // Use a pre-interned one when possible. + tcx.types + .fresh_tys + .get(n as usize) + .copied() + .unwrap_or_else(|| Ty::new_infer(tcx, ty::FreshTy(n))) + } + + #[inline] + pub fn new_fresh_int(tcx: TyCtxt<'tcx>, n: u32) -> Ty<'tcx> { + // Use a pre-interned one when possible. + tcx.types + .fresh_int_tys + .get(n as usize) + .copied() + .unwrap_or_else(|| Ty::new_infer(tcx, ty::FreshIntTy(n))) + } + + #[inline] + pub fn new_fresh_float(tcx: TyCtxt<'tcx>, n: u32) -> Ty<'tcx> { + // Use a pre-interned one when possible. + tcx.types + .fresh_float_tys + .get(n as usize) + .copied() + .unwrap_or_else(|| Ty::new_infer(tcx, ty::FreshFloatTy(n))) + } + + #[inline] + pub fn new_param(tcx: TyCtxt<'tcx>, index: u32, name: Symbol) -> Ty<'tcx> { + tcx.mk_ty_from_kind(Param(ParamTy { index, name })) + } + + #[inline] + pub fn new_bound( + tcx: TyCtxt<'tcx>, + index: ty::DebruijnIndex, + bound_ty: ty::BoundTy, + ) -> Ty<'tcx> { + Ty::new(tcx, Bound(index, bound_ty)) + } + + #[inline] + pub fn new_placeholder(tcx: TyCtxt<'tcx>, placeholder: ty::PlaceholderType) -> Ty<'tcx> { + Ty::new(tcx, Placeholder(placeholder)) + } + + #[inline] + pub fn new_alias( + tcx: TyCtxt<'tcx>, + kind: ty::AliasKind, + alias_ty: ty::AliasTy<'tcx>, + ) -> Ty<'tcx> { + debug_assert_matches!( + (kind, tcx.def_kind(alias_ty.def_id)), + (ty::Opaque, DefKind::OpaqueTy) + | (ty::Projection | ty::Inherent, DefKind::AssocTy) + | (ty::Opaque | ty::Projection, DefKind::ImplTraitPlaceholder) + | (ty::Weak, DefKind::TyAlias) + ); + Ty::new(tcx, Alias(kind, alias_ty)) + } + + #[inline] + pub fn new_opaque(tcx: TyCtxt<'tcx>, def_id: DefId, substs: SubstsRef<'tcx>) -> Ty<'tcx> { + Ty::new_alias(tcx, ty::Opaque, tcx.mk_alias_ty(def_id, substs)) + } + + /// Constructs a `TyKind::Error` type with current `ErrorGuaranteed` + pub fn new_error(tcx: TyCtxt<'tcx>, reported: ErrorGuaranteed) -> Ty<'tcx> { + Ty::new(tcx, Error(reported)) + } + + /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` to ensure it gets used. + #[track_caller] + pub fn new_misc_error(tcx: TyCtxt<'tcx>) -> Ty<'tcx> { + Ty::new_error_with_message(tcx, DUMMY_SP, "TyKind::Error constructed but no error reported") + } + + /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg` to + /// ensure it gets used. + #[track_caller] + pub fn new_error_with_message<S: Into<MultiSpan>>( + tcx: TyCtxt<'tcx>, + span: S, + msg: impl Into<DiagnosticMessage>, + ) -> Ty<'tcx> { + let reported = tcx.sess.delay_span_bug(span, msg); + Ty::new(tcx, Error(reported)) + } + + #[inline] + pub fn new_int(tcx: TyCtxt<'tcx>, i: ty::IntTy) -> Ty<'tcx> { + use ty::IntTy::*; + match i { + Isize => tcx.types.isize, + I8 => tcx.types.i8, + I16 => tcx.types.i16, + I32 => tcx.types.i32, + I64 => tcx.types.i64, + I128 => tcx.types.i128, + } + } + + #[inline] + pub fn new_uint(tcx: TyCtxt<'tcx>, ui: ty::UintTy) -> Ty<'tcx> { + use ty::UintTy::*; + match ui { + Usize => tcx.types.usize, + U8 => tcx.types.u8, + U16 => tcx.types.u16, + U32 => tcx.types.u32, + U64 => tcx.types.u64, + U128 => tcx.types.u128, + } + } + + #[inline] + pub fn new_float(tcx: TyCtxt<'tcx>, f: ty::FloatTy) -> Ty<'tcx> { + use ty::FloatTy::*; + match f { + F32 => tcx.types.f32, + F64 => tcx.types.f64, + } + } + + #[inline] + pub fn new_ref(tcx: TyCtxt<'tcx>, r: Region<'tcx>, tm: TypeAndMut<'tcx>) -> Ty<'tcx> { + Ty::new(tcx, Ref(r, tm.ty, tm.mutbl)) + } + + #[inline] + pub fn new_mut_ref(tcx: TyCtxt<'tcx>, r: Region<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { + Ty::new_ref(tcx, r, TypeAndMut { ty, mutbl: hir::Mutability::Mut }) + } + + #[inline] + pub fn new_imm_ref(tcx: TyCtxt<'tcx>, r: Region<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { + Ty::new_ref(tcx, r, TypeAndMut { ty, mutbl: hir::Mutability::Not }) + } + + #[inline] + pub fn new_ptr(tcx: TyCtxt<'tcx>, tm: TypeAndMut<'tcx>) -> Ty<'tcx> { + Ty::new(tcx, RawPtr(tm)) + } + + #[inline] + pub fn new_mut_ptr(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { + Ty::new_ptr(tcx, TypeAndMut { ty, mutbl: hir::Mutability::Mut }) + } + + #[inline] + pub fn new_imm_ptr(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { + Ty::new_ptr(tcx, TypeAndMut { ty, mutbl: hir::Mutability::Not }) + } + + #[inline] + pub fn new_adt(tcx: TyCtxt<'tcx>, def: AdtDef<'tcx>, substs: SubstsRef<'tcx>) -> Ty<'tcx> { + Ty::new(tcx, Adt(def, substs)) + } + + #[inline] + pub fn new_foreign(tcx: TyCtxt<'tcx>, def_id: DefId) -> Ty<'tcx> { + Ty::new(tcx, Foreign(def_id)) + } + + #[inline] + pub fn new_array(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, n: u64) -> Ty<'tcx> { + Ty::new(tcx, Array(ty, ty::Const::from_target_usize(tcx, n))) + } + + #[inline] + pub fn new_array_with_const_len( + tcx: TyCtxt<'tcx>, + ty: Ty<'tcx>, + ct: ty::Const<'tcx>, + ) -> Ty<'tcx> { + Ty::new(tcx, Array(ty, ct)) + } + + #[inline] + pub fn new_slice(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { + Ty::new(tcx, Slice(ty)) + } + + #[inline] + pub fn new_tup(tcx: TyCtxt<'tcx>, ts: &[Ty<'tcx>]) -> Ty<'tcx> { + if ts.is_empty() { tcx.types.unit } else { Ty::new(tcx, Tuple(tcx.mk_type_list(&ts))) } + } + + pub fn new_tup_from_iter<I, T>(tcx: TyCtxt<'tcx>, iter: I) -> T::Output + where + I: Iterator<Item = T>, + T: CollectAndApply<Ty<'tcx>, Ty<'tcx>>, + { + T::collect_and_apply(iter, |ts| Ty::new_tup(tcx, ts)) + } + + #[inline] + pub fn new_fn_def( + tcx: TyCtxt<'tcx>, + def_id: DefId, + substs: impl IntoIterator<Item: Into<GenericArg<'tcx>>>, + ) -> Ty<'tcx> { + let substs = tcx.check_and_mk_substs(def_id, substs); + Ty::new(tcx, FnDef(def_id, substs)) + } + + #[inline] + pub fn new_fn_ptr(tcx: TyCtxt<'tcx>, fty: PolyFnSig<'tcx>) -> Ty<'tcx> { + Ty::new(tcx, FnPtr(fty)) + } + + #[inline] + pub fn new_dynamic( + tcx: TyCtxt<'tcx>, + obj: &'tcx List<PolyExistentialPredicate<'tcx>>, + reg: ty::Region<'tcx>, + repr: DynKind, + ) -> Ty<'tcx> { + Ty::new(tcx, Dynamic(obj, reg, repr)) + } + + #[inline] + pub fn new_projection( + tcx: TyCtxt<'tcx>, + item_def_id: DefId, + substs: impl IntoIterator<Item: Into<GenericArg<'tcx>>>, + ) -> Ty<'tcx> { + Ty::new_alias(tcx, ty::Projection, tcx.mk_alias_ty(item_def_id, substs)) + } + + #[inline] + pub fn new_closure( + tcx: TyCtxt<'tcx>, + def_id: DefId, + closure_substs: SubstsRef<'tcx>, + ) -> Ty<'tcx> { + debug_assert_eq!( + closure_substs.len(), + tcx.generics_of(tcx.typeck_root_def_id(def_id)).count() + 3, + "closure constructed with incorrect substitutions" + ); + Ty::new(tcx, Closure(def_id, closure_substs)) + } + + #[inline] + pub fn new_generator( + tcx: TyCtxt<'tcx>, + def_id: DefId, + generator_substs: SubstsRef<'tcx>, + movability: hir::Movability, + ) -> Ty<'tcx> { + debug_assert_eq!( + generator_substs.len(), + tcx.generics_of(tcx.typeck_root_def_id(def_id)).count() + 5, + "generator constructed with incorrect number of substitutions" + ); + Ty::new(tcx, Generator(def_id, generator_substs, movability)) + } + + #[inline] + pub fn new_generator_witness( + tcx: TyCtxt<'tcx>, + types: ty::Binder<'tcx, &'tcx List<Ty<'tcx>>>, + ) -> Ty<'tcx> { + Ty::new(tcx, GeneratorWitness(types)) + } + + #[inline] + pub fn new_generator_witness_mir( + tcx: TyCtxt<'tcx>, + id: DefId, + substs: SubstsRef<'tcx>, + ) -> Ty<'tcx> { + Ty::new(tcx, GeneratorWitnessMIR(id, substs)) + } + + // misc + + #[inline] + pub fn new_unit(tcx: TyCtxt<'tcx>) -> Ty<'tcx> { + tcx.types.unit + } + + #[inline] + pub fn new_static_str(tcx: TyCtxt<'tcx>) -> Ty<'tcx> { + Ty::new_imm_ref(tcx, tcx.lifetimes.re_static, tcx.types.str_) + } + + #[inline] + pub fn new_diverging_default(tcx: TyCtxt<'tcx>) -> Ty<'tcx> { + if tcx.features().never_type_fallback { tcx.types.never } else { tcx.types.unit } + } + + // lang and diagnostic tys + + fn new_generic_adt(tcx: TyCtxt<'tcx>, wrapper_def_id: DefId, ty_param: Ty<'tcx>) -> Ty<'tcx> { + let adt_def = tcx.adt_def(wrapper_def_id); + let substs = + InternalSubsts::for_item(tcx, wrapper_def_id, |param, substs| match param.kind { + GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => bug!(), + GenericParamDefKind::Type { has_default, .. } => { + if param.index == 0 { + ty_param.into() + } else { + assert!(has_default); + tcx.type_of(param.def_id).subst(tcx, substs).into() + } + } + }); + Ty::new(tcx, Adt(adt_def, substs)) + } + + #[inline] + pub fn new_lang_item(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, item: LangItem) -> Option<Ty<'tcx>> { + let def_id = tcx.lang_items().get(item)?; + Some(Ty::new_generic_adt(tcx, def_id, ty)) + } + + #[inline] + pub fn new_diagnostic_item(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, name: Symbol) -> Option<Ty<'tcx>> { + let def_id = tcx.get_diagnostic_item(name)?; + Some(Ty::new_generic_adt(tcx, def_id, ty)) + } + + #[inline] + pub fn new_box(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { + let def_id = tcx.require_lang_item(LangItem::OwnedBox, None); + Ty::new_generic_adt(tcx, def_id, ty) + } + + #[inline] + pub fn new_maybe_uninit(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { + let def_id = tcx.require_lang_item(LangItem::MaybeUninit, None); + Ty::new_generic_adt(tcx, def_id, ty) + } + + /// Creates a `&mut Context<'_>` [`Ty`] with erased lifetimes. + pub fn new_task_context(tcx: TyCtxt<'tcx>) -> Ty<'tcx> { + let context_did = tcx.require_lang_item(LangItem::Context, None); + let context_adt_ref = tcx.adt_def(context_did); + let context_substs = tcx.mk_substs(&[tcx.lifetimes.re_erased.into()]); + let context_ty = Ty::new_adt(tcx, context_adt_ref, context_substs); + Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, context_ty) + } +} + /// Type utilities impl<'tcx> Ty<'tcx> { #[inline(always)] @@ -2213,7 +2704,7 @@ impl<'tcx> Ty<'tcx> { let assoc_items = tcx.associated_item_def_ids( tcx.require_lang_item(hir::LangItem::DiscriminantKind, None), ); - tcx.mk_projection(assoc_items[0], tcx.mk_substs(&[self.into()])) + Ty::new_projection(tcx, assoc_items[0], tcx.mk_substs(&[self.into()])) } ty::Bool @@ -2366,7 +2857,7 @@ impl<'tcx> Ty<'tcx> { ty::Tuple(tys) => tys.iter().all(|ty| ty.is_trivially_sized(tcx)), - ty::Adt(def, _substs) => def.sized_constraint(tcx).0.is_empty(), + ty::Adt(def, _substs) => def.sized_constraint(tcx).skip_binder().is_empty(), ty::Alias(..) | ty::Param(_) | ty::Placeholder(..) => false, |