]> git.lizzy.rs Git - rust.git/commitdiff
rustc_target: move for_variant and field TyLayout methods to a trait.
authorIrina Popa <irinagpopa@gmail.com>
Wed, 7 Feb 2018 17:27:43 +0000 (19:27 +0200)
committerIrina Popa <irinagpopa@gmail.com>
Thu, 26 Apr 2018 13:50:29 +0000 (16:50 +0300)
src/librustc/ty/layout.rs
src/librustc_target/abi/mod.rs

index 069250bb05570a63d6f5dd11bf37778d423aa56d..f7ac25a0db09031388c008cb64bc46f2a98952cd 100644 (file)
@@ -19,7 +19,7 @@
 use std::fmt;
 use std::i128;
 use std::mem;
-use std::ops::{Deref, RangeInclusive};
+use std::ops::RangeInclusive;
 
 use ich::StableHashingContext;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
@@ -801,9 +801,9 @@ enum StructKind {
 
                     if let Some(i) = dataful_variant {
                         let count = (niche_variants.end - niche_variants.start + 1) as u128;
-                        for (field_index, field) in variants[i].iter().enumerate() {
+                        for (field_index, &field) in variants[i].iter().enumerate() {
                             let (offset, niche, niche_start) =
-                                match field.find_niche(self, count)? {
+                                match self.find_niche(field, count)? {
                                     Some(niche) => niche,
                                     None => continue
                                 };
@@ -1300,26 +1300,6 @@ pub fn same_size(self, other: SizeSkeleton) -> bool {
     }
 }
 
-/// The details of the layout of a type, alongside the type itself.
-/// Provides various type traversal APIs (e.g. recursing into fields).
-///
-/// Note that the details are NOT guaranteed to always be identical
-/// to those obtained from `layout_of(ty)`, as we need to produce
-/// layouts for which Rust types do not exist, such as enum variants
-/// or synthetic fields of enums (i.e. discriminants) and fat pointers.
-#[derive(Copy, Clone, Debug)]
-pub struct TyLayout<'tcx> {
-    pub ty: Ty<'tcx>,
-    details: &'tcx LayoutDetails
-}
-
-impl<'tcx> Deref for TyLayout<'tcx> {
-    type Target = &'tcx LayoutDetails;
-    fn deref(&self) -> &&'tcx LayoutDetails {
-        &self.details
-    }
-}
-
 pub trait HasTyCtxt<'tcx>: HasDataLayout {
     fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx>;
 }
@@ -1371,6 +1351,8 @@ fn map_same<F: FnOnce(T) -> T>(self, f: F) -> Self {
     }
 }
 
+pub type TyLayout<'tcx> = ::rustc_target::abi::TyLayout<'tcx, Ty<'tcx>>;
+
 impl<'a, 'tcx> LayoutOf for LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
     type Ty = Ty<'tcx>;
     type TyLayout = Result<TyLayout<'tcx>, LayoutError<'tcx>>;
@@ -1458,22 +1440,22 @@ pub fn layout_of(self, param_env_and_ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>)
     }
 }
 
