use crate::ty::fold::ValidateBoundVars;
use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef};
use crate::ty::InferTy::{self, *};
-use crate::ty::{
- self, AdtDef, DefIdTree, Discr, Ty, TyCtxt, TypeFlags, TypeFoldable, WithConstness,
-};
+use crate::ty::{self, AdtDef, DefIdTree, Discr, Term, Ty, TyCtxt, TypeFlags, TypeFoldable};
use crate::ty::{DelaySpanBugEmitted, List, ParamEnv, TyS};
use polonius_engine::Atom;
use rustc_data_structures::captures::Captures;
Error(DelaySpanBugEmitted),
}
-impl TyKind<'tcx> {
+impl<'tcx> TyKind<'tcx> {
#[inline]
pub fn is_primitive(&self) -> bool {
matches!(self, Bool | Char | Int(_) | Uint(_) | Float(_))
/// The ordering assumed here must match that used by `ClosureSubsts::new` above.
fn split(self) -> ClosureSubstsParts<'tcx, GenericArg<'tcx>> {
match self.substs[..] {
- [ref parent_substs @ .., closure_kind_ty, closure_sig_as_fn_ptr_ty, tupled_upvars_ty] => {
- ClosureSubstsParts {
- parent_substs,
- closure_kind_ty,
- closure_sig_as_fn_ptr_ty,
- tupled_upvars_ty,
- }
- }
+ [
+ ref parent_substs @ ..,
+ closure_kind_ty,
+ closure_sig_as_fn_ptr_ty,
+ tupled_upvars_ty,
+ ] => ClosureSubstsParts {
+ parent_substs,
+ closure_kind_ty,
+ closure_sig_as_fn_ptr_ty,
+ tupled_upvars_ty,
+ },
_ => bug!("closure substs missing synthetics"),
}
}
}
}
+/// An inline const is modeled like
+///
+/// const InlineConst<'l0...'li, T0...Tj, R>: R;
+///
+/// where:
+///
+/// - 'l0...'li and T0...Tj are the generic parameters
+/// inherited from the item that defined the inline const,
+/// - R represents the type of the constant.
+///
+/// When the inline const is instantiated, `R` is substituted as the actual inferred
+/// type of the constant. The reason that `R` is represented as an extra type parameter
+/// is the same reason that [`ClosureSubsts`] have `CS` and `U` as type parameters:
+/// inline const can reference lifetimes that are internal to the creating function.
+#[derive(Copy, Clone, Debug, TypeFoldable)]
+pub struct InlineConstSubsts<'tcx> {
+ /// Generic parameters from the enclosing item,
+ /// concatenated with the inferred type of the constant.
+ pub substs: SubstsRef<'tcx>,
+}
+
+/// Struct returned by `split()`.
+pub struct InlineConstSubstsParts<'tcx, T> {
+ pub parent_substs: &'tcx [GenericArg<'tcx>],
+ pub ty: T,
+}
+
+impl<'tcx> InlineConstSubsts<'tcx> {
+ /// Construct `InlineConstSubsts` from `InlineConstSubstsParts`.
+ pub fn new(
+ tcx: TyCtxt<'tcx>,
+ parts: InlineConstSubstsParts<'tcx, Ty<'tcx>>,
+ ) -> InlineConstSubsts<'tcx> {
+ InlineConstSubsts {
+ substs: tcx.mk_substs(
+ parts.parent_substs.iter().copied().chain(std::iter::once(parts.ty.into())),
+ ),
+ }
+ }
+
+ /// Divides the inline const substs into their respective components.
+ /// The ordering assumed here must match that used by `InlineConstSubsts::new` above.
+ fn split(self) -> InlineConstSubstsParts<'tcx, GenericArg<'tcx>> {
+ match self.substs[..] {
+ [ref parent_substs @ .., ty] => InlineConstSubstsParts { parent_substs, ty },
+ _ => bug!("inline const substs missing synthetics"),
+ }
+ }
+
+ /// Returns the substitutions of the inline const's parent.
+ pub fn parent_substs(self) -> &'tcx [GenericArg<'tcx>] {
+ self.split().parent_substs
+ }
+
+ /// Returns the type of this inline const.
+ pub fn ty(self) -> Ty<'tcx> {
+ self.split().ty.expect_ty()
+ }
+}
+
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable)]
pub enum ExistentialPredicate<'tcx> {
tcx.def_path_hash(a.item_def_id).cmp(&tcx.def_path_hash(b.item_def_id))
}
(AutoTrait(ref a), AutoTrait(ref b)) => {
- tcx.trait_def(*a).def_path_hash.cmp(&tcx.trait_def(*b).def_path_hash)
+ tcx.def_path_hash(*a).cmp(&tcx.def_path_hash(*b))
}
(Trait(_), _) => Ordering::Less,
(Projection(_), Trait(_)) => Ordering::Greater,
///
/// Trait references also appear in object types like `Foo<U>`, but in
/// that case the `Self` parameter is absent from the substitutions.
-#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable)]
pub struct TraitRef<'tcx> {
pub def_id: DefId,
Binder(value, self.1)
}
+ pub fn try_map_bound<F, U: TypeFoldable<'tcx>, E>(self, f: F) -> Result<Binder<'tcx, U>, E>
+ where
+ F: FnOnce(T) -> Result<U, E>,
+ {
+ let value = f(self.0)?;
+ if cfg!(debug_assertions) {
+ let mut validator = ValidateBoundVars::new(self.1);
+ value.visit_with(&mut validator);
+ }
+ Ok(Binder(value, self.1))
+ }
+
/// Wraps a `value` in a binder, using the same bound variables as the
/// current `Binder`. This should not be used if the new value *changes*
/// the bound variables. Note: the (old or new) value itself does not
pub struct ExistentialProjection<'tcx> {
pub item_def_id: DefId,
pub substs: SubstsRef<'tcx>,
- pub ty: Ty<'tcx>,
+ pub term: Term<'tcx>,
}
pub type PolyExistentialProjection<'tcx> = Binder<'tcx, ExistentialProjection<'tcx>>;
item_def_id: self.item_def_id,
substs: tcx.mk_substs_trait(self_ty, self.substs),
},
- ty: self.ty,
+ term: self.term,
}
}
Self {
item_def_id: projection_predicate.projection_ty.item_def_id,
substs: tcx.intern_substs(&projection_predicate.projection_ty.substs[1..]),
- ty: projection_predicate.ty,
+ term: projection_predicate.term,
}
}
}
match *self {
ty::ReVar(..) => {
- flags = flags | TypeFlags::HAS_KNOWN_FREE_REGIONS;
- flags = flags | TypeFlags::HAS_KNOWN_FREE_LOCAL_REGIONS;
+ flags = flags | TypeFlags::HAS_FREE_REGIONS;
+ flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS;
flags = flags | TypeFlags::HAS_RE_INFER;
}
ty::RePlaceholder(..) => {
- flags = flags | TypeFlags::HAS_KNOWN_FREE_REGIONS;
- flags = flags | TypeFlags::HAS_KNOWN_FREE_LOCAL_REGIONS;
+ flags = flags | TypeFlags::HAS_FREE_REGIONS;
+ flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS;
flags = flags | TypeFlags::HAS_RE_PLACEHOLDER;
}
ty::ReEarlyBound(..) => {
- flags = flags | TypeFlags::HAS_KNOWN_FREE_REGIONS;
- flags = flags | TypeFlags::HAS_KNOWN_FREE_LOCAL_REGIONS;
- flags = flags | TypeFlags::HAS_KNOWN_RE_PARAM;
+ flags = flags | TypeFlags::HAS_FREE_REGIONS;
+ flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS;
+ flags = flags | TypeFlags::HAS_RE_PARAM;
}
ty::ReFree { .. } => {
- flags = flags | TypeFlags::HAS_KNOWN_FREE_REGIONS;
- flags = flags | TypeFlags::HAS_KNOWN_FREE_LOCAL_REGIONS;
+ flags = flags | TypeFlags::HAS_FREE_REGIONS;
+ flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS;
}
ty::ReEmpty(_) | ty::ReStatic => {
- flags = flags | TypeFlags::HAS_KNOWN_FREE_REGIONS;
+ flags = flags | TypeFlags::HAS_FREE_REGIONS;
}
ty::ReLateBound(..) => {
flags = flags | TypeFlags::HAS_RE_LATE_BOUND;
pub fn sequence_element_type(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
match self.kind() {
Array(ty, _) | Slice(ty) => ty,
- Str => tcx.mk_mach_uint(ty::UintTy::U8),
+ Str => tcx.types.u8,
_ => bug!("`sequence_element_type` called on non-sequence value: {}", self),
}
}
pub fn simd_size_and_type(&self, tcx: TyCtxt<'tcx>) -> (u64, Ty<'tcx>) {
match self.kind() {
Adt(def, substs) => {
+ assert!(def.repr.simd(), "`simd_size_and_type` called on non-SIMD type");
let variant = def.non_enum_variant();
let f0_ty = variant.fields[0].ty(tcx, substs);
match f0_ty.kind() {
+ // If the first field is an array, we assume it is the only field and its
+ // elements are the SIMD components.
Array(f0_elem_ty, f0_len) => {
// FIXME(repr_simd): https://github.com/rust-lang/rust/pull/78863#discussion_r522784112
// The way we evaluate the `N` in `[T; N]` here only works since we use
// if we use it in generic code. See the `simd-array-trait` ui test.
(f0_len.eval_usize(tcx, ParamEnv::empty()) as u64, f0_elem_ty)
}
+ // Otherwise, the fields of this Adt are the SIMD components (and we assume they
+ // all have the same type).
_ => (variant.fields.len() as u64, f0_ty),
}
}
) -> Option<Discr<'tcx>> {
match self.kind() {
TyKind::Adt(adt, _) if adt.variants.is_empty() => {
- bug!("discriminant_for_variant called on zero variant enum");
+ // This can actually happen during CTFE, see
+ // https://github.com/rust-lang/rust/issues/89765.
+ None
}
TyKind::Adt(adt, _) if adt.is_enum() => {
Some(adt.discriminant_for_variant(tcx, variant_index))
ty::Generator(_, substs, _) => substs.as_generator().discr_ty(tcx),
ty::Param(_) | ty::Projection(_) | ty::Opaque(..) | ty::Infer(ty::TyVar(_)) => {
- let assoc_items =
- tcx.associated_items(tcx.lang_items().discriminant_kind_trait().unwrap());
- let discriminant_def_id = assoc_items.in_definition_order().next().unwrap().def_id;
- tcx.mk_projection(discriminant_def_id, tcx.mk_substs([self.into()].iter()))
+ let assoc_items = tcx.associated_item_def_ids(
+ tcx.require_lang_item(hir::LangItem::DiscriminantKind, None),
+ );
+ tcx.mk_projection(assoc_items[0], tcx.intern_substs(&[self.into()]))
}
ty::Bool
}
/// Returns the type of metadata for (potentially fat) pointers to this type.
- pub fn ptr_metadata_ty(&'tcx self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
- // FIXME: should this normalize?
- let tail = tcx.struct_tail_without_normalization(self);
+ pub fn ptr_metadata_ty(
+ &'tcx self,
+ tcx: TyCtxt<'tcx>,
+ normalize: impl FnMut(Ty<'tcx>) -> Ty<'tcx>,
+ ) -> Ty<'tcx> {
+ let tail = tcx.struct_tail_with_normalize(self, normalize);
match tail.kind() {
// Sized types
ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
/// a miscompilation or unsoundness.
///
/// When in doubt, use `VarianceDiagInfo::default()`
-#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
+#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
pub enum VarianceDiagInfo<'tcx> {
/// No additional information - this is the default.
/// We will not add any additional information to error messages.
+ #[default]
None,
- /// We switched our variance because a type occurs inside
- /// the generic argument of a mutable reference or pointer
- /// (`*mut T` or `&mut T`). In either case, our variance
- /// will always be `Invariant`.
- Mut {
- /// Tracks whether we had a mutable pointer or reference,
- /// for better error messages
- kind: VarianceDiagMutKind,
- /// The type parameter of the mutable pointer/reference
- /// (the `T` in `&mut T` or `*mut T`).
+ /// We switched our variance because a generic argument occurs inside
+ /// the invariant generic argument of another type.
+ Invariant {
+ /// The generic type containing the generic parameter
+ /// that changes the variance (e.g. `*mut T`, `MyStruct<T>`)
ty: Ty<'tcx>,
+ /// The index of the generic parameter being used
+ /// (e.g. `0` for `*mut T`, `1` for `MyStruct<'CovariantParam, 'InvariantParam>`)
+ param_index: u32,
},
}
-#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
-pub enum VarianceDiagMutKind {
- /// A mutable raw pointer (`*mut T`)
- RawPtr,
- /// A mutable reference (`&mut T`)
- Ref,
-}
-
impl<'tcx> VarianceDiagInfo<'tcx> {
/// Mirrors `Variance::xform` - used to 'combine' the existing
/// and new `VarianceDiagInfo`s when our variance changes.
pub fn xform(self, other: VarianceDiagInfo<'tcx>) -> VarianceDiagInfo<'tcx> {
- // For now, just use the first `VarianceDiagInfo::Mut` that we see
+ // For now, just use the first `VarianceDiagInfo::Invariant` that we see
match self {
VarianceDiagInfo::None => other,
- VarianceDiagInfo::Mut { .. } => self,
+ VarianceDiagInfo::Invariant { .. } => self,
}
}
}
-
-impl<'tcx> Default for VarianceDiagInfo<'tcx> {
- fn default() -> Self {
- Self::None
- }
-}