about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEduard-Mihai Burtescu <edy.burt@gmail.com>2017-09-16 23:12:39 +0300
committerEduard-Mihai Burtescu <edy.burt@gmail.com>2017-11-19 02:14:30 +0200
commit33a205b56fbe5039d3f64743334b634be8dc4f0c (patch)
tree94c41cab6df4d1a5e8eb427bd5dd554c3ce86e0b
parent658ebfc788d1926b6eaaeb38da52a13a424e1242 (diff)
downloadrust-33a205b56fbe5039d3f64743334b634be8dc4f0c.tar.gz
rust-33a205b56fbe5039d3f64743334b634be8dc4f0c.zip
rustc: collapse Layout::CEnum into Layout::General.
-rw-r--r--src/librustc/lib.rs3
-rw-r--r--src/librustc/ty/layout.rs168
-rw-r--r--src/librustc_trans/adt.rs11
-rw-r--r--src/librustc_trans/debuginfo/metadata.rs9
-rw-r--r--src/librustc_trans/lib.rs1
-rw-r--r--src/librustc_trans/mir/constant.rs17
-rw-r--r--src/librustc_trans/mir/lvalue.rs5
-rw-r--r--src/librustc_trans/mir/rvalue.rs6
-rw-r--r--src/librustc_trans/type_of.rs1
9 files changed, 86 insertions, 135 deletions
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index 5e9019c92c5..44039817e72 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -47,10 +47,11 @@
 #![feature(core_intrinsics)]
 #![feature(drain_filter)]
 #![feature(i128_type)]
-#![feature(match_default_bindings)]
+#![feature(inclusive_range)]
 #![feature(inclusive_range_syntax)]
 #![cfg_attr(windows, feature(libc))]
 #![feature(macro_vis_matcher)]
+#![feature(match_default_bindings)]
 #![feature(never_type)]
 #![feature(nonzero)]
 #![feature(quote)]
diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs
index 18c3a270787..5775fc957b5 100644
--- a/src/librustc/ty/layout.rs
+++ b/src/librustc/ty/layout.rs
@@ -25,7 +25,7 @@ use std::fmt;
 use std::i64;
 use std::iter;
 use std::mem;
-use std::ops::{Deref, Add, Sub, Mul, AddAssign};
+use std::ops::{Deref, Add, Sub, Mul, AddAssign, RangeInclusive};
 
 use ich::StableHashingContext;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