-impl<'a, 'tcx> TyLayout<'tcx> {
-    pub fn for_variant<C>(&self, cx: C, variant_index: usize) -> Self
-        where C: LayoutOf<Ty = Ty<'tcx>> + HasTyCtxt<'tcx>,
-              C::TyLayout: MaybeResult<TyLayout<'tcx>>
-    {
-        let details = match self.variants {
-            Variants::Single { index } if index == variant_index => self.details,
+impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx> 
+    where C: LayoutOf<Ty = Ty<'tcx>> + HasTyCtxt<'tcx>,
+          C::TyLayout: MaybeResult<TyLayout<'tcx>>
+{
+    fn for_variant(this: TyLayout<'tcx>, cx: C, variant_index: usize) -> TyLayout<'tcx> {
+        let details = match this.variants {
+            Variants::Single { index } if index == variant_index => this.details,
 
             Variants::Single { index } => {
                 // Deny calling for_variant more than once for non-Single enums.
-                cx.layout_of(self.ty).map_same(|layout| {
+                cx.layout_of(this.ty).map_same(|layout| {
                     assert_eq!(layout.variants, Variants::Single { index });
                     layout
                 });
 
-                let fields = match self.ty.sty {
+                let fields = match this.ty.sty {
                     ty::TyAdt(def, _) => def.variants[variant_index].fields.len(),
                     _ => bug!()
                 };
@@ -1491,17 +1473,14 @@ pub fn for_variant<C>(&self, cx: C, variant_index: usize) -> Self
         assert_eq!(details.variants, Variants::Single { index: variant_index });
 
         TyLayout {
-            ty: self.ty,
+            ty: this.ty,
             details
         }
     }
 
-    pub fn field<C>(&self, cx: C, i: usize) -> C::TyLayout
-        where C: LayoutOf<Ty = Ty<'tcx>> + HasTyCtxt<'tcx>,
-              C::TyLayout: MaybeResult<TyLayout<'tcx>>
-    {
+    fn field(this: TyLayout<'tcx>, cx: C, i: usize) -> C::TyLayout {
         let tcx = cx.tcx();
-        cx.layout_of(match self.ty.sty {
+        cx.layout_of(match this.ty.sty {
             ty::TyBool |
             ty::TyChar |
             ty::TyInt(_) |
@@ -1513,7 +1492,7 @@ pub fn field<C>(&self, cx: C, i: usize) -> C::TyLayout
             ty::TyGeneratorWitness(..) |
             ty::TyForeign(..) |
             ty::TyDynamic(..) => {
-                bug!("TyLayout::field_type({:?}): not applicable", self)
+                bug!("TyLayout::field_type({:?}): not applicable", this)
             }
 
             // Potentially-fat pointers.
@@ -1527,13 +1506,13 @@ pub fn field<C>(&self, cx: C, i: usize) -> C::TyLayout
                 // as the `Abi` or `FieldPlacement` is checked by users.
                 if i == 0 {
                     let nil = tcx.mk_nil();
-                    let ptr_ty = if self.ty.is_unsafe_ptr() {
+                    let ptr_ty = if this.ty.is_unsafe_ptr() {
                         tcx.mk_mut_ptr(nil)
                     } else {
                         tcx.mk_mut_ref(tcx.types.re_static, nil)
                     };
                     return cx.layout_of(ptr_ty).map_same(|mut ptr_layout| {
-                        ptr_layout.ty = self.ty;
+                        ptr_layout.ty = this.ty;
                         ptr_layout
                     });
                 }
@@ -1546,7 +1525,7 @@ pub fn field<C>(&self, cx: C, i: usize) -> C::TyLayout
                         // the correct number of vtables slots.
                         tcx.mk_imm_ref(tcx.types.re_static, tcx.mk_nil())
                     }
-                    _ => bug!("TyLayout::field_type({:?}): not applicable", self)
+                    _ => bug!("TyLayout::field_type({:?}): not applicable", this)
                 }
             }
 
@@ -1568,12 +1547,12 @@ pub fn field<C>(&self, cx: C, i: usize) -> C::TyLayout
 
             // SIMD vector types.
             ty::TyAdt(def, ..) if def.repr.simd() => {
-                self.ty.simd_type(tcx)
+                this.ty.simd_type(tcx)
             }
 
             // ADTs.
             ty::TyAdt(def, substs) => {
-                match self.variants {
+                match this.variants {
                     Variants::Single { index } => {
                         def.variants[index].fields[i].ty(tcx, substs)
                     }
@@ -1593,45 +1572,25 @@ pub fn field<C>(&self, cx: C, i: usize) -> C::TyLayout
 
             ty::TyProjection(_) | ty::TyAnon(..) | ty::TyParam(_) |
             ty::TyInfer(_) | ty::TyError => {
-                bug!("TyLayout::field_type: unexpected type `{}`", self.ty)
+                bug!("TyLayout::field_type: unexpected type `{}`", this.ty)
             }
         })
     }
+}
 
-    /// Returns true if the layout corresponds to an unsized type.
-    pub fn is_unsized(&self) -> bool {
-        self.abi.is_unsized()
-    }
-
-    /// Returns true if the type is a ZST and not unsized.
-    pub fn is_zst(&self) -> bool {
-        match self.abi {
-            Abi::Uninhabited => true,
-            Abi::Scalar(_) |
-            Abi::ScalarPair(..) |
-            Abi::Vector { .. } => false,
-            Abi::Aggregate { sized } => sized && self.size.bytes() == 0
-        }
-    }
-
-    pub fn size_and_align(&self) -> (Size, Align) {
-        (self.size, self.align)
-    }
-
+impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
     /// Find the offset of a niche leaf field, starting from
     /// the given type and recursing through aggregates, which
     /// has at least `count` consecutive invalid values.
     /// The tuple is `(offset, scalar, niche_value)`.
     // FIXME(eddyb) traverse already optimized enums.
-    fn find_niche<C>(&self, cx: C, count: u128)
+    fn find_niche(self, layout: TyLayout<'tcx>, count: u128)
         -> Result<Option<(Size, Scalar, u128)>, LayoutError<'tcx>>
-        where C: LayoutOf<Ty = Ty<'tcx>, TyLayout = Result<Self, LayoutError<'tcx>>> +
-                 HasTyCtxt<'tcx>
     {
         let scalar_component = |scalar: &Scalar, offset| {
             let Scalar { value, valid_range: ref v } = *scalar;
 
-            let bits = value.size(cx).bits();
+            let bits = value.size(self).bits();
             assert!(bits <= 128);
             let max_value = !0u128 >> (128 - bits);
 
@@ -1658,17 +1617,17 @@ fn find_niche<C>(&self, cx: C, count: u128)
         // Locals variables which live across yields are stored
         // in the generator type as fields. These may be uninitialized
         // so we don't look for niches there.
-        if let ty::TyGenerator(..) = self.ty.sty {
+        if let ty::TyGenerator(..) = layout.ty.sty {
             return Ok(None);
         }
 
-        match self.abi {
+        match layout.abi {
             Abi::Scalar(ref scalar) => {
                 return Ok(scalar_component(scalar, Size::from_bytes(0)));
             }
             Abi::ScalarPair(ref a, ref b) => {
                 return Ok(scalar_component(a, Size::from_bytes(0)).or_else(|| {
-                    scalar_component(b, a.value.size(cx).abi_align(b.value.align(cx)))
+                    scalar_component(b, a.value.size(self).abi_align(b.value.align(self)))
                 }));
             }
             Abi::Vector { ref element, .. } => {
@@ -1678,22 +1637,22 @@ fn find_niche<C>(&self, cx: C, count: u128)
         }
 
         // Perhaps one of the fields is non-zero, let's recurse and find out.
-        if let FieldPlacement::Union(_) = self.fields {
+        if let FieldPlacement::Union(_) = layout.fields {
             // Only Rust enums have safe-to-inspect fields
             // (a discriminant), other unions are unsafe.
-            if let Variants::Single { .. } = self.variants {
+            if let Variants::Single { .. } = layout.variants {
                 return Ok(None);
             }
         }
-        if let FieldPlacement::Array { .. } = self.fields {
-            if self.fields.count() > 0 {
-                return self.field(cx, 0)?.find_niche(cx, count);
+        if let FieldPlacement::Array { .. } = layout.fields {
+            if layout.fields.count() > 0 {
+                return self.find_niche(layout.field(self, 0)?, count);
             }
         }
-        for i in 0..self.fields.count() {
-            let r = self.field(cx, i)?.find_niche(cx, count)?;
+        for i in 0..layout.fields.count() {
+            let r = self.find_niche(layout.field(self, i)?, count)?;
             if let Some((offset, scalar, niche_value)) = r {
-                let offset = self.fields.offset(i) + offset;
+                let offset = layout.fields.offset(i) + offset;
                 return Ok(Some((offset, scalar, niche_value)));
             }
         }
index b0a53445659ef402b057a3f5233b4dcf0776ee92..cc3fd3e0cdd1e0f429a593510054314c77dafc88 100644 (file)
@@ -14,7 +14,7 @@
 use spec::Target;
 
 use std::cmp;
-use std::ops::{Add, Sub, Mul, AddAssign, RangeInclusive};
+use std::ops::{Add, Deref, Sub, Mul, AddAssign, RangeInclusive};
 
 pub mod call;
 
@@ -757,9 +757,67 @@ pub fn uninhabited(field_count: usize) -> Self {
     }
 }
 
+/// The details of the layout of a type, alongside the type itself.
+/// Provides various type traversal APIs (e.g. recursing into fields).
+///
+/// Note that the details are NOT guaranteed to always be identical
+/// to those obtained from `layout_of(ty)`, as we need to produce
+/// layouts for which Rust types do not exist, such as enum variants
+/// or synthetic fields of enums (i.e. discriminants) and fat pointers.
+#[derive(Copy, Clone, Debug)]
+pub struct TyLayout<'a, Ty> {
+    pub ty: Ty,
+    pub details: &'a LayoutDetails
+}
+
+impl<'a, Ty> Deref for TyLayout<'a, Ty> {
+    type Target = &'a LayoutDetails;
+    fn deref(&self) -> &&'a LayoutDetails {
+        &self.details
+    }
+}
+
 pub trait LayoutOf {
     type Ty;
     type TyLayout;
 
     fn layout_of(self, ty: Self::Ty) -> Self::TyLayout;
 }
+
+pub trait TyLayoutMethods<'a, C: LayoutOf>: Sized {
+    fn for_variant(this: TyLayout<'a, Self>, cx: C, variant_index: usize) -> TyLayout<'a, Self>;
+    fn field(this: TyLayout<'a, Self>, cx: C, i: usize) -> C::TyLayout;
+}
+
+impl<'a, Ty> TyLayout<'a, Ty> {
+    pub fn for_variant<C>(self, cx: C, variant_index: usize) -> Self
+    where Ty: TyLayoutMethods<'a, C>, C: LayoutOf {
+        Ty::for_variant(self, cx, variant_index)
+    }
+    pub fn field<C>(self, cx: C, i: usize) -> C::TyLayout 
+    where Ty: TyLayoutMethods<'a, C>, C: LayoutOf {
+        Ty::field(self, cx, i)
+    }
+}
+
+impl<'a, Ty> TyLayout<'a, Ty> {
+    /// Returns true if the layout corresponds to an unsized type.
+    pub fn is_unsized(&self) -> bool {
+        self.abi.is_unsized()
+    }
+
+    /// Returns true if the type is a ZST and not unsized.
+    pub fn is_zst(&self) -> bool {
+        match self.abi {
+            Abi::Uninhabited => true,
+            Abi::Scalar(_) |
+            Abi::ScalarPair(..) |
+            Abi::Vector { .. } => false,
+            Abi::Aggregate { sized } => sized && self.size.bytes() == 0
+        }
+    }
+
+    pub fn size_and_align(&self) -> (Size, Align) {
+        (self.size, self.align)
+    }
+}
\ No newline at end of file