X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=compiler%2Frustc_middle%2Fsrc%2Fty%2Fmod.rs;h=a7833ab64310fc29513aac6f9c7eb015cc1f29ba;hb=f25cb83296d0e5d78036d6086b6342604243d940;hp=da9d51a29b18c45d79caa7a03597dff9118cd403;hpb=e820ecdba115e56d3d1cb0df169463a23a28fabd;p=rust.git diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index da9d51a29b1..a7833ab6431 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -48,7 +48,7 @@ pub use vtable::*; use std::fmt::Debug; -use std::hash::Hash; +use std::hash::{Hash, Hasher}; use std::ops::ControlFlow; use std::{fmt, str}; @@ -124,6 +124,7 @@ mod generics; mod impls_ty; mod instance; +mod layout_sanity_check; mod list; mod parameterized; mod rvalue_scopes; @@ -177,6 +178,11 @@ pub struct ResolverAstLowering { pub label_res_map: NodeMap, /// Resolutions for lifetimes. pub lifetimes_res_map: NodeMap, + /// Mapping from generics `def_id`s to TAIT generics `def_id`s. + /// For each captured lifetime (e.g., 'a), we create a new lifetime parameter that is a generic + /// defined on the TAIT, so we have type Foo<'a1> = ... and we establish a mapping in this + /// field from the original parameter 'a to the new parameter 'a1. + pub generics_def_id_map: Vec>, /// Lifetime parameters that lowering will have to introduce. pub extra_lifetime_params_map: NodeMap>, @@ -588,6 +594,29 @@ pub fn without_const(mut self, tcx: TyCtxt<'tcx>) -> Self { } self } + + /// Whether this projection can be soundly normalized. + /// + /// Wf predicates must not be normalized, as normalization + /// can remove required bounds which would cause us to + /// unsoundly accept some programs. See #91068. + #[inline] + pub fn allow_normalization(self) -> bool { + match self.kind().skip_binder() { + PredicateKind::WellFormed(_) => false, + PredicateKind::Trait(_) + | PredicateKind::RegionOutlives(_) + | PredicateKind::TypeOutlives(_) + | PredicateKind::Projection(_) + | PredicateKind::ObjectSafe(_) + | PredicateKind::ClosureKind(_, _, _) + | PredicateKind::Subtype(_) + | PredicateKind::Coerce(_) + | PredicateKind::ConstEvaluatable(_) + | PredicateKind::ConstEquate(_, _) + | PredicateKind::TypeWellFormedFromEnv(_) => true, + } + } } impl<'a, 'tcx> HashStable> for Predicate<'tcx> { @@ -1200,7 +1229,7 @@ pub struct BoundConst<'tcx> { pub ty: Ty<'tcx>, } -pub type PlaceholderConst<'tcx> = Placeholder>; +pub type PlaceholderConst<'tcx> = Placeholder; /// A `DefId` which, in case it is a const argument, is potentially bundled with /// the `DefId` of the generic parameter it instantiates. @@ -1704,6 +1733,59 @@ pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident { } } +impl PartialEq for VariantDef { + #[inline] + fn eq(&self, other: &Self) -> bool { + // There should be only one `VariantDef` for each `def_id`, therefore + // it is fine to implement `PartialEq` only based on `def_id`. + // + // Below, we exhaustively destructure `self` and `other` so that if the + // definition of `VariantDef` changes, a compile-error will be produced, + // reminding us to revisit this assumption. + + let Self { + def_id: lhs_def_id, + ctor_def_id: _, + name: _, + discr: _, + fields: _, + ctor_kind: _, + flags: _, + } = &self; + + let Self { + def_id: rhs_def_id, + ctor_def_id: _, + name: _, + discr: _, + fields: _, + ctor_kind: _, + flags: _, + } = other; + + lhs_def_id == rhs_def_id + } +} + +impl Eq for VariantDef {} + +impl Hash for VariantDef { + #[inline] + fn hash(&self, s: &mut H) { + // There should be only one `VariantDef` for each `def_id`, therefore + // it is fine to implement `Hash` only based on `def_id`. + // + // Below, we exhaustively destructure `self` so that if the definition + // of `VariantDef` changes, a compile-error will be produced, reminding + // us to revisit this assumption. + + let Self { def_id, ctor_def_id: _, name: _, discr: _, fields: _, ctor_kind: _, flags: _ } = + &self; + + def_id.hash(s) + } +} + #[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)] pub enum VariantDiscr { /// Explicit value for this variant, i.e., `X = 123`. @@ -1724,6 +1806,42 @@ pub struct FieldDef { pub vis: Visibility, } +impl PartialEq for FieldDef { + #[inline] + fn eq(&self, other: &Self) -> bool { + // There should be only one `FieldDef` for each `did`, therefore it is + // fine to implement `PartialEq` only based on `did`. + // + // Below, we exhaustively destructure `self` so that if the definition + // of `FieldDef` changes, a compile-error will be produced, reminding + // us to revisit this assumption. + + let Self { did: lhs_did, name: _, vis: _ } = &self; + + let Self { did: rhs_did, name: _, vis: _ } = other; + + lhs_did == rhs_did + } +} + +impl Eq for FieldDef {} + +impl Hash for FieldDef { + #[inline] + fn hash(&self, s: &mut H) { + // There should be only one `FieldDef` for each `did`, therefore it is + // fine to implement `Hash` only based on `did`. + // + // Below, we exhaustively destructure `self` so that if the definition + // of `FieldDef` changes, a compile-error will be produced, reminding + // us to revisit this assumption. + + let Self { did, name: _, vis: _ } = &self; + + did.hash(s) + } +} + bitflags! { #[derive(TyEncodable, TyDecodable, Default, HashStable)] pub struct ReprFlags: u8 { @@ -1945,7 +2063,7 @@ pub fn typeck_body(self, body: hir::BodyId) -> &'tcx TypeckResults<'tcx> { pub fn provided_trait_methods(self, id: DefId) -> impl 'tcx + Iterator { self.associated_items(id) .in_definition_order() - .filter(|item| item.kind == AssocKind::Fn && item.defaultness.has_value()) + .filter(move |item| item.kind == AssocKind::Fn && item.defaultness(self).has_value()) } /// Look up the name of a definition across crates. This does not look at HIR. @@ -2191,13 +2309,29 @@ pub fn trait_id_of_impl(self, def_id: DefId) -> Option { self.impl_trait_ref(def_id).map(|tr| tr.def_id) } + /// If the given `DefId` describes an item belonging to a trait, + /// returns the `DefId` of the trait that the trait item belongs to; + /// otherwise, returns `None`. + pub fn trait_of_item(self, def_id: DefId) -> Option { + if let DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy = self.def_kind(def_id) { + let parent = self.parent(def_id); + if let DefKind::Trait | DefKind::TraitAlias = self.def_kind(parent) { + return Some(parent); + } + } + None + } + /// If the given `DefId` describes a method belonging to an impl, returns the /// `DefId` of the impl that the method belongs to; otherwise, returns `None`. pub fn impl_of_method(self, def_id: DefId) -> Option { - self.opt_associated_item(def_id).and_then(|trait_item| match trait_item.container { - TraitContainer(_) => None, - ImplContainer(def_id) => Some(def_id), - }) + if let DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy = self.def_kind(def_id) { + let parent = self.parent(def_id); + if let DefKind::Impl = self.def_kind(parent) { + return Some(parent); + } + } + None } /// If the given `DefId` belongs to a trait that was automatically derived, returns `true`.