diff options
| author | Irina Popa <irinagpopa@gmail.com> | 2018-02-07 19:27:43 +0200 |
|---|---|---|
| committer | Irina Popa <irinagpopa@gmail.com> | 2018-04-26 16:50:29 +0300 |
| commit | c45dda92feedaaed22bd9d74ec24164dc206da44 (patch) | |
| tree | 3d10cd4a0c13984316ea890f08891b0e95ad8541 /src/librustc_target | |
| parent | 7a5147616b16b78a65d80f13b85c3010131d3b7a (diff) | |
| download | rust-c45dda92feedaaed22bd9d74ec24164dc206da44.tar.gz rust-c45dda92feedaaed22bd9d74ec24164dc206da44.zip | |
rustc_target: move for_variant and field TyLayout methods to a trait.
Diffstat (limited to 'src/librustc_target')
| -rw-r--r-- | src/librustc_target/abi/mod.rs | 60 |
1 files changed, 59 insertions, 1 deletions
diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index b0a53445659..cc3fd3e0cdd 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -14,7 +14,7 @@ pub use self::Primitive::*; 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 @@ impl LayoutDetails { } } +/// 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 |