@@ -841,9 +841,9 @@ impl<'a, 'tcx> Struct {
             (&Scalar(Pointer), _) if !layout.ty.is_unsafe_ptr() => {
                 Ok(Some((Size::from_bytes(0), Pointer)))
             }
-            (&CEnum { discr, .. }, &ty::TyAdt(def, _)) => {
+            (&General { discr, .. }, &ty::TyAdt(def, _)) => {
                 if def.discriminants(tcx).all(|d| d.to_u128_unchecked() != 0) {
-                    Ok(Some((Size::from_bytes(0), discr)))
+                    Ok(Some((layout.fields.offset(0), discr)))
                 } else {
                     Ok(None)
                 }
@@ -1095,18 +1095,6 @@ pub enum Layout {
 
     // Remaining variants are all ADTs such as structs, enums or tuples.
 
-    /// C-like enums; basically an integer.
-    CEnum {
-        discr: Primitive,
-        /// Inclusive discriminant range.
-        /// If min > max, it represents min...u64::MAX followed by 0...max.
-        // FIXME(eddyb) always use the shortest range, e.g. by finding
-        // the largest space between two consecutive discriminants and
-        // taking everything else as the (shortest) discriminant range.
-        min: u64,
-        max: u64
-    },
-
     /// Single-case enums, and structs/tuples.
     Univariant(Struct),
 
@@ -1118,6 +1106,12 @@ pub enum Layout {
     /// at a non-0 offset, after where the discriminant would go.
     General {
         discr: Primitive,
+        /// Inclusive wrap-around range of discriminant values, that is,
+        /// if min > max, it represents min..=u64::MAX followed by 0..=max.
+        // FIXME(eddyb) always use the shortest range, e.g. by finding
+        // the largest space between two consecutive discriminants and
+        // taking everything else as the (shortest) discriminant range.
+        discr_range: RangeInclusive<u64>,
         variants: Vec<Struct>,
         size: Size,
         align: Align,
@@ -1240,7 +1234,6 @@ impl<'a, 'tcx> Layout {
                     FieldPlacement::union(def.struct_variant().fields.len())
                 }
 
-                CEnum { .. } |
                 General { .. } => FieldPlacement::union(1),
 
                 NullablePointer { ref discr_offset, .. } => {
@@ -1250,19 +1243,17 @@ impl<'a, 'tcx> Layout {
                 }
             };
             let abi = match *layout {
-                Scalar(value) |
-                CEnum { discr: value, .. } => Abi::Scalar(value),
-
+                Scalar(value) => Abi::Scalar(value),
                 Vector { .. } => Abi::Vector,
 
                 Array { .. } |
                 FatPointer { .. } |
                 Univariant(_) |
-                UntaggedUnion(_) |
-                General { .. } => Abi::Aggregate,
+                UntaggedUnion(_) => Abi::Aggregate,
 
-                NullablePointer { discr, discr_offset, .. } => {
-                    if discr_offset.bytes() == 0 && discr.size(cx) == layout.size(cx) {
+                General { discr, .. } |
+                NullablePointer { discr, .. } => {
+                    if fields.offset(0).bytes() == 0 && discr.size(cx) == layout.size(cx) {
                         Abi::Scalar(discr)
                     } else {
                         Abi::Aggregate
@@ -1431,7 +1422,14 @@ impl<'a, 'tcx> Layout {
 
             // ADTs.
             ty::TyAdt(def, substs) => {
-                if def.variants.is_empty() {
+                // Cache the field layouts.
+                let variants = def.variants.iter().map(|v| {
+                    v.fields.iter().map(|field| {
+                        cx.layout_of(field.ty(tcx, substs))
+                    }).collect::<Result<Vec<_>, _>>()
+                }).collect::<Result<Vec<_>, _>>()?;
+
+                if variants.is_empty() {
                     // Uninhabitable; represent as unit
                     // (Typechecking will reject discriminant-sizing attrs.)
 
@@ -1439,74 +1437,39 @@ impl<'a, 'tcx> Layout {
                           &def.repr, StructKind::AlwaysSizedUnivariant, ty)?));
                 }
 
-                if def.is_enum() && def.variants.iter().all(|v| v.fields.is_empty()) {
-                    // All bodies empty -> intlike
-                    let (mut min, mut max) = (i64::max_value(), i64::min_value());
-                    for discr in def.discriminants(tcx) {
-                        let x = discr.to_u128_unchecked() as i64;
-                        if x < min { min = x; }
-                        if x > max { max = x; }
-                    }
-
-                    // FIXME: should handle i128? signed-value based impl is weird and hard to
-                    // grok.
-                    let (discr, signed) = Integer::repr_discr(tcx, ty, &def.repr, min, max);
-                    return success(CEnum {
-                        discr: Int(discr, signed),
-                        // FIXME: should be u128?
-                        min: min as u64,
-                        max: max as u64
-                    });
-                }
-
-                if !def.is_enum() || (def.variants.len() == 1 &&
-                                      !def.repr.inhibit_enum_layout_opt()) {
+                if !def.is_enum() || (variants.len() == 1 &&
+                                      !def.repr.inhibit_enum_layout_opt() &&
+                                      !variants[0].is_empty()) {
                     // Struct, or union, or univariant enum equivalent to a struct.
                     // (Typechecking will reject discriminant-sizing attrs.)
 
-                    let kind = if def.is_enum() || def.variants[0].fields.len() == 0{
+                    let kind = if def.is_enum() || variants[0].len() == 0 {
                         StructKind::AlwaysSizedUnivariant
                     } else {
                         let param_env = tcx.param_env(def.did);
-                        let fields = &def.variants[0].fields;
-                        let last_field = &fields[fields.len()-1];
+                        let last_field = def.variants[0].fields.last().unwrap();
                         let always_sized = tcx.type_of(last_field.did)
                           .is_sized(tcx, param_env, DUMMY_SP);
                         if !always_sized { StructKind::MaybeUnsizedUnivariant }
                         else { StructKind::AlwaysSizedUnivariant }
                     };
 
-                    let fields = def.variants[0].fields.iter().map(|field| {
-                        cx.layout_of(field.ty(tcx, substs))
-                    }).collect::<Result<Vec<_>, _>>()?;
                     let layout = if def.is_union() {
                         let mut un = Union::new(dl, &def.repr);
-                        un.extend(dl, fields.iter().map(|&f| Ok(f.layout)), ty)?;
+                        un.extend(dl, variants[0].iter().map(|&f| Ok(f.layout)), ty)?;
                         UntaggedUnion(un)
                     } else {
-                        Univariant(Struct::new(dl, &fields, &def.repr, kind, ty)?)
+                        Univariant(Struct::new(dl, &variants[0], &def.repr, kind, ty)?)
                     };
                     return success(layout);
                 }
 
-                // Since there's at least one
-                // non-empty body, explicit discriminants should have
-                // been rejected by a checker before this point.
-                for (i, v) in def.variants.iter().enumerate() {
-                    if v.discr != ty::VariantDiscr::Relative(i) {
-                        bug!("non-C-like enum {} with specified discriminants",
-                            tcx.item_path_str(def.did));
-                    }
-                }
+                let no_explicit_discriminants = def.variants.iter().enumerate()
+                    .all(|(i, v)| v.discr == ty::VariantDiscr::Relative(i));
 
-                // Cache the substituted and normalized variant field types.
-                let variants = def.variants.iter().map(|v| {
-                    v.fields.iter().map(|field| {
-                        cx.layout_of(field.ty(tcx, substs))
-                    }).collect::<Result<Vec<_>, _>>()
-                }).collect::<Result<Vec<_>, _>>()?;
-
-                if variants.len() == 2 && !def.repr.inhibit_enum_layout_opt() {
+                if variants.len() == 2 &&
+                   !def.repr.inhibit_enum_layout_opt() &&
+                   no_explicit_discriminants {
                     // Nullable pointer optimization
                     let st0 = Struct::new(dl, &variants[0],
                         &def.repr, StructKind::AlwaysSizedUnivariant, ty)?;
@@ -1554,16 +1517,23 @@ impl<'a, 'tcx> Layout {
                     }
                 }
 
-                // The general case.
-                let discr_max = (variants.len() - 1) as i64;
-                assert!(discr_max >= 0);
-                let (min_ity, _) = Integer::repr_discr(tcx, ty, &def.repr, 0, discr_max);
+                let (mut min, mut max) = (i64::max_value(), i64::min_value());
+                for discr in def.discriminants(tcx) {
+                    let x = discr.to_u128_unchecked() as i64;
+                    if x < min { min = x; }
+                    if x > max { max = x; }
+                }
+                // FIXME: should handle i128? signed-value based impl is weird and hard to
+                // grok.
+                let (min_ity, signed) = Integer::repr_discr(tcx, ty, &def.repr, min, max);
+
                 let mut align = dl.aggregate_align;
                 let mut primitive_align = dl.aggregate_align;
                 let mut size = Size::from_bytes(0);
 
                 // We're interested in the smallest alignment, so start large.
                 let mut start_align = Align::from_bytes(256, 256).unwrap();
+                assert_eq!(Integer::for_abi_align(dl, start_align), None);
 
                 // Create the set of structs that represent each variant.
                 let mut variants = variants.into_iter().map(|fields| {
@@ -1644,7 +1614,10 @@ impl<'a, 'tcx> Layout {
                 }
 
                 General {
-                    discr: Int(ity, false),
+                    discr: Int(ity, signed),
+
+                    // FIXME: should be u128?
+                    discr_range: (min as u64)..=(max as u64),
                     variants,
                     size,
                     align,
@@ -1680,7 +1653,7 @@ impl<'a, 'tcx> Layout {
     pub fn is_unsized(&self) -> bool {
         match *self {
             Scalar(_) | Vector {..} | FatPointer {..} |
-            CEnum {..} | UntaggedUnion {..} | General {..} |
+            UntaggedUnion {..} | General {..} |
             NullablePointer {..} => false,
 
             Array { sized, .. } |
@@ -1720,7 +1693,6 @@ impl<'a, 'tcx> Layout {
                  metadata.size(dl)).abi_align(self.align(dl))
             }
 
-            CEnum { discr, .. } => discr.size(dl),
             General { size, .. } => size,
             UntaggedUnion(ref un) => un.stride(),
 
@@ -1754,7 +1726,6 @@ impl<'a, 'tcx> Layout {
                 Pointer.align(dl).max(metadata.align(dl))
             }
 
-            CEnum { discr, .. } => discr.align(dl),
             Array { align, .. } | General { align, .. } => align,
             UntaggedUnion(ref un) => un.align,
 
@@ -1856,16 +1827,6 @@ impl<'a, 'tcx> Layout {
             }
         };
 
-        let build_primitive_info = |name: ast::Name, value: Primitive| {
-            session::VariantInfo {
-                name: Some(name.to_string()),
-                kind: session::SizeKind::Exact,
-                align: value.align(tcx).abi(),
-                size: value.size(tcx).bytes(),
-                fields: vec![],
-            }
-        };
-
         let build_variant_info = |n: Option<ast::Name>,
                                   flds: &[(ast::Name, Ty<'tcx>)],
                                   s: &Struct| {
@@ -1959,17 +1920,6 @@ impl<'a, 'tcx> Layout {
                 record(adt_kind.into(), None, Vec::new());
             }
 
-            Layout::CEnum { discr, .. } => {
-                debug!("print-type-size t: `{:?}` adt c-like enum", ty);
-                let variant_infos: Vec<_> =
-                    adt_def.variants.iter()
-                                    .map(|variant_def| {
-                                        build_primitive_info(variant_def.name, discr)
-                                    })
-                                    .collect();
-                record(adt_kind.into(), Some(discr.size(tcx)), variant_infos);
-            }
-
             // other cases provide little interesting (i.e. adjustable
             // via representation tweaks) size info beyond total size.
             Layout::Scalar(_) |
@@ -2284,6 +2234,7 @@ impl<'a, 'tcx> FullLayout<'tcx> {
         FullLayout {
             variant_index: Some(variant_index),
             fields,
+            abi: Abi::Aggregate,
             ..*self
         }
     }
@@ -2356,7 +2307,6 @@ impl<'a, 'tcx> FullLayout<'tcx> {
                     match self.variant_index {
                         None => match *self.layout {
                             // Discriminant field for enums (where applicable).
-                            CEnum { discr, .. } |
                             General { discr, .. } |
                             NullablePointer { discr, .. } => {
                                 return [discr.to_ty(tcx)][i];
@@ -2416,19 +2366,23 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for Layout
             FatPointer(ref metadata) => {
                 metadata.hash_stable(hcx, hasher);
             }
-            CEnum { discr, min, max } => {
-                discr.hash_stable(hcx, hasher);
-                min.hash_stable(hcx, hasher);
-                max.hash_stable(hcx, hasher);
-            }
             Univariant(ref variant) => {
                 variant.hash_stable(hcx, hasher);
             }
             UntaggedUnion(ref un) => {
                 un.hash_stable(hcx, hasher);
             }
-            General { discr, ref variants, size, align, primitive_align } => {
+            General {
+                discr,
+                discr_range: RangeInclusive { start, end },
+                ref variants,
+                size,
+                align,
+                primitive_align
+            } => {
                 discr.hash_stable(hcx, hasher);
+                start.hash_stable(hcx, hasher);
+                end.hash_stable(hcx, hasher);
                 variants.hash_stable(hcx, hasher);
                 size.hash_stable(hcx, hasher);
                 align.hash_stable(hcx, hasher);
diff --git a/src/librustc_trans/adt.rs b/src/librustc_trans/adt.rs
index de42676a90d..e1a65f37eff 100644
--- a/src/librustc_trans/adt.rs
+++ b/src/librustc_trans/adt.rs
@@ -69,7 +69,7 @@ pub fn finish_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
     let l = cx.layout_of(t);
     debug!("finish_type_of: {} with layout {:#?}", t, l);
     match *l {
-        layout::CEnum { .. } | layout::General { .. } | layout::UntaggedUnion { .. } => { }
+        layout::General { .. } | layout::UntaggedUnion { .. } => { }
         layout::Univariant { ..} | layout::NullablePointer { .. } => {
             if let layout::Abi::Scalar(_) = l.abi {
                 return;
@@ -101,13 +101,12 @@ fn generic_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                              t: Ty<'tcx>,
                              name: Option<&str>) -> Type {
     let l = cx.layout_of(t);
-    debug!("adt::generic_type_of t: {:?} name: {:?}", t, name);
+    debug!("adt::generic_type_of {:#?} name: {:?}", l, name);
+    if let layout::Abi::Scalar(value) = l.abi {
+        return cx.llvm_type_of(value.to_ty(cx.tcx()));
+    }
     match *l {
-        layout::CEnum { discr, .. } => cx.llvm_type_of(discr.to_ty(cx.tcx())),
         layout::NullablePointer { nndiscr, ref nonnull, .. } => {
-            if let layout::Abi::Scalar(_) = l.abi {
-                return cx.llvm_type_of(l.field(cx, 0).ty);
-            }
             match name {
                 None => {
                     Type::struct_(cx, &struct_llfields(cx, l.for_variant(nndiscr as usize),
diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs
index aad6f3446ee..16bca343dd0 100644
--- a/src/librustc_trans/debuginfo/metadata.rs
+++ b/src/librustc_trans/debuginfo/metadata.rs
@@ -1282,7 +1282,6 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
                     }
                 ]
             },
-            layout::CEnum { .. } => span_bug!(self.span, "This should be unreachable."),
             ref l @ _ => bug!("Not an enum layout: {:#?}", l)
         }
     }
@@ -1491,14 +1490,16 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
     let type_rep = cx.layout_of(enum_type);
 
     let discriminant_type_metadata = match *type_rep {
-        layout::CEnum { discr, .. } => {
-            return FinalMetadata(discriminant_type_metadata(discr))
-        },
         layout::NullablePointer { .. } | layout::Univariant { .. } => None,
         layout::General { discr, .. } => Some(discriminant_type_metadata(discr)),
         ref l @ _ => bug!("Not an enum layout: {:#?}", l)
     };
 
+    match (type_rep.abi, discriminant_type_metadata) {
+        (layout::Abi::Scalar(_), Some(discr)) => return FinalMetadata(discr),
+        _ => {}
+    }
+
     let (enum_type_size, enum_type_align) = type_rep.size_and_align(cx);
 
     let enum_name = CString::new(enum_name).unwrap();
diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs
index 2776125bd82..dd33012e900 100644
--- a/src/librustc_trans/lib.rs
+++ b/src/librustc_trans/lib.rs
@@ -25,6 +25,7 @@
 #![allow(unused_attributes)]
 #![feature(i128_type)]
 #![feature(i128)]
+#![feature(inclusive_range)]
 #![feature(libc)]
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs
index c677352c278..c8d8199a05e 100644
--- a/src/librustc_trans/mir/constant.rs
+++ b/src/librustc_trans/mir/constant.rs
@@ -1091,7 +1091,7 @@ fn trans_const_adt<'a, 'tcx>(
         _ => 0,
     };
     match *l {
-        layout::CEnum { .. } => {
+        layout::General { ref variants, .. } => {
             let discr = match *kind {
                 mir::AggregateKind::Adt(adt_def, _, _, _) => {
                     adt_def.discriminant_for_variant(ccx.tcx(), variant_index)
@@ -1099,15 +1099,14 @@ fn trans_const_adt<'a, 'tcx>(
                 },
                 _ => 0,
             };
-            assert_eq!(vals.len(), 0);
-            Const::new(C_int(ccx.llvm_type_of(t), discr as i64), t)
-        }
-        layout::General { ref variants, .. } => {
             let discr_ty = l.field(ccx, 0).ty;
-            let variant = &variants[variant_index];
-            let lldiscr = C_int(ccx.llvm_type_of(discr_ty), variant_index as i64);
-            build_const_struct(ccx, l, &variant, vals,
-                Some(Const::new(lldiscr, discr_ty)))
+            let discr = Const::new(C_int(ccx.llvm_type_of(discr_ty), discr as i64),
+                                   discr_ty);
+            if let layout::Abi::Scalar(_) = l.abi {
+                discr
+            } else {
+                build_const_struct(ccx, l, &variants[variant_index], vals, Some(discr))
+            }
         }
         layout::UntaggedUnion(ref un) => {
             assert_eq!(variant_index, 0);
diff --git a/src/librustc_trans/mir/lvalue.rs b/src/librustc_trans/mir/lvalue.rs
index 883751d25a0..f39e3cb7812 100644
--- a/src/librustc_trans/mir/lvalue.rs
+++ b/src/librustc_trans/mir/lvalue.rs
@@ -367,8 +367,7 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
             _ => bug!("discriminant not scalar: {:#?}", discr_layout)
         };
         let (min, max) = match *l {
-            layout::CEnum { min, max, .. } => (min, max),
-            layout::General { ref variants, .. } => (0, variants.len() as u64 - 1),
+            layout::General { ref discr_range, .. } => (discr_range.start, discr_range.end),
             _ => (0, u64::max_value()),
         };
         let max_next = max.wrapping_add(1);
@@ -394,7 +393,6 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
             }
         };
         match *l {
-            layout::CEnum { .. } |
             layout::General { .. } => {
                 let signed = match discr_scalar {
                     layout::Int(_, signed) => signed,
@@ -419,7 +417,6 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
             .discriminant_for_variant(bcx.tcx(), variant_index)
             .to_u128_unchecked() as u64;
         match *l {
-            layout::CEnum { .. } |
             layout::General { .. } => {
                 let ptr = self.project_field(bcx, 0);
                 bcx.store(C_int(bcx.ccx.llvm_type_of(ptr.ty.to_ty(bcx.tcx())), to as i64),
diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs
index b931d9a2549..b7143f23691 100644
--- a/src/librustc_trans/mir/rvalue.rs
+++ b/src/librustc_trans/mir/rvalue.rs
@@ -277,8 +277,8 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
                         let llval = operand.immediate();
                         let l = bcx.ccx.layout_of(operand.ty);
 
-                        if let Layout::CEnum { min, max, .. } = *l {
-                            if max > min {
+                        if let Layout::General { ref discr_range, .. } = *l {
+                            if discr_range.end > discr_range.start {
                                 // We want `table[e as usize]` to not
                                 // have bound checks, and this is the most
                                 // convenient place to put the `assume`.
@@ -286,7 +286,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
                                 base::call_assume(&bcx, bcx.icmp(
                                     llvm::IntULE,
                                     llval,
-                                    C_uint(ll_t_in, max)
+                                    C_uint(ll_t_in, discr_range.end)
                                 ));
                             }
                         }
diff --git a/src/librustc_trans/type_of.rs b/src/librustc_trans/type_of.rs
index 264f711de8f..eca6057db36 100644
--- a/src/librustc_trans/type_of.rs
+++ b/src/librustc_trans/type_of.rs
@@ -242,7 +242,6 @@ impl<'tcx> LayoutLlvmExt for FullLayout<'tcx> {
         }
         match **self {
             Layout::Scalar { .. } |
-            Layout::CEnum { .. } |
             Layout::UntaggedUnion { .. } => {
                 bug!("FullLayout::llvm_field_index({:?}): not applicable", self)
             }