use crate::mir::interpret::ConstValue;
use crate::middle::region;
use polonius_engine::Atom;
-use rustc_data_structures::indexed_vec::Idx;
+use rustc_index::vec::Idx;
use rustc_macros::HashStable;
-use crate::ty::subst::{InternalSubsts, Subst, SubstsRef, Kind, UnpackedKind};
+use crate::ty::subst::{InternalSubsts, Subst, SubstsRef, GenericArg, GenericArgKind};
use crate::ty::{self, AdtDef, Discr, DefIdTree, TypeFlags, Ty, TyCtxt, TypeFoldable};
use crate::ty::{List, TyS, ParamEnvAnd, ParamEnv};
-use crate::ty::layout::VariantIdx;
+use crate::ty::layout::{Size, Integer, IntegerExt, VariantIdx};
use crate::util::captures::Captures;
use crate::mir::interpret::{Scalar, GlobalId};
use std::ops::Range;
use rustc_target::spec::abi;
use syntax::ast::{self, Ident};
+use syntax::attr::{SignedInt, UnsignedInt};
use syntax::symbol::{kw, InternedString};
use self::InferTy::*;
/// AST structure in `libsyntax/ast.rs` as well.
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash,
RustcEncodable, RustcDecodable, HashStable, Debug)]
-#[cfg_attr(not(bootstrap), rustc_diagnostic_item = "TyKind")]
+#[rustc_diagnostic_item = "TyKind"]
pub enum TyKind<'tcx> {
/// The primitive boolean type. Written as `bool`.
Bool,
/// The anonymous type of a closure. Used to represent the type of
/// `|a| a`.
- Closure(DefId, ClosureSubsts<'tcx>),
+ Closure(DefId, SubstsRef<'tcx>),
/// The anonymous type of a generator. Used to represent the type of
/// `|a| yield a`.
- Generator(DefId, GeneratorSubsts<'tcx>, hir::GeneratorMovability),
+ Generator(DefId, SubstsRef<'tcx>, hir::GeneratorMovability),
/// A type representin the types stored inside a generator.
/// This should only appear in GeneratorInteriors.
/// type parameters is similar, but the role of CK and CS are
/// different. CK represents the "yield type" and CS represents the
/// "return type" of the generator.
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash,
- Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug,
+ RustcEncodable, RustcDecodable, HashStable)]
pub struct ClosureSubsts<'tcx> {
/// Lifetime and type parameters from the enclosing function,
/// concatenated with the types of the upvars.
struct SplitClosureSubsts<'tcx> {
closure_kind_ty: Ty<'tcx>,
closure_sig_ty: Ty<'tcx>,
- upvar_kinds: &'tcx [Kind<'tcx>],
+ upvar_kinds: &'tcx [GenericArg<'tcx>],
}
impl<'tcx> ClosureSubsts<'tcx> {
) -> impl Iterator<Item = Ty<'tcx>> + 'tcx {
let SplitClosureSubsts { upvar_kinds, .. } = self.split(def_id, tcx);
upvar_kinds.iter().map(|t| {
- if let UnpackedKind::Type(ty) = t.unpack() {
+ if let GenericArgKind::Type(ty) = t.unpack() {
ty
} else {
bug!("upvar should be type")
/// Returns the closure kind for this closure; may return a type
/// variable during inference. To get the closure kind during
/// inference, use `infcx.closure_kind(def_id, substs)`.
- pub fn closure_kind_ty(self, def_id: DefId, tcx: TyCtxt<'_>) -> Ty<'tcx> {
+ pub fn kind_ty(self, def_id: DefId, tcx: TyCtxt<'_>) -> Ty<'tcx> {
self.split(def_id, tcx).closure_kind_ty
}
/// closure; may contain type variables during inference. To get
/// the closure signature during inference, use
/// `infcx.fn_sig(def_id)`.
- pub fn closure_sig_ty(self, def_id: DefId, tcx: TyCtxt<'_>) -> Ty<'tcx> {
+ pub fn sig_ty(self, def_id: DefId, tcx: TyCtxt<'_>) -> Ty<'tcx> {
self.split(def_id, tcx).closure_sig_ty
}
/// there are no type variables.
///
/// If you have an inference context, use `infcx.closure_kind()`.
- pub fn closure_kind(self, def_id: DefId, tcx: TyCtxt<'tcx>) -> ty::ClosureKind {
+ pub fn kind(self, def_id: DefId, tcx: TyCtxt<'tcx>) -> ty::ClosureKind {
self.split(def_id, tcx).closure_kind_ty.to_opt_closure_kind().unwrap()
}
/// there are no type variables.
///
/// If you have an inference context, use `infcx.closure_sig()`.
- pub fn closure_sig(self, def_id: DefId, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> {
- let ty = self.closure_sig_ty(def_id, tcx);
- match ty.sty {
+ pub fn sig(&self, def_id: DefId, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> {
+ let ty = self.sig_ty(def_id, tcx);
+ match ty.kind {
ty::FnPtr(sig) => sig,
- _ => bug!("closure_sig_ty is not a fn-ptr: {:?}", ty.sty),
+ _ => bug!("closure_sig_ty is not a fn-ptr: {:?}", ty.kind),
}
}
}
yield_ty: Ty<'tcx>,
return_ty: Ty<'tcx>,
witness: Ty<'tcx>,
- upvar_kinds: &'tcx [Kind<'tcx>],
+ upvar_kinds: &'tcx [GenericArg<'tcx>],
}
impl<'tcx> GeneratorSubsts<'tcx> {
) -> impl Iterator<Item = Ty<'tcx>> + 'tcx {
let SplitGeneratorSubsts { upvar_kinds, .. } = self.split(def_id, tcx);
upvar_kinds.iter().map(|t| {
- if let UnpackedKind::Type(ty) = t.unpack() {
+ if let GenericArgKind::Type(ty) = t.unpack() {
ty
} else {
bug!("upvar should be type")
#[derive(Debug, Copy, Clone)]
pub enum UpvarSubsts<'tcx> {
- Closure(ClosureSubsts<'tcx>),
+ Closure(SubstsRef<'tcx>),
Generator(GeneratorSubsts<'tcx>),
}
pub fn upvar_tys(
self,
def_id: DefId,
- tcx: TyCtxt<'_>,
+ tcx: TyCtxt<'tcx>,
) -> impl Iterator<Item = Ty<'tcx>> + 'tcx {
let upvar_kinds = match self {
- UpvarSubsts::Closure(substs) => substs.split(def_id, tcx).upvar_kinds,
+ UpvarSubsts::Closure(substs) => substs.as_closure().split(def_id, tcx).upvar_kinds,
UpvarSubsts::Generator(substs) => substs.split(def_id, tcx).upvar_kinds,
};
upvar_kinds.iter().map(|t| {
- if let UnpackedKind::Type(ty) = t.unpack() {
+ if let GenericArgKind::Type(ty) = t.unpack() {
ty
} else {
bug!("upvar should be type")
}
}
-newtype_index! {
+rustc_index::newtype_index! {
/// A [De Bruijn index][dbi] is a standard means of representing
/// regions (and perhaps later types) in a higher-ranked setting. In
/// particular, imagine a type like this:
pub index: u32,
}
-newtype_index! {
+rustc_index::newtype_index! {
pub struct RegionVid {
DEBUG_FORMAT = custom,
}
FreshFloatTy(u32),
}
-newtype_index! {
+rustc_index::newtype_index! {
pub struct BoundVar { .. }
}
impl<'tcx> TyS<'tcx> {
#[inline]
pub fn is_unit(&self) -> bool {
- match self.sty {
+ match self.kind {
Tuple(ref tys) => tys.is_empty(),
_ => false,
}
#[inline]
pub fn is_never(&self) -> bool {
- match self.sty {
+ match self.kind {
Never => true,
_ => false,
}
pub fn conservative_is_privately_uninhabited(&self, tcx: TyCtxt<'tcx>) -> bool {
// FIXME(varkor): we can make this less conversative by substituting concrete
// type arguments.
- match self.sty {
+ match self.kind {
ty::Never => true,
ty::Adt(def, _) if def.is_union() => {
// For now, `union`s are never considered uninhabited.
#[inline]
pub fn is_primitive(&self) -> bool {
- match self.sty {
+ match self.kind {
Bool | Char | Int(_) | Uint(_) | Float(_) => true,
_ => false,
}
#[inline]
pub fn is_ty_var(&self) -> bool {
- match self.sty {
+ match self.kind {
Infer(TyVar(_)) => true,
_ => false,
}
#[inline]
pub fn is_ty_infer(&self) -> bool {
- match self.sty {
+ match self.kind {
Infer(_) => true,
_ => false,
}
#[inline]
pub fn is_phantom_data(&self) -> bool {
- if let Adt(def, _) = self.sty {
+ if let Adt(def, _) = self.kind {
def.is_phantom_data()
} else {
false
}
#[inline]
- pub fn is_bool(&self) -> bool { self.sty == Bool }
+ pub fn is_bool(&self) -> bool { self.kind == Bool }
#[inline]
pub fn is_param(&self, index: u32) -> bool {
- match self.sty {
+ match self.kind {
ty::Param(ref data) => data.index == index,
_ => false,
}
#[inline]
pub fn is_slice(&self) -> bool {
- match self.sty {
- RawPtr(TypeAndMut { ty, .. }) | Ref(_, ty, _) => match ty.sty {
+ match self.kind {
+ RawPtr(TypeAndMut { ty, .. }) | Ref(_, ty, _) => match ty.kind {
Slice(_) | Str => true,
_ => false,
},
#[inline]
pub fn is_simd(&self) -> bool {
- match self.sty {
+ match self.kind {
Adt(def, _) => def.repr.simd(),
_ => false,
}
}
pub fn sequence_element_type(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
- match self.sty {
+ match self.kind {
Array(ty, _) | Slice(ty) => ty,
Str => tcx.mk_mach_uint(ast::UintTy::U8),
_ => bug!("sequence_element_type called on non-sequence value: {}", self),
}
pub fn simd_type(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
- match self.sty {
+ match self.kind {
Adt(def, substs) => {
def.non_enum_variant().fields[0].ty(tcx, substs)
}
}
pub fn simd_size(&self, _cx: TyCtxt<'_>) -> usize {
- match self.sty {
+ match self.kind {
Adt(def, _) => def.non_enum_variant().fields.len(),
_ => bug!("simd_size called on invalid type")
}
#[inline]
pub fn is_region_ptr(&self) -> bool {
- match self.sty {
+ match self.kind {
Ref(..) => true,
_ => false,
}
#[inline]
pub fn is_mutable_ptr(&self) -> bool {
- match self.sty {
+ match self.kind {
RawPtr(TypeAndMut { mutbl: hir::Mutability::MutMutable, .. }) |
Ref(_, _, hir::Mutability::MutMutable) => true,
_ => false
#[inline]
pub fn is_unsafe_ptr(&self) -> bool {
- match self.sty {
+ match self.kind {
RawPtr(_) => return true,
_ => return false,
}
/// Returns `true` if this type is an `Arc<T>`.
#[inline]
pub fn is_arc(&self) -> bool {
- match self.sty {
+ match self.kind {
Adt(def, _) => def.is_arc(),
_ => false,
}
/// Returns `true` if this type is an `Rc<T>`.
#[inline]
pub fn is_rc(&self) -> bool {
- match self.sty {
+ match self.kind {
Adt(def, _) => def.is_rc(),
_ => false,
}
#[inline]
pub fn is_box(&self) -> bool {
- match self.sty {
+ match self.kind {
Adt(def, _) => def.is_box(),
_ => false,
}
/// panics if called on any type other than `Box<T>`
pub fn boxed_ty(&self) -> Ty<'tcx> {
- match self.sty {
+ match self.kind {
Adt(def, substs) if def.is_box() => substs.type_at(0),
_ => bug!("`boxed_ty` is called on non-box type {:?}", self),
}
/// contents are abstract to rustc.)
#[inline]
pub fn is_scalar(&self) -> bool {
- match self.sty {
+ match self.kind {
Bool | Char | Int(_) | Float(_) | Uint(_) |
Infer(IntVar(_)) | Infer(FloatVar(_)) |
FnDef(..) | FnPtr(_) | RawPtr(_) => true,
/// Returns `true` if this type is a floating point type.
#[inline]
pub fn is_floating_point(&self) -> bool {
- match self.sty {
+ match self.kind {
Float(_) |
Infer(FloatVar(_)) => true,
_ => false,
#[inline]
pub fn is_trait(&self) -> bool {
- match self.sty {
+ match self.kind {
Dynamic(..) => true,
_ => false,
}
#[inline]
pub fn is_enum(&self) -> bool {
- match self.sty {
+ match self.kind {
Adt(adt_def, _) => {
adt_def.is_enum()
}
#[inline]
pub fn is_closure(&self) -> bool {
- match self.sty {
+ match self.kind {
Closure(..) => true,
_ => false,
}
#[inline]
pub fn is_generator(&self) -> bool {
- match self.sty {
+ match self.kind {
Generator(..) => true,
_ => false,
}
#[inline]
pub fn is_integral(&self) -> bool {
- match self.sty {
+ match self.kind {
Infer(IntVar(_)) | Int(_) | Uint(_) => true,
_ => false
}
#[inline]
pub fn is_fresh_ty(&self) -> bool {
- match self.sty {
+ match self.kind {
Infer(FreshTy(_)) => true,
_ => false,
}
#[inline]
pub fn is_fresh(&self) -> bool {
- match self.sty {
+ match self.kind {
Infer(FreshTy(_)) => true,
Infer(FreshIntTy(_)) => true,
Infer(FreshFloatTy(_)) => true,
#[inline]
pub fn is_char(&self) -> bool {
- match self.sty {
+ match self.kind {
Char => true,
_ => false,
}
#[inline]
pub fn is_signed(&self) -> bool {
- match self.sty {
+ match self.kind {
Int(_) => true,
_ => false,
}
#[inline]
pub fn is_ptr_sized_integral(&self) -> bool {
- match self.sty {
+ match self.kind {
Int(ast::IntTy::Isize) | Uint(ast::UintTy::Usize) => true,
_ => false,
}
#[inline]
pub fn is_machine(&self) -> bool {
- match self.sty {
+ match self.kind {
Int(..) | Uint(..) | Float(..) => true,
_ => false,
}
#[inline]
pub fn has_concrete_skeleton(&self) -> bool {
- match self.sty {
+ match self.kind {
Param(_) | Infer(_) | Error => false,
_ => true,
}
/// The parameter `explicit` indicates if this is an *explicit* dereference.
/// Some types -- notably unsafe ptrs -- can only be dereferenced explicitly.
pub fn builtin_deref(&self, explicit: bool) -> Option<TypeAndMut<'tcx>> {
- match self.sty {
+ match self.kind {
Adt(def, _) if def.is_box() => {
Some(TypeAndMut {
ty: self.boxed_ty(),
/// Returns the type of `ty[i]`.
pub fn builtin_index(&self) -> Option<Ty<'tcx>> {
- match self.sty {
+ match self.kind {
Array(ty, _) | Slice(ty) => Some(ty),
_ => None,
}
}
pub fn fn_sig(&self, tcx: TyCtxt<'tcx>) -> PolyFnSig<'tcx> {
- match self.sty {
+ match self.kind {
FnDef(def_id, substs) => {
tcx.fn_sig(def_id).subst(tcx, substs)
}
#[inline]
pub fn is_fn(&self) -> bool {
- match self.sty {
+ match self.kind {
FnDef(..) | FnPtr(_) => true,
_ => false,
}
#[inline]
pub fn is_fn_ptr(&self) -> bool {
- match self.sty {
+ match self.kind {
FnPtr(_) => true,
_ => false,
}
#[inline]
pub fn is_impl_trait(&self) -> bool {
- match self.sty {
+ match self.kind {
Opaque(..) => true,
_ => false,
}
#[inline]
pub fn ty_adt_def(&self) -> Option<&'tcx AdtDef> {
- match self.sty {
+ match self.kind {
Adt(adt, _) => Some(adt),
_ => None,
}
/// Iterates over tuple fields.
/// Panics when called on anything but a tuple.
pub fn tuple_fields(&self) -> impl DoubleEndedIterator<Item=Ty<'tcx>> {
- match self.sty {
+ match self.kind {
Tuple(substs) => substs.iter().map(|field| field.expect_ty()),
_ => bug!("tuple_fields called on non-tuple"),
}
/// FIXME This requires the optimized MIR in the case of generators.
#[inline]
pub fn variant_range(&self, tcx: TyCtxt<'tcx>) -> Option<Range<VariantIdx>> {
- match self.sty {
+ match self.kind {
TyKind::Adt(adt, _) => Some(adt.variant_range()),
- TyKind::Generator(def_id, substs, _) => Some(substs.variant_range(def_id, tcx)),
+ TyKind::Generator(def_id, substs, _) =>
+ Some(substs.assert_generator().variant_range(def_id, tcx)),
_ => None,
}
}
tcx: TyCtxt<'tcx>,
variant_index: VariantIdx,
) -> Option<Discr<'tcx>> {
- match self.sty {
+ match self.kind {
TyKind::Adt(adt, _) => Some(adt.discriminant_for_variant(tcx, variant_index)),
TyKind::Generator(def_id, substs, _) =>
- Some(substs.discriminant_for_variant(def_id, tcx, variant_index)),
+ Some(substs.as_generator().discriminant_for_variant(def_id, tcx, variant_index)),
_ => None,
}
}
/// types reachable from this type via `walk_tys`). This ignores late-bound
/// regions binders.
pub fn push_regions(&self, out: &mut SmallVec<[ty::Region<'tcx>; 4]>) {
- match self.sty {
+ match self.kind {
Ref(region, _, _) => {
out.push(region);
}
Adt(_, substs) | Opaque(_, substs) => {
out.extend(substs.regions())
}
- Closure(_, ClosureSubsts { ref substs }) |
- Generator(_, GeneratorSubsts { ref substs }, _) => {
+ Closure(_, ref substs ) |
+ Generator(_, ref substs, _) => {
out.extend(substs.regions())
}
Projection(ref data) | UnnormalizedProjection(ref data) => {
/// inferred. Once upvar inference (in `src/librustc_typeck/check/upvar.rs`)
/// is complete, that type variable will be unified.
pub fn to_opt_closure_kind(&self) -> Option<ty::ClosureKind> {
- match self.sty {
+ match self.kind {
Int(int_ty) => match int_ty {
ast::IntTy::I8 => Some(ty::ClosureKind::Fn),
ast::IntTy::I16 => Some(ty::ClosureKind::FnMut),
/// Returning true means the type is known to be sized. Returning
/// `false` means nothing -- could be sized, might not be.
pub fn is_trivially_sized(&self, tcx: TyCtxt<'tcx>) -> bool {
- match self.sty {
+ match self.kind {
ty::Infer(ty::IntVar(_)) | ty::Infer(ty::FloatVar(_)) |
ty::Uint(_) | ty::Int(_) | ty::Bool | ty::Float(_) |
ty::FnDef(..) | ty::FnPtr(_) | ty::RawPtr(..) |
ty: Ty<'tcx>,
) -> Option<u128> {
assert_eq!(self.ty, ty);
+ // This is purely an optimization -- layout_of is a pretty expensive operation,
+ // but if we can determine the size without calling it, we don't need all that complexity
+ // (hashing, caching, etc.). As such, try to skip it.
+ let size = match ty.kind {
+ ty::Bool => Size::from_bytes(1),
+ ty::Char => Size::from_bytes(4),
+ ty::Int(ity) => {
+ Integer::from_attr(&tcx, SignedInt(ity)).size()
+ }
+ ty::Uint(uty) => {
+ Integer::from_attr(&tcx, UnsignedInt(uty)).size()
+ }
+ _ => tcx.layout_of(param_env.with_reveal_all().and(ty)).ok()?.size,
+ };
// if `ty` does not depend on generic parameters, use an empty param_env
- let size = tcx.layout_of(param_env.with_reveal_all().and(ty)).ok()?.size;
self.eval(tcx, param_env).val.try_to_bits(size)
}