//!
//! ["The `ty` module: representing types"]: https://rustc-dev-guide.rust-lang.org/ty.html
-pub use self::fold::{TypeFoldable, TypeFolder, TypeVisitor};
+pub use self::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeVisitor};
pub use self::AssocItemContainer::*;
pub use self::BorrowKind::*;
pub use self::IntVarValue::*;
GeneratorSubsts, GeneratorSubstsParts, InlineConstSubsts, InlineConstSubstsParts, ParamConst,
ParamTy, PolyExistentialProjection, PolyExistentialTraitRef, PolyFnSig, PolyGenSig,
PolyTraitRef, ProjectionTy, Region, RegionKind, RegionVid, TraitRef, TyKind, TypeAndMut,
- UpvarSubsts, VarianceDiagInfo, VarianceDiagMutKind,
+ UpvarSubsts, VarianceDiagInfo,
};
pub use self::trait_def::TraitDef;
ConstIfConst,
}
+impl BoundConstness {
+ /// Reduce `self` and `constness` to two possible combined states instead of four.
+ pub fn and(&mut self, constness: hir::Constness) -> hir::Constness {
+ match (constness, self) {
+ (hir::Constness::Const, BoundConstness::ConstIfConst) => hir::Constness::Const,
+ (_, this) => {
+ *this = BoundConstness::NotConst;
+ hir::Constness::NotConst
+ }
+ }
+ }
+}
+
impl fmt::Display for BoundConstness {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
pub type PolyTraitPredicate<'tcx> = ty::Binder<'tcx, TraitPredicate<'tcx>>;
impl<'tcx> TraitPredicate<'tcx> {
+ pub fn remap_constness(&mut self, tcx: TyCtxt<'tcx>, param_env: &mut ParamEnv<'tcx>) {
+ if unlikely!(Some(self.trait_ref.def_id) == tcx.lang_items().drop_trait()) {
+ // remap without changing constness of this predicate.
+ // this is because `T: ~const Drop` has a different meaning to `T: Drop`
+ param_env.remap_constness_with(self.constness)
+ } else {
+ *param_env = param_env.with_constness(self.constness.and(param_env.constness()))
+ }
+ }
pub fn def_id(self) -> DefId {
self.trait_ref.def_id
}
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx>;
}
-impl ToPredicate<'tcx> for Binder<'tcx, PredicateKind<'tcx>> {
+impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, PredicateKind<'tcx>> {
#[inline(always)]
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
tcx.mk_predicate(self)
}
}
-impl<'tcx> ToPredicate<'tcx> for ConstnessAnd<PolyTraitRef<'tcx>> {
- fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
- self.value
- .map_bound(|trait_ref| {
- PredicateKind::Trait(ty::TraitPredicate {
- trait_ref,
- constness: self.constness,
- polarity: ty::ImplPolarity::Positive,
- })
- })
- .to_predicate(tcx)
- }
-}
-
impl<'tcx> ToPredicate<'tcx> for PolyTraitPredicate<'tcx> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
self.map_bound(PredicateKind::Trait).to_predicate(tcx)
}
impl<'tcx> Predicate<'tcx> {
- pub fn to_opt_poly_trait_ref(self) -> Option<ConstnessAnd<PolyTraitRef<'tcx>>> {
+ pub fn to_opt_poly_trait_pred(self) -> Option<PolyTraitPredicate<'tcx>> {
let predicate = self.kind();
match predicate.skip_binder() {
- PredicateKind::Trait(t) => {
- Some(ConstnessAnd { constness: t.constness, value: predicate.rebind(t.trait_ref) })
- }
+ PredicateKind::Trait(t) => Some(predicate.rebind(t)),
PredicateKind::Projection(..)
| PredicateKind::Subtype(..)
| PredicateKind::Coerce(..)
/// want `Reveal::All`.
///
/// Note: This is packed, use the reveal() method to access it.
- packed: CopyTaggedPtr<&'tcx List<Predicate<'tcx>>, traits::Reveal, true>,
+ packed: CopyTaggedPtr<&'tcx List<Predicate<'tcx>>, ParamTag, true>,
}
-unsafe impl rustc_data_structures::tagged_ptr::Tag for traits::Reveal {
- const BITS: usize = 1;
+#[derive(Copy, Clone)]
+struct ParamTag {
+ reveal: traits::Reveal,
+ constness: hir::Constness,
+}
+
+unsafe impl rustc_data_structures::tagged_ptr::Tag for ParamTag {
+ const BITS: usize = 2;
#[inline]
fn into_usize(self) -> usize {
match self {
- traits::Reveal::UserFacing => 0,
- traits::Reveal::All => 1,
+ Self { reveal: traits::Reveal::UserFacing, constness: hir::Constness::NotConst } => 0,
+ Self { reveal: traits::Reveal::All, constness: hir::Constness::NotConst } => 1,
+ Self { reveal: traits::Reveal::UserFacing, constness: hir::Constness::Const } => 2,
+ Self { reveal: traits::Reveal::All, constness: hir::Constness::Const } => 3,
}
}
#[inline]
unsafe fn from_usize(ptr: usize) -> Self {
match ptr {
- 0 => traits::Reveal::UserFacing,
- 1 => traits::Reveal::All,
+ 0 => Self { reveal: traits::Reveal::UserFacing, constness: hir::Constness::NotConst },
+ 1 => Self { reveal: traits::Reveal::All, constness: hir::Constness::NotConst },
+ 2 => Self { reveal: traits::Reveal::UserFacing, constness: hir::Constness::Const },
+ 3 => Self { reveal: traits::Reveal::All, constness: hir::Constness::Const },
_ => std::hint::unreachable_unchecked(),
}
}
f.debug_struct("ParamEnv")
.field("caller_bounds", &self.caller_bounds())
.field("reveal", &self.reveal())
+ .field("constness", &self.constness())
.finish()
}
}
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
self.caller_bounds().hash_stable(hcx, hasher);
self.reveal().hash_stable(hcx, hasher);
+ self.constness().hash_stable(hcx, hasher);
}
}
impl<'tcx> TypeFoldable<'tcx> for ParamEnv<'tcx> {
- fn super_fold_with<F: ty::fold::TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
- ParamEnv::new(self.caller_bounds().fold_with(folder), self.reveal().fold_with(folder))
+ fn try_super_fold_with<F: ty::fold::FallibleTypeFolder<'tcx>>(
+ self,
+ folder: &mut F,
+ ) -> Result<Self, F::Error> {
+ Ok(ParamEnv::new(
+ self.caller_bounds().try_fold_with(folder)?,
+ self.reveal().try_fold_with(folder)?,
+ self.constness().try_fold_with(folder)?,
+ ))
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.caller_bounds().visit_with(visitor)?;
- self.reveal().visit_with(visitor)
+ self.reveal().visit_with(visitor)?;
+ self.constness().visit_with(visitor)
}
}
/// type-checking.
#[inline]
pub fn empty() -> Self {
- Self::new(List::empty(), Reveal::UserFacing)
+ Self::new(List::empty(), Reveal::UserFacing, hir::Constness::NotConst)
}
#[inline]
#[inline]
pub fn reveal(self) -> traits::Reveal {
- self.packed.tag()
+ self.packed.tag().reveal
+ }
+
+ #[inline]
+ pub fn constness(self) -> hir::Constness {
+ self.packed.tag().constness
}
/// Construct a trait environment with no where-clauses in scope
/// or invoke `param_env.with_reveal_all()`.
#[inline]
pub fn reveal_all() -> Self {
- Self::new(List::empty(), Reveal::All)
+ Self::new(List::empty(), Reveal::All, hir::Constness::NotConst)
}
/// Construct a trait environment with the given set of predicates.
#[inline]
- pub fn new(caller_bounds: &'tcx List<Predicate<'tcx>>, reveal: Reveal) -> Self {
- ty::ParamEnv { packed: CopyTaggedPtr::new(caller_bounds, reveal) }
+ pub fn new(
+ caller_bounds: &'tcx List<Predicate<'tcx>>,
+ reveal: Reveal,
+ constness: hir::Constness,
+ ) -> Self {
+ ty::ParamEnv { packed: CopyTaggedPtr::new(caller_bounds, ParamTag { reveal, constness }) }
}
pub fn with_user_facing(mut self) -> Self {
- self.packed.set_tag(Reveal::UserFacing);
+ self.packed.set_tag(ParamTag { reveal: Reveal::UserFacing, ..self.packed.tag() });
self
}
+ #[inline]
+ pub fn with_constness(mut self, constness: hir::Constness) -> Self {
+ self.packed.set_tag(ParamTag { constness, ..self.packed.tag() });
+ self
+ }
+
+ #[inline]
+ pub fn with_const(mut self) -> Self {
+ self.packed.set_tag(ParamTag { constness: hir::Constness::Const, ..self.packed.tag() });
+ self
+ }
+
+ #[inline]
+ pub fn without_const(mut self) -> Self {
+ self.packed.set_tag(ParamTag { constness: hir::Constness::NotConst, ..self.packed.tag() });
+ self
+ }
+
+ #[inline]
+ pub fn remap_constness_with(&mut self, mut constness: ty::BoundConstness) {
+ *self = self.with_constness(constness.and(self.constness()))
+ }
+
/// Returns a new parameter environment with the same clauses, but
/// which "reveals" the true results of projections in all cases
/// (even for associated types that are specializable). This is
/// will be normalized to their underlying types.
/// See PR #65989 and issue #65918 for more details
pub fn with_reveal_all_normalized(self, tcx: TyCtxt<'tcx>) -> Self {
- if self.packed.tag() == traits::Reveal::All {
+ if self.packed.tag().reveal == traits::Reveal::All {
return self;
}
- ParamEnv::new(tcx.normalize_opaque_types(self.caller_bounds()), Reveal::All)
+ ParamEnv::new(
+ tcx.normalize_opaque_types(self.caller_bounds()),
+ Reveal::All,
+ self.constness(),
+ )
}
/// Returns this same environment but with no caller bounds.
#[inline]
pub fn without_caller_bounds(self) -> Self {
- Self::new(List::empty(), self.reveal())
+ Self::new(List::empty(), self.reveal(), self.constness())
}
/// Creates a suitable environment in which to perform trait
}
}
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TypeFoldable)]
-pub struct ConstnessAnd<T> {
- pub constness: BoundConstness,
- pub value: T,
-}
-
// FIXME(ecstaticmorse): Audit all occurrences of `without_const().to_predicate(tcx)` to ensure that
// the constness of trait bounds is being propagated correctly.
-pub trait WithConstness: Sized {
- #[inline]
- fn with_constness(self, constness: BoundConstness) -> ConstnessAnd<Self> {
- ConstnessAnd { constness, value: self }
- }
-
+impl<'tcx> PolyTraitRef<'tcx> {
#[inline]
- fn with_const_if_const(self) -> ConstnessAnd<Self> {
- self.with_constness(BoundConstness::ConstIfConst)
+ pub fn with_constness(self, constness: BoundConstness) -> PolyTraitPredicate<'tcx> {
+ self.map_bound(|trait_ref| ty::TraitPredicate {
+ trait_ref,
+ constness,
+ polarity: ty::ImplPolarity::Positive,
+ })
}
-
#[inline]
- fn without_const(self) -> ConstnessAnd<Self> {
+ pub fn without_const(self) -> PolyTraitPredicate<'tcx> {
self.with_constness(BoundConstness::NotConst)
}
}
-impl<T> WithConstness for T {}
-
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TypeFoldable)]
pub struct ParamEnvAnd<'tcx, T> {
pub param_env: ParamEnv<'tcx>,
pub fn into_parts(self) -> (ParamEnv<'tcx>, T) {
(self.param_env, self.value)
}
+
+ #[inline]
+ pub fn without_const(mut self) -> Self {
+ self.param_env = self.param_env.without_const();
+ self
+ }
}
impl<'a, 'tcx, T> HashStable<StableHashingContext<'a>> for ParamEnvAnd<'tcx, T>
}
bitflags! {
- #[derive(HashStable)]
+ #[derive(HashStable, TyEncodable, TyDecodable)]
pub struct VariantFlags: u32 {
const NO_VARIANT_FLAGS = 0;
/// Indicates whether the field list of this variant is `#[non_exhaustive]`.
}
/// Definition of a variant -- a struct's fields or an enum variant.
-#[derive(Debug, HashStable)]
+#[derive(Debug, HashStable, TyEncodable, TyDecodable)]
pub struct VariantDef {
/// `DefId` that identifies the variant itself.
/// If this variant belongs to a struct or union, then this is a copy of its `DefId`.
Relative(u32),
}
-#[derive(Debug, HashStable)]
+#[derive(Debug, HashStable, TyEncodable, TyDecodable)]
pub struct FieldDef {
pub did: DefId,
#[stable_hasher(project(name))]
// the seed stored in `ReprOptions.layout_seed`
const RANDOMIZE_LAYOUT = 1 << 5;
// Any of these flags being set prevent field reordering optimisation.
- const IS_UNOPTIMISABLE = ReprFlags::IS_C.bits |
- ReprFlags::IS_SIMD.bits |
- ReprFlags::IS_LINEAR.bits;
+ const IS_UNOPTIMISABLE = ReprFlags::IS_C.bits
+ | ReprFlags::IS_SIMD.bits
+ | ReprFlags::IS_LINEAR.bits;
}
}
// Generate a deterministically-derived seed from the item's path hash
// to allow for cross-crate compilation to actually work
- let field_shuffle_seed = tcx.def_path_hash(did).0.to_smaller_hash();
+ let mut field_shuffle_seed = tcx.def_path_hash(did).0.to_smaller_hash();
+
+ // If the user defined a custom seed for layout randomization, xor the item's
+ // path hash with the user defined seed, this will allowing determinism while
+ // still allowing users to further randomize layout generation for e.g. fuzzing
+ if let Some(user_seed) = tcx.sess.opts.debugging_opts.layout_seed {
+ field_shuffle_seed ^= user_seed;
+ }
for attr in tcx.get_attrs(did).iter() {
for r in attr::find_repr_attrs(&tcx.sess, attr) {
impl<'tcx> FieldDef {
/// Returns the type of this field. The resulting type is not normalized. The `subst` is
- /// typically obtained via the second field of `TyKind::AdtDef`.
+ /// typically obtained via the second field of [`TyKind::Adt`].
pub fn ty(&self, tcx: TyCtxt<'tcx>, subst: SubstsRef<'tcx>) -> Ty<'tcx> {
tcx.type_of(self.did).subst(tcx, subst)
}
}
}
-/// Yields the parent function's `DefId` if `def_id` is an `impl Trait` definition.
-pub fn is_impl_trait_defn(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
- if let Some(def_id) = def_id.as_local() {
- if let Node::Item(item) = tcx.hir().get(tcx.hir().local_def_id_to_hir_id(def_id)) {
- if let hir::ItemKind::OpaqueTy(ref opaque_ty) = item.kind {
- return opaque_ty.impl_trait_fn;
- }
+/// Yields the parent function's `LocalDefId` if `def_id` is an `impl Trait` definition.
+pub fn is_impl_trait_defn(tcx: TyCtxt<'_>, def_id: DefId) -> Option<LocalDefId> {
+ let def_id = def_id.as_local()?;
+ if let Node::Item(item) = tcx.hir().get(tcx.hir().local_def_id_to_hir_id(def_id)) {
+ if let hir::ItemKind::OpaqueTy(ref opaque_ty) = item.kind {
+ return match opaque_ty.origin {
+ hir::OpaqueTyOrigin::FnReturn(parent) | hir::OpaqueTyOrigin::AsyncFn(parent) => {
+ Some(parent)
+ }
+ hir::OpaqueTyOrigin::TyAlias => None,
+ };
}
}
None