]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc/ty/mod.rs
Rollup merge of #55834 - ogoffart:union-abi, r=eddyb
[rust.git] / src / librustc / ty / mod.rs
index ef9b3e3efab275f3421c3ea5eb9bcede113efa92..a474065b5cd55fe1911c8a1de888eb53ddf52ac3 100644 (file)
@@ -32,6 +32,7 @@
 use session::CrateDisambiguator;
 use traits::{self, Reveal};
 use ty;
+use ty::layout::VariantIdx;
 use ty::subst::{Subst, Substs};
 use ty::util::{IntTypeExt, Discr};
 use ty::walk::TypeWalker;
@@ -57,7 +58,7 @@
 use syntax_pos::{DUMMY_SP, Span};
 
 use smallvec;
-use rustc_data_structures::indexed_vec::Idx;
+use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult,
                                            HashStable};
 
@@ -514,6 +515,10 @@ pub struct TyS<'tcx> {
     outer_exclusive_binder: ty::DebruijnIndex,
 }
 
+// `TyS` is used a lot. Make sure it doesn't unintentionally get bigger.
+#[cfg(target_arch = "x86_64")]
+static_assert!(MEM_SIZE_OF_TY_S: ::std::mem::size_of::<TyS<'_>>() == 32);
+
 impl<'tcx> Ord for TyS<'tcx> {
     fn cmp(&self, other: &TyS<'tcx>) -> Ordering {
         self.sty.cmp(&other.sty)
@@ -1785,7 +1790,7 @@ pub enum VariantDiscr {
     /// For efficiency reasons, the distance from the
     /// last `Explicit` discriminant is being stored,
     /// or `0` for the first variant, if it has none.
-    Relative(usize),
+    Relative(u32),
 }
 
 #[derive(Debug)]
@@ -1801,7 +1806,7 @@ pub struct FieldDef {
 /// table.
 pub struct AdtDef {
     pub did: DefId,
-    pub variants: Vec<VariantDef>,
+    pub variants: IndexVec<self::layout::VariantIdx, VariantDef>,
     flags: AdtFlags,
     pub repr: ReprOptions,
 }
@@ -1993,13 +1998,19 @@ pub fn inhibit_enum_layout_opt(&self) -> bool {
     pub fn inhibit_struct_field_reordering_opt(&self) -> bool {
         !(self.flags & ReprFlags::IS_UNOPTIMISABLE).is_empty() || (self.pack == 1)
     }
+
+    /// Returns true if this `#[repr()]` should inhibit union abi optimisations
+    pub fn inhibit_union_abi_opt(&self) -> bool {
+        self.c()
+    }
+
 }
 
 impl<'a, 'gcx, 'tcx> AdtDef {
     fn new(tcx: TyCtxt<'_, '_, '_>,
            did: DefId,
            kind: AdtKind,
-           variants: Vec<VariantDef>,
+           variants: IndexVec<VariantIdx, VariantDef>,
            repr: ReprOptions) -> Self {
         debug!("AdtDef::new({:?}, {:?}, {:?}, {:?})", did, kind, variants, repr);
         let mut flags = AdtFlags::NO_ADT_FLAGS;
@@ -2121,11 +2132,11 @@ pub fn has_dtor(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> bool {
     /// Asserts this is a struct or union and returns its unique variant.
     pub fn non_enum_variant(&self) -> &VariantDef {
         assert!(self.is_struct() || self.is_union());
-        &self.variants[0]
+        &self.variants[VariantIdx::new(0)]
     }
 
     #[inline]
-    pub fn predicates(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> GenericPredicates<'gcx> {
+    pub fn predicates(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Lrc<GenericPredicates<'gcx>> {
         tcx.predicates_of(self.did)
     }
 
@@ -2148,11 +2159,12 @@ pub fn variant_with_id(&self, vid: DefId) -> &VariantDef {
             .expect("variant_with_id: unknown variant")
     }
 
-    pub fn variant_index_with_id(&self, vid: DefId) -> usize {
+    pub fn variant_index_with_id(&self, vid: DefId) -> VariantIdx {
         self.variants
-            .iter()
-            .position(|v| v.did == vid)
+            .iter_enumerated()
+            .find(|(_, v)| v.did == vid)
             .expect("variant_index_with_id: unknown variant")
+            .0
     }
 
     pub fn variant_of_def(&self, def: Def) -> &VariantDef {
@@ -2216,11 +2228,11 @@ pub fn eval_explicit_discr(
     pub fn discriminants(
         &'a self,
         tcx: TyCtxt<'a, 'gcx, 'tcx>,
-    ) -> impl Iterator<Item=Discr<'tcx>> + Captures<'gcx> + 'a {
+    ) -> impl Iterator<Item=(VariantIdx, Discr<'tcx>)> + Captures<'gcx> + 'a {
         let repr_type = self.repr.discr_type();
         let initial = repr_type.initial_discriminant(tcx.global_tcx());
         let mut prev_discr = None::<Discr<'tcx>>;
-        self.variants.iter().map(move |v| {
+        self.variants.iter_enumerated().map(move |(i, v)| {
             let mut discr = prev_discr.map_or(initial, |d| d.wrap_incr(tcx));
             if let VariantDiscr::Explicit(expr_did) = v.discr {
                 if let Some(new_discr) = self.eval_explicit_discr(tcx, expr_did) {
@@ -2229,7 +2241,7 @@ pub fn discriminants(
             }
             prev_discr = Some(discr);
 
-            discr
+            (i, discr)
         })
     }
 
@@ -2240,7 +2252,7 @@ pub fn discriminants(
     /// assuming there are no constant-evaluation errors there.
     pub fn discriminant_for_variant(&self,
                                     tcx: TyCtxt<'a, 'gcx, 'tcx>,
-                                    variant_index: usize)
+                                    variant_index: VariantIdx)
                                     -> Discr<'tcx> {
         let (val, offset) = self.discriminant_def_for_variant(variant_index);
         let explicit_value = val
@@ -2254,12 +2266,12 @@ pub fn discriminant_for_variant(&self,
     /// inferred discriminant directly
     pub fn discriminant_def_for_variant(
         &self,
-        variant_index: usize,
-    ) -> (Option<DefId>, usize) {
-        let mut explicit_index = variant_index;
+        variant_index: VariantIdx,
+    ) -> (Option<DefId>, u32) {
+        let mut explicit_index = variant_index.as_u32();
         let expr_did;
         loop {
-            match self.variants[explicit_index].discr {
+            match self.variants[VariantIdx::from_u32(explicit_index)].discr {
                 ty::VariantDiscr::Relative(0) => {
                     expr_did = None;
                     break;
@@ -2273,7 +2285,7 @@ pub fn discriminant_def_for_variant(
                 }
             }
         }
-        (expr_did, variant_index - explicit_index)
+        (expr_did, variant_index.as_u32() - explicit_index)
     }
 
     pub fn destructor(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Option<Destructor> {
@@ -2367,8 +2379,8 @@ fn sized_constraint_for_ty(&self,
                     def_id: sized_trait,
                     substs: tcx.mk_substs_trait(ty, &[])
                 }).to_predicate();
-                let predicates = tcx.predicates_of(self.did).predicates;
-                if predicates.into_iter().any(|(p, _)| p == sized_predicate) {
+                let predicates = &tcx.predicates_of(self.did).predicates;
+                if predicates.iter().any(|(p, _)| *p == sized_predicate) {
                     vec![]
                 } else {
                     vec![ty]
@@ -2394,7 +2406,7 @@ pub fn ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, subst: &Substs<'tcx>) -> Ty<'tcx>
 
 /// Represents the various closure traits in the Rust language. This
 /// will determine the type of the environment (`self`, in the
-/// desuaring) argument that the closure expects.
+/// desugaring) argument that the closure expects.
 ///
 /// You can get the environment type of a closure using
 /// `tcx.closure_env_ty()`.
@@ -2674,10 +2686,17 @@ pub fn find_field_index(self, ident: Ident, variant: &VariantDef) -> Option<usiz
     pub fn associated_items(
         self,
         def_id: DefId,
-    ) -> impl Iterator<Item = AssociatedItem> + 'a {
-        let def_ids = self.associated_item_def_ids(def_id);
-        Box::new((0..def_ids.len()).map(move |i| self.associated_item(def_ids[i])))
-            as Box<dyn Iterator<Item = AssociatedItem> + 'a>
+    ) -> AssociatedItemsIterator<'a, 'gcx, 'tcx> {
+        // Ideally, we would use `-> impl Iterator` here, but it falls
+        // afoul of the conservative "capture [restrictions]" we put
+        // in place, so we use a hand-written iterator.
+        //
+        // [restrictions]: https://github.com/rust-lang/rust/issues/34511#issuecomment-373423999
+        AssociatedItemsIterator {
+            tcx: self,
+            def_ids: self.associated_item_def_ids(def_id),
+            next_index: 0,
+        }
     }
 
     /// Returns `true` if the impls are the same polarity and the trait either
@@ -2874,6 +2893,22 @@ pub fn adjust_ident(self, mut ident: Ident, scope: DefId, block: NodeId) -> (Ide
     }
 }
 
+pub struct AssociatedItemsIterator<'a, 'gcx: 'tcx, 'tcx: 'a> {
+    tcx: TyCtxt<'a, 'gcx, 'tcx>,
+    def_ids: Lrc<Vec<DefId>>,
+    next_index: usize,
+}
+
+impl Iterator for AssociatedItemsIterator<'_, '_, '_> {
+    type Item = AssociatedItem;
+
+    fn next(&mut self) -> Option<AssociatedItem> {
+        let def_id = self.def_ids.get(self.next_index)?;
+        self.next_index += 1;
+        Some(self.tcx.associated_item(*def_id))
+    }
+}
+
 impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     pub fn with_freevars<T, F>(self, fid: NodeId, f: F) -> T where
         F: FnOnce(&[hir::Freevar]) -> T,