]> git.lizzy.rs Git - rust.git/blob - src/librustc/ty/layout.rs
Auto merge of #41433 - estebank:constructor, r=michaelwoerister
[rust.git] / src / librustc / ty / layout.rs
1 // Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 pub use self::Integer::*;
12 pub use self::Layout::*;
13 pub use self::Primitive::*;
14
15 use infer::InferCtxt;
16 use session::Session;
17 use traits;
18 use ty::{self, Ty, TyCtxt, TypeFoldable, ReprOptions, ReprFlags};
19
20 use syntax::ast::{FloatTy, IntTy, UintTy};
21 use syntax::attr;
22 use syntax_pos::DUMMY_SP;
23
24 use std::cmp;
25 use std::fmt;
26 use std::i64;
27 use std::iter;
28 use std::ops::Deref;
29
30 /// Parsed [Data layout](http://llvm.org/docs/LangRef.html#data-layout)
31 /// for a target, which contains everything needed to compute layouts.
32 pub struct TargetDataLayout {
33     pub endian: Endian,
34     pub i1_align: Align,
35     pub i8_align: Align,
36     pub i16_align: Align,
37     pub i32_align: Align,
38     pub i64_align: Align,
39     pub i128_align: Align,
40     pub f32_align: Align,
41     pub f64_align: Align,
42     pub pointer_size: Size,
43     pub pointer_align: Align,
44     pub aggregate_align: Align,
45
46     /// Alignments for vector types.
47     pub vector_align: Vec<(Size, Align)>
48 }
49
50 impl Default for TargetDataLayout {
51     /// Creates an instance of `TargetDataLayout`.
52     fn default() -> TargetDataLayout {
53         TargetDataLayout {
54             endian: Endian::Big,
55             i1_align: Align::from_bits(8, 8).unwrap(),
56             i8_align: Align::from_bits(8, 8).unwrap(),
57             i16_align: Align::from_bits(16, 16).unwrap(),
58             i32_align: Align::from_bits(32, 32).unwrap(),
59             i64_align: Align::from_bits(32, 64).unwrap(),
60             i128_align: Align::from_bits(32, 64).unwrap(),
61             f32_align: Align::from_bits(32, 32).unwrap(),
62             f64_align: Align::from_bits(64, 64).unwrap(),
63             pointer_size: Size::from_bits(64),
64             pointer_align: Align::from_bits(64, 64).unwrap(),
65             aggregate_align: Align::from_bits(0, 64).unwrap(),
66             vector_align: vec![
67                 (Size::from_bits(64), Align::from_bits(64, 64).unwrap()),
68                 (Size::from_bits(128), Align::from_bits(128, 128).unwrap())
69             ]
70         }
71     }
72 }
73
74 impl TargetDataLayout {
75     pub fn parse(sess: &Session) -> TargetDataLayout {
76         // Parse a bit count from a string.
77         let parse_bits = |s: &str, kind: &str, cause: &str| {
78             s.parse::<u64>().unwrap_or_else(|err| {
79                 sess.err(&format!("invalid {} `{}` for `{}` in \"data-layout\": {}",
80                                   kind, s, cause, err));
81                 0
82             })
83         };
84
85         // Parse a size string.
86         let size = |s: &str, cause: &str| {
87             Size::from_bits(parse_bits(s, "size", cause))
88         };
89
90         // Parse an alignment string.
91         let align = |s: &[&str], cause: &str| {
92             if s.is_empty() {
93                 sess.err(&format!("missing alignment for `{}` in \"data-layout\"", cause));
94             }
95             let abi = parse_bits(s[0], "alignment", cause);
96             let pref = s.get(1).map_or(abi, |pref| parse_bits(pref, "alignment", cause));
97             Align::from_bits(abi, pref).unwrap_or_else(|err| {
98                 sess.err(&format!("invalid alignment for `{}` in \"data-layout\": {}",
99                                   cause, err));
100                 Align::from_bits(8, 8).unwrap()
101             })
102         };
103
104         let mut dl = TargetDataLayout::default();
105         let mut i128_align_src = 64;
106         for spec in sess.target.target.data_layout.split("-") {
107             match &spec.split(":").collect::<Vec<_>>()[..] {
108                 &["e"] => dl.endian = Endian::Little,
109                 &["E"] => dl.endian = Endian::Big,
110                 &["a", ref a..] => dl.aggregate_align = align(a, "a"),
111                 &["f32", ref a..] => dl.f32_align = align(a, "f32"),
112                 &["f64", ref a..] => dl.f64_align = align(a, "f64"),
113                 &[p @ "p", s, ref a..] | &[p @ "p0", s, ref a..] => {
114                     dl.pointer_size = size(s, p);
115                     dl.pointer_align = align(a, p);
116                 }
117                 &[s, ref a..] if s.starts_with("i") => {
118                     let bits = match s[1..].parse::<u64>() {
119                         Ok(bits) => bits,
120                         Err(_) => {
121                             size(&s[1..], "i"); // For the user error.
122                             continue;
123                         }
124                     };
125                     let a = align(a, s);
126                     match bits {
127                         1 => dl.i1_align = a,
128                         8 => dl.i8_align = a,
129                         16 => dl.i16_align = a,
130                         32 => dl.i32_align = a,
131                         64 => dl.i64_align = a,
132                         _ => {}
133                     }
134                     if bits >= i128_align_src && bits <= 128 {
135                         // Default alignment for i128 is decided by taking the alignment of
136                         // largest-sized i{64...128}.
137                         i128_align_src = bits;
138                         dl.i128_align = a;
139                     }
140                 }
141                 &[s, ref a..] if s.starts_with("v") => {
142                     let v_size = size(&s[1..], "v");
143                     let a = align(a, s);
144                     if let Some(v) = dl.vector_align.iter_mut().find(|v| v.0 == v_size) {
145                         v.1 = a;
146                         continue;
147                     }
148                     // No existing entry, add a new one.
149                     dl.vector_align.push((v_size, a));
150                 }
151                 _ => {} // Ignore everything else.
152             }
153         }
154
155         // Perform consistency checks against the Target information.
156         let endian_str = match dl.endian {
157             Endian::Little => "little",
158             Endian::Big => "big"
159         };
160         if endian_str != sess.target.target.target_endian {
161             sess.err(&format!("inconsistent target specification: \"data-layout\" claims \
162                                architecture is {}-endian, while \"target-endian\" is `{}`",
163                               endian_str, sess.target.target.target_endian));
164         }
165
166         if dl.pointer_size.bits().to_string() != sess.target.target.target_pointer_width {
167             sess.err(&format!("inconsistent target specification: \"data-layout\" claims \
168                                pointers are {}-bit, while \"target-pointer-width\" is `{}`",
169                               dl.pointer_size.bits(), sess.target.target.target_pointer_width));
170         }
171
172         dl
173     }
174
175     /// Return exclusive upper bound on object size.
176     ///
177     /// The theoretical maximum object size is defined as the maximum positive `isize` value.
178     /// This ensures that the `offset` semantics remain well-defined by allowing it to correctly
179     /// index every address within an object along with one byte past the end, along with allowing
180     /// `isize` to store the difference between any two pointers into an object.
181     ///
182     /// The upper bound on 64-bit currently needs to be lower because LLVM uses a 64-bit integer
183     /// to represent object size in bits. It would need to be 1 << 61 to account for this, but is
184     /// currently conservatively bounded to 1 << 47 as that is enough to cover the current usable
185     /// address space on 64-bit ARMv8 and x86_64.
186     pub fn obj_size_bound(&self) -> u64 {
187         match self.pointer_size.bits() {
188             16 => 1 << 15,
189             32 => 1 << 31,
190             64 => 1 << 47,
191             bits => bug!("obj_size_bound: unknown pointer bit size {}", bits)
192         }
193     }
194
195     pub fn ptr_sized_integer(&self) -> Integer {
196         match self.pointer_size.bits() {
197             16 => I16,
198             32 => I32,
199             64 => I64,
200             bits => bug!("ptr_sized_integer: unknown pointer bit size {}", bits)
201         }
202     }
203 }
204
205 pub trait HasDataLayout: Copy {
206     fn data_layout(&self) -> &TargetDataLayout;
207 }
208
209 impl<'a> HasDataLayout for &'a TargetDataLayout {
210     fn data_layout(&self) -> &TargetDataLayout {
211         self
212     }
213 }
214
215 /// Endianness of the target, which must match cfg(target-endian).
216 #[derive(Copy, Clone)]
217 pub enum Endian {
218     Little,
219     Big
220 }
221
222 /// Size of a type in bytes.
223 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
224 pub struct Size {
225     raw: u64
226 }
227
228 impl Size {
229     pub fn from_bits(bits: u64) -> Size {
230         Size::from_bytes((bits + 7) / 8)
231     }
232
233     pub fn from_bytes(bytes: u64) -> Size {
234         if bytes >= (1 << 61) {
235             bug!("Size::from_bytes: {} bytes in bits doesn't fit in u64", bytes)
236         }
237         Size {
238             raw: bytes
239         }
240     }
241
242     pub fn bytes(self) -> u64 {
243         self.raw
244     }
245
246     pub fn bits(self) -> u64 {
247         self.bytes() * 8
248     }
249
250     pub fn abi_align(self, align: Align) -> Size {
251         let mask = align.abi() - 1;
252         Size::from_bytes((self.bytes() + mask) & !mask)
253     }
254
255     pub fn checked_add<C: HasDataLayout>(self, offset: Size, cx: C) -> Option<Size> {
256         let dl = cx.data_layout();
257
258         // Each Size is less than dl.obj_size_bound(), so the sum is
259         // also less than 1 << 62 (and therefore can't overflow).
260         let bytes = self.bytes() + offset.bytes();
261
262         if bytes < dl.obj_size_bound() {
263             Some(Size::from_bytes(bytes))
264         } else {
265             None
266         }
267     }
268
269     pub fn checked_mul<C: HasDataLayout>(self, count: u64, cx: C) -> Option<Size> {
270         let dl = cx.data_layout();
271
272         // Each Size is less than dl.obj_size_bound(), so the sum is
273         // also less than 1 << 62 (and therefore can't overflow).
274         match self.bytes().checked_mul(count) {
275             Some(bytes) if bytes < dl.obj_size_bound() => {
276                 Some(Size::from_bytes(bytes))
277             }
278             _ => None
279         }
280     }
281 }
282
283 /// Alignment of a type in bytes, both ABI-mandated and preferred.
284 /// Since alignments are always powers of 2, we can pack both in one byte,
285 /// giving each a nibble (4 bits) for a maximum alignment of 2<sup>15</sup> = 32768.
286 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
287 pub struct Align {
288     raw: u8
289 }
290
291 impl Align {
292     pub fn from_bits(abi: u64, pref: u64) -> Result<Align, String> {
293         Align::from_bytes((abi + 7) / 8, (pref + 7) / 8)
294     }
295
296     pub fn from_bytes(abi: u64, pref: u64) -> Result<Align, String> {
297         let pack = |align: u64| {
298             // Treat an alignment of 0 bytes like 1-byte alignment.
299             if align == 0 {
300                 return Ok(0);
301             }
302
303             let mut bytes = align;
304             let mut pow: u8 = 0;
305             while (bytes & 1) == 0 {
306                 pow += 1;
307                 bytes >>= 1;
308             }
309             if bytes != 1 {
310                 Err(format!("`{}` is not a power of 2", align))
311             } else if pow > 0x0f {
312                 Err(format!("`{}` is too large", align))
313             } else {
314                 Ok(pow)
315             }
316         };
317
318         Ok(Align {
319             raw: pack(abi)? | (pack(pref)? << 4)
320         })
321     }
322
323     pub fn abi(self) -> u64 {
324         1 << (self.raw & 0xf)
325     }
326
327     pub fn pref(self) -> u64 {
328         1 << (self.raw >> 4)
329     }
330
331     pub fn min(self, other: Align) -> Align {
332         let abi = cmp::min(self.raw & 0x0f, other.raw & 0x0f);
333         let pref = cmp::min(self.raw & 0xf0, other.raw & 0xf0);
334         Align {
335             raw: abi | pref
336         }
337     }
338
339     pub fn max(self, other: Align) -> Align {
340         let abi = cmp::max(self.raw & 0x0f, other.raw & 0x0f);
341         let pref = cmp::max(self.raw & 0xf0, other.raw & 0xf0);
342         Align {
343             raw: abi | pref
344         }
345     }
346 }
347
348 /// Integers, also used for enum discriminants.
349 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
350 pub enum Integer {
351     I1,
352     I8,
353     I16,
354     I32,
355     I64,
356     I128,
357 }
358
359 impl Integer {
360     pub fn size(&self) -> Size {
361         match *self {
362             I1 => Size::from_bits(1),
363             I8 => Size::from_bytes(1),
364             I16 => Size::from_bytes(2),
365             I32 => Size::from_bytes(4),
366             I64  => Size::from_bytes(8),
367             I128  => Size::from_bytes(16),
368         }
369     }
370
371     pub fn align<C: HasDataLayout>(&self, cx: C) -> Align {
372         let dl = cx.data_layout();
373
374         match *self {
375             I1 => dl.i1_align,
376             I8 => dl.i8_align,
377             I16 => dl.i16_align,
378             I32 => dl.i32_align,
379             I64 => dl.i64_align,
380             I128 => dl.i128_align,
381         }
382     }
383
384     pub fn to_ty<'a, 'tcx>(&self, tcx: &ty::TyCtxt<'a, 'tcx, 'tcx>,
385                            signed: bool) -> Ty<'tcx> {
386         match (*self, signed) {
387             (I1, false) => tcx.types.u8,
388             (I8, false) => tcx.types.u8,
389             (I16, false) => tcx.types.u16,
390             (I32, false) => tcx.types.u32,
391             (I64, false) => tcx.types.u64,
392             (I128, false) => tcx.types.u128,
393             (I1, true) => tcx.types.i8,
394             (I8, true) => tcx.types.i8,
395             (I16, true) => tcx.types.i16,
396             (I32, true) => tcx.types.i32,
397             (I64, true) => tcx.types.i64,
398             (I128, true) => tcx.types.i128,
399         }
400     }
401
402     /// Find the smallest Integer type which can represent the signed value.
403     pub fn fit_signed(x: i64) -> Integer {
404         match x {
405             -0x0000_0000_0000_0001...0x0000_0000_0000_0000 => I1,
406             -0x0000_0000_0000_0080...0x0000_0000_0000_007f => I8,
407             -0x0000_0000_0000_8000...0x0000_0000_0000_7fff => I16,
408             -0x0000_0000_8000_0000...0x0000_0000_7fff_ffff => I32,
409             -0x8000_0000_0000_0000...0x7fff_ffff_ffff_ffff => I64,
410             _ => I128
411         }
412     }
413
414     /// Find the smallest Integer type which can represent the unsigned value.
415     pub fn fit_unsigned(x: u64) -> Integer {
416         match x {
417             0...0x0000_0000_0000_0001 => I1,
418             0...0x0000_0000_0000_00ff => I8,
419             0...0x0000_0000_0000_ffff => I16,
420             0...0x0000_0000_ffff_ffff => I32,
421             0...0xffff_ffff_ffff_ffff => I64,
422             _ => I128,
423         }
424     }
425
426     /// Find the smallest integer with the given alignment.
427     pub fn for_abi_align<C: HasDataLayout>(cx: C, align: Align) -> Option<Integer> {
428         let dl = cx.data_layout();
429
430         let wanted = align.abi();
431         for &candidate in &[I8, I16, I32, I64] {
432             let ty = Int(candidate);
433             if wanted == ty.align(dl).abi() && wanted == ty.size(dl).bytes() {
434                 return Some(candidate);
435             }
436         }
437         None
438     }
439
440     /// Get the Integer type from an attr::IntType.
441     pub fn from_attr<C: HasDataLayout>(cx: C, ity: attr::IntType) -> Integer {
442         let dl = cx.data_layout();
443
444         match ity {
445             attr::SignedInt(IntTy::I8) | attr::UnsignedInt(UintTy::U8) => I8,
446             attr::SignedInt(IntTy::I16) | attr::UnsignedInt(UintTy::U16) => I16,
447             attr::SignedInt(IntTy::I32) | attr::UnsignedInt(UintTy::U32) => I32,
448             attr::SignedInt(IntTy::I64) | attr::UnsignedInt(UintTy::U64) => I64,
449             attr::SignedInt(IntTy::I128) | attr::UnsignedInt(UintTy::U128) => I128,
450             attr::SignedInt(IntTy::Is) | attr::UnsignedInt(UintTy::Us) => {
451                 dl.ptr_sized_integer()
452             }
453         }
454     }
455
456     /// Find the appropriate Integer type and signedness for the given
457     /// signed discriminant range and #[repr] attribute.
458     /// N.B.: u64 values above i64::MAX will be treated as signed, but
459     /// that shouldn't affect anything, other than maybe debuginfo.
460     fn repr_discr(tcx: TyCtxt, ty: Ty, repr: &ReprOptions, min: i64, max: i64)
461                       -> (Integer, bool) {
462         // Theoretically, negative values could be larger in unsigned representation
463         // than the unsigned representation of the signed minimum. However, if there
464         // are any negative values, the only valid unsigned representation is u64
465         // which can fit all i64 values, so the result remains unaffected.
466         let unsigned_fit = Integer::fit_unsigned(cmp::max(min as u64, max as u64));
467         let signed_fit = cmp::max(Integer::fit_signed(min), Integer::fit_signed(max));
468
469         let mut min_from_extern = None;
470         let min_default = I8;
471
472         if let Some(ity) = repr.int {
473             let discr = Integer::from_attr(tcx, ity);
474             let fit = if ity.is_signed() { signed_fit } else { unsigned_fit };
475             if discr < fit {
476                 bug!("Integer::repr_discr: `#[repr]` hint too small for \
477                   discriminant range of enum `{}", ty)
478             }
479             return (discr, ity.is_signed());
480         }
481
482         if repr.c() {
483             match &tcx.sess.target.target.arch[..] {
484                 // WARNING: the ARM EABI has two variants; the one corresponding
485                 // to `at_least == I32` appears to be used on Linux and NetBSD,
486                 // but some systems may use the variant corresponding to no
487                 // lower bound.  However, we don't run on those yet...?
488                 "arm" => min_from_extern = Some(I32),
489                 _ => min_from_extern = Some(I32),
490             }
491         }
492
493         let at_least = min_from_extern.unwrap_or(min_default);
494
495         // If there are no negative values, we can use the unsigned fit.
496         if min >= 0 {
497             (cmp::max(unsigned_fit, at_least), false)
498         } else {
499             (cmp::max(signed_fit, at_least), true)
500         }
501     }
502 }
503
504 /// Fundamental unit of memory access and layout.
505 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
506 pub enum Primitive {
507     Int(Integer),
508     F32,
509     F64,
510     Pointer
511 }
512
513 impl Primitive {
514     pub fn size<C: HasDataLayout>(self, cx: C) -> Size {
515         let dl = cx.data_layout();
516
517         match self {
518             Int(I1) | Int(I8) => Size::from_bits(8),
519             Int(I16) => Size::from_bits(16),
520             Int(I32) | F32 => Size::from_bits(32),
521             Int(I64) | F64 => Size::from_bits(64),
522             Int(I128) => Size::from_bits(128),
523             Pointer => dl.pointer_size
524         }
525     }
526
527     pub fn align<C: HasDataLayout>(self, cx: C) -> Align {
528         let dl = cx.data_layout();
529
530         match self {
531             Int(I1) => dl.i1_align,
532             Int(I8) => dl.i8_align,
533             Int(I16) => dl.i16_align,
534             Int(I32) => dl.i32_align,
535             Int(I64) => dl.i64_align,
536             Int(I128) => dl.i128_align,
537             F32 => dl.f32_align,
538             F64 => dl.f64_align,
539             Pointer => dl.pointer_align
540         }
541     }
542 }
543
544 /// Path through fields of nested structures.
545 // FIXME(eddyb) use small vector optimization for the common case.
546 pub type FieldPath = Vec<u32>;
547
548 /// A structure, a product type in ADT terms.
549 #[derive(PartialEq, Eq, Hash, Debug)]
550 pub struct Struct {
551     /// Maximum alignment of fields and repr alignment.
552     pub align: Align,
553
554     /// Primitive alignment of fields without repr alignment.
555     pub primitive_align: Align,
556
557     /// If true, no alignment padding is used.
558     pub packed: bool,
559
560     /// If true, the size is exact, otherwise it's only a lower bound.
561     pub sized: bool,
562
563     /// Offsets for the first byte of each field, ordered to match the source definition order.
564     /// This vector does not go in increasing order.
565     /// FIXME(eddyb) use small vector optimization for the common case.
566     pub offsets: Vec<Size>,
567
568     /// Maps source order field indices to memory order indices, depending how fields were permuted.
569     /// FIXME (camlorn) also consider small vector  optimization here.
570     pub memory_index: Vec<u32>,
571
572     pub min_size: Size,
573 }
574
575 // Info required to optimize struct layout.
576 #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug)]
577 enum StructKind {
578     // A tuple, closure, or univariant which cannot be coerced to unsized.
579     AlwaysSizedUnivariant,
580     // A univariant, the last field of which may be coerced to unsized.
581     MaybeUnsizedUnivariant,
582     // A univariant, but part of an enum.
583     EnumVariant,
584 }
585
586 impl<'a, 'gcx, 'tcx> Struct {
587     fn new(dl: &TargetDataLayout, fields: &Vec<&'a Layout>,
588                   repr: &ReprOptions, kind: StructKind,
589                   scapegoat: Ty<'gcx>) -> Result<Struct, LayoutError<'gcx>> {
590         if repr.packed() && repr.align > 0 {
591             bug!("Struct cannot be packed and aligned");
592         }
593
594         let align = if repr.packed() {
595             dl.i8_align
596         } else {
597             dl.aggregate_align
598         };
599
600         let mut ret = Struct {
601             align: align,
602             primitive_align: align,
603             packed: repr.packed(),
604             sized: true,
605             offsets: vec![],
606             memory_index: vec![],
607             min_size: Size::from_bytes(0),
608         };
609
610         // Anything with repr(C) or repr(packed) doesn't optimize.
611         // Neither do  1-member and 2-member structs.
612         // In addition, code in trans assume that 2-element structs can become pairs.
613         // It's easier to just short-circuit here.
614         let can_optimize = (fields.len() > 2 || StructKind::EnumVariant == kind)
615             && (repr.flags & ReprFlags::IS_UNOPTIMISABLE).is_empty();
616
617         let (optimize, sort_ascending) = match kind {
618             StructKind::AlwaysSizedUnivariant => (can_optimize, false),
619             StructKind::MaybeUnsizedUnivariant => (can_optimize, false),
620             StructKind::EnumVariant => {
621                 assert!(fields.len() >= 1, "Enum variants must have discriminants.");
622                 (can_optimize && fields[0].size(dl).bytes() == 1, true)
623             }
624         };
625
626         ret.offsets = vec![Size::from_bytes(0); fields.len()];
627         let mut inverse_memory_index: Vec<u32> = (0..fields.len() as u32).collect();
628
629         if optimize {
630             let start = if let StructKind::EnumVariant = kind { 1 } else { 0 };
631             let end = if let StructKind::MaybeUnsizedUnivariant = kind {
632                 fields.len() - 1
633             } else {
634                 fields.len()
635             };
636             if end > start {
637                 let optimizing  = &mut inverse_memory_index[start..end];
638                 if sort_ascending {
639                     optimizing.sort_by_key(|&x| fields[x as usize].align(dl).abi());
640                 } else {
641                     optimizing.sort_by(| &a, &b | {
642                         let a = fields[a as usize].align(dl).abi();
643                         let b = fields[b as usize].align(dl).abi();
644                         b.cmp(&a)
645                     });
646                 }
647             }
648         }
649
650         // inverse_memory_index holds field indices by increasing memory offset.
651         // That is, if field 5 has offset 0, the first element of inverse_memory_index is 5.
652         // We now write field offsets to the corresponding offset slot;
653         // field 5 with offset 0 puts 0 in offsets[5].
654         // At the bottom of this function, we use inverse_memory_index to produce memory_index.
655
656         if let StructKind::EnumVariant = kind {
657             assert_eq!(inverse_memory_index[0], 0,
658               "Enum variant discriminants must have the lowest offset.");
659         }
660
661         let mut offset = Size::from_bytes(0);
662
663         for i in inverse_memory_index.iter() {
664             let field = fields[*i as usize];
665             if !ret.sized {
666                 bug!("Struct::new: field #{} of `{}` comes after unsized field",
667                      ret.offsets.len(), scapegoat);
668             }
669
670             if field.is_unsized() {
671                 ret.sized = false;
672             }
673
674             // Invariant: offset < dl.obj_size_bound() <= 1<<61
675             if !ret.packed {
676                 let align = field.align(dl);
677                 let primitive_align = field.primitive_align(dl);
678                 ret.align = ret.align.max(align);
679                 ret.primitive_align = ret.primitive_align.max(primitive_align);
680                 offset = offset.abi_align(align);
681             }
682
683             debug!("Struct::new offset: {:?} field: {:?} {:?}", offset, field, field.size(dl));
684             ret.offsets[*i as usize] = offset;
685
686             offset = offset.checked_add(field.size(dl), dl)
687                            .map_or(Err(LayoutError::SizeOverflow(scapegoat)), Ok)?;
688         }
689
690         if repr.align > 0 {
691             let repr_align = repr.align as u64;
692             ret.align = ret.align.max(Align::from_bytes(repr_align, repr_align).unwrap());
693             debug!("Struct::new repr_align: {:?}", repr_align);
694         }
695
696         debug!("Struct::new min_size: {:?}", offset);
697         ret.min_size = offset;
698
699         // As stated above, inverse_memory_index holds field indices by increasing offset.
700         // This makes it an already-sorted view of the offsets vec.
701         // To invert it, consider:
702         // If field 5 has offset 0, offsets[0] is 5, and memory_index[5] should be 0.
703         // Field 5 would be the first element, so memory_index is i:
704         // Note: if we didn't optimize, it's already right.
705
706         if optimize {
707             ret.memory_index = vec![0; inverse_memory_index.len()];
708
709             for i in 0..inverse_memory_index.len() {
710                 ret.memory_index[inverse_memory_index[i] as usize]  = i as u32;
711             }
712         } else {
713             ret.memory_index = inverse_memory_index;
714         }
715
716         Ok(ret)
717     }
718
719     /// Get the size with trailing alignment padding.
720     pub fn stride(&self) -> Size {
721         self.min_size.abi_align(self.align)
722     }
723
724     /// Determine whether a structure would be zero-sized, given its fields.
725     fn would_be_zero_sized<I>(dl: &TargetDataLayout, fields: I)
726                               -> Result<bool, LayoutError<'gcx>>
727     where I: Iterator<Item=Result<&'a Layout, LayoutError<'gcx>>> {
728         for field in fields {
729             let field = field?;
730             if field.is_unsized() || field.size(dl).bytes() > 0 {
731                 return Ok(false);
732             }
733         }
734         Ok(true)
735     }
736
737     /// Get indices of the tys that made this struct by increasing offset.
738     #[inline]
739     pub fn field_index_by_increasing_offset<'b>(&'b self) -> impl iter::Iterator<Item=usize>+'b {
740         let mut inverse_small = [0u8; 64];
741         let mut inverse_big = vec![];
742         let use_small = self.memory_index.len() <= inverse_small.len();
743
744         // We have to write this logic twice in order to keep the array small.
745         if use_small {
746             for i in 0..self.memory_index.len() {
747                 inverse_small[self.memory_index[i] as usize] = i as u8;
748             }
749         } else {
750             inverse_big = vec![0; self.memory_index.len()];
751             for i in 0..self.memory_index.len() {
752                 inverse_big[self.memory_index[i] as usize] = i as u32;
753             }
754         }
755
756         (0..self.memory_index.len()).map(move |i| {
757             if use_small { inverse_small[i] as usize }
758             else { inverse_big[i] as usize }
759         })
760     }
761
762     /// Find the path leading to a non-zero leaf field, starting from
763     /// the given type and recursing through aggregates.
764     /// The tuple is `(path, source_path)`,
765     /// where `path` is in memory order and `source_path` in source order.
766     // FIXME(eddyb) track value ranges and traverse already optimized enums.
767     fn non_zero_field_in_type(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
768                                ty: Ty<'gcx>)
769                                -> Result<Option<(FieldPath, FieldPath)>, LayoutError<'gcx>> {
770         let tcx = infcx.tcx.global_tcx();
771         match (ty.layout(infcx)?, &ty.sty) {
772             (&Scalar { non_zero: true, .. }, _) |
773             (&CEnum { non_zero: true, .. }, _) => Ok(Some((vec![], vec![]))),
774             (&FatPointer { non_zero: true, .. }, _) => {
775                 Ok(Some((vec![FAT_PTR_ADDR as u32], vec![FAT_PTR_ADDR as u32])))
776             }
777
778             // Is this the NonZero lang item wrapping a pointer or integer type?
779             (&Univariant { non_zero: true, .. }, &ty::TyAdt(def, substs)) => {
780                 let fields = &def.struct_variant().fields;
781                 assert_eq!(fields.len(), 1);
782                 match *fields[0].ty(tcx, substs).layout(infcx)? {
783                     // FIXME(eddyb) also allow floating-point types here.
784                     Scalar { value: Int(_), non_zero: false } |
785                     Scalar { value: Pointer, non_zero: false } => {
786                         Ok(Some((vec![0], vec![0])))
787                     }
788                     FatPointer { non_zero: false, .. } => {
789                         let tmp = vec![FAT_PTR_ADDR as u32, 0];
790                         Ok(Some((tmp.clone(), tmp)))
791                     }
792                     _ => Ok(None)
793                 }
794             }
795
796             // Perhaps one of the fields of this struct is non-zero
797             // let's recurse and find out
798             (&Univariant { ref variant, .. }, &ty::TyAdt(def, substs)) if def.is_struct() => {
799                 Struct::non_zero_field_paths(infcx, def.struct_variant().fields
800                                                       .iter().map(|field| {
801                     field.ty(tcx, substs)
802                 }),
803                 Some(&variant.memory_index[..]))
804             }
805
806             // Perhaps one of the upvars of this closure is non-zero
807             (&Univariant { ref variant, .. }, &ty::TyClosure(def, substs)) => {
808                 let upvar_tys = substs.upvar_tys(def, tcx);
809                 Struct::non_zero_field_paths(infcx, upvar_tys,
810                     Some(&variant.memory_index[..]))
811             }
812             // Can we use one of the fields in this tuple?
813             (&Univariant { ref variant, .. }, &ty::TyTuple(tys, _)) => {
814                 Struct::non_zero_field_paths(infcx, tys.iter().cloned(),
815                     Some(&variant.memory_index[..]))
816             }
817
818             // Is this a fixed-size array of something non-zero
819             // with at least one element?
820             (_, &ty::TyArray(ety, d)) if d > 0 => {
821                 Struct::non_zero_field_paths(infcx, Some(ety).into_iter(), None)
822             }
823
824             (_, &ty::TyProjection(_)) | (_, &ty::TyAnon(..)) => {
825                 let normalized = infcx.normalize_projections(ty);
826                 if ty == normalized {
827                     return Ok(None);
828                 }
829                 return Struct::non_zero_field_in_type(infcx, normalized);
830             }
831
832             // Anything else is not a non-zero type.
833             _ => Ok(None)
834         }
835     }
836
837     /// Find the path leading to a non-zero leaf field, starting from
838     /// the given set of fields and recursing through aggregates.
839     /// Returns Some((path, source_path)) on success.
840     /// `path` is translated to memory order. `source_path` is not.
841     fn non_zero_field_paths<I>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
842                                   fields: I,
843                                   permutation: Option<&[u32]>)
844                                   -> Result<Option<(FieldPath, FieldPath)>, LayoutError<'gcx>>
845     where I: Iterator<Item=Ty<'gcx>> {
846         for (i, ty) in fields.enumerate() {
847             if let Some((mut path, mut source_path)) = Struct::non_zero_field_in_type(infcx, ty)? {
848                 source_path.push(i as u32);
849                 let index = if let Some(p) = permutation {
850                     p[i] as usize
851                 } else {
852                     i
853                 };
854                 path.push(index as u32);
855                 return Ok(Some((path, source_path)));
856             }
857         }
858         Ok(None)
859     }
860
861     pub fn over_align(&self) -> Option<u32> {
862         let align = self.align.abi();
863         let primitive_align = self.primitive_align.abi();
864         if align > primitive_align {
865             Some(align as u32)
866         } else {
867             None
868         }
869     }
870 }
871
872 /// An untagged union.
873 #[derive(PartialEq, Eq, Hash, Debug)]
874 pub struct Union {
875     pub align: Align,
876     pub primitive_align: Align,
877
878     pub min_size: Size,
879
880     /// If true, no alignment padding is used.
881     pub packed: bool,
882 }
883
884 impl<'a, 'gcx, 'tcx> Union {
885     fn new(dl: &TargetDataLayout, packed: bool) -> Union {
886         let align = if packed { dl.i8_align } else { dl.aggregate_align };
887         Union {
888             align: align,
889             primitive_align: align,
890             min_size: Size::from_bytes(0),
891             packed: packed,
892         }
893     }
894
895     /// Extend the Struct with more fields.
896     fn extend<I>(&mut self, dl: &TargetDataLayout,
897                  fields: I,
898                  scapegoat: Ty<'gcx>)
899                  -> Result<(), LayoutError<'gcx>>
900     where I: Iterator<Item=Result<&'a Layout, LayoutError<'gcx>>> {
901         for (index, field) in fields.enumerate() {
902             let field = field?;
903             if field.is_unsized() {
904                 bug!("Union::extend: field #{} of `{}` is unsized",
905                      index, scapegoat);
906             }
907
908             debug!("Union::extend field: {:?} {:?}", field, field.size(dl));
909
910             if !self.packed {
911                 self.align = self.align.max(field.align(dl));
912                 self.primitive_align = self.primitive_align.max(field.primitive_align(dl));
913             }
914             self.min_size = cmp::max(self.min_size, field.size(dl));
915         }
916
917         debug!("Union::extend min-size: {:?}", self.min_size);
918
919         Ok(())
920     }
921
922     /// Get the size with trailing alignment padding.
923     pub fn stride(&self) -> Size {
924         self.min_size.abi_align(self.align)
925     }
926
927     pub fn over_align(&self) -> Option<u32> {
928         let align = self.align.abi();
929         let primitive_align = self.primitive_align.abi();
930         if align > primitive_align {
931             Some(align as u32)
932         } else {
933             None
934         }
935     }
936 }
937
938 /// The first half of a fat pointer.
939 /// - For a trait object, this is the address of the box.
940 /// - For a slice, this is the base address.
941 pub const FAT_PTR_ADDR: usize = 0;
942
943 /// The second half of a fat pointer.
944 /// - For a trait object, this is the address of the vtable.
945 /// - For a slice, this is the length.
946 pub const FAT_PTR_EXTRA: usize = 1;
947
948 /// Type layout, from which size and alignment can be cheaply computed.
949 /// For ADTs, it also includes field placement and enum optimizations.
950 /// NOTE: Because Layout is interned, redundant information should be
951 /// kept to a minimum, e.g. it includes no sub-component Ty or Layout.
952 #[derive(Debug, PartialEq, Eq, Hash)]
953 pub enum Layout {
954     /// TyBool, TyChar, TyInt, TyUint, TyFloat, TyRawPtr, TyRef or TyFnPtr.
955     Scalar {
956         value: Primitive,
957         // If true, the value cannot represent a bit pattern of all zeroes.
958         non_zero: bool
959     },
960
961     /// SIMD vectors, from structs marked with #[repr(simd)].
962     Vector {
963         element: Primitive,
964         count: u64
965     },
966
967     /// TyArray, TySlice or TyStr.
968     Array {
969         /// If true, the size is exact, otherwise it's only a lower bound.
970         sized: bool,
971         align: Align,
972         primitive_align: Align,
973         element_size: Size,
974         count: u64
975     },
976
977     /// TyRawPtr or TyRef with a !Sized pointee.
978     FatPointer {
979         metadata: Primitive,
980         // If true, the pointer cannot be null.
981         non_zero: bool
982     },
983
984     // Remaining variants are all ADTs such as structs, enums or tuples.
985
986     /// C-like enums; basically an integer.
987     CEnum {
988         discr: Integer,
989         signed: bool,
990         non_zero: bool,
991         // Inclusive discriminant range.
992         // If min > max, it represents min...u64::MAX followed by 0...max.
993         // FIXME(eddyb) always use the shortest range, e.g. by finding
994         // the largest space between two consecutive discriminants and
995         // taking everything else as the (shortest) discriminant range.
996         min: u64,
997         max: u64
998     },
999
1000     /// Single-case enums, and structs/tuples.
1001     Univariant {
1002         variant: Struct,
1003         // If true, the structure is NonZero.
1004         // FIXME(eddyb) use a newtype Layout kind for this.
1005         non_zero: bool
1006     },
1007
1008     /// Untagged unions.
1009     UntaggedUnion {
1010         variants: Union,
1011     },
1012
1013     /// General-case enums: for each case there is a struct, and they
1014     /// all start with a field for the discriminant.
1015     General {
1016         discr: Integer,
1017         variants: Vec<Struct>,
1018         size: Size,
1019         align: Align,
1020         primitive_align: Align,
1021     },
1022
1023     /// Two cases distinguished by a nullable pointer: the case with discriminant
1024     /// `nndiscr` must have single field which is known to be nonnull due to its type.
1025     /// The other case is known to be zero sized. Hence we represent the enum
1026     /// as simply a nullable pointer: if not null it indicates the `nndiscr` variant,
1027     /// otherwise it indicates the other case.
1028     ///
1029     /// For example, `std::option::Option` instantiated at a safe pointer type
1030     /// is represented such that `None` is a null pointer and `Some` is the
1031     /// identity function.
1032     RawNullablePointer {
1033         nndiscr: u64,
1034         value: Primitive
1035     },
1036
1037     /// Two cases distinguished by a nullable pointer: the case with discriminant
1038     /// `nndiscr` is represented by the struct `nonnull`, where the `discrfield`th
1039     /// field is known to be nonnull due to its type; if that field is null, then
1040     /// it represents the other case, which is known to be zero sized.
1041     StructWrappedNullablePointer {
1042         nndiscr: u64,
1043         nonnull: Struct,
1044         // N.B. There is a 0 at the start, for LLVM GEP through a pointer.
1045         discrfield: FieldPath,
1046         // Like discrfield, but in source order. For debuginfo.
1047         discrfield_source: FieldPath
1048     }
1049 }
1050
1051 #[derive(Copy, Clone, Debug)]
1052 pub enum LayoutError<'tcx> {
1053     Unknown(Ty<'tcx>),
1054     SizeOverflow(Ty<'tcx>)
1055 }
1056
1057 impl<'tcx> fmt::Display for LayoutError<'tcx> {
1058     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1059         match *self {
1060             LayoutError::Unknown(ty) => {
1061                 write!(f, "the type `{:?}` has an unknown layout", ty)
1062             }
1063             LayoutError::SizeOverflow(ty) => {
1064                 write!(f, "the type `{:?}` is too big for the current architecture", ty)
1065             }
1066         }
1067     }
1068 }
1069
1070 impl<'a, 'gcx, 'tcx> Layout {
1071     pub fn compute_uncached(ty: Ty<'gcx>,
1072                             infcx: &InferCtxt<'a, 'gcx, 'tcx>)
1073                             -> Result<&'gcx Layout, LayoutError<'gcx>> {
1074         let tcx = infcx.tcx.global_tcx();
1075         let success = |layout| Ok(tcx.intern_layout(layout));
1076         let dl = &tcx.data_layout;
1077         assert!(!ty.has_infer_types());
1078
1079         let ptr_layout = |pointee: Ty<'gcx>| {
1080             let non_zero = !ty.is_unsafe_ptr();
1081             let pointee = infcx.normalize_projections(pointee);
1082             if pointee.is_sized(tcx, &infcx.parameter_environment, DUMMY_SP) {
1083                 Ok(Scalar { value: Pointer, non_zero: non_zero })
1084             } else {
1085                 let unsized_part = tcx.struct_tail(pointee);
1086                 let meta = match unsized_part.sty {
1087                     ty::TySlice(_) | ty::TyStr => {
1088                         Int(dl.ptr_sized_integer())
1089                     }
1090                     ty::TyDynamic(..) => Pointer,
1091                     _ => return Err(LayoutError::Unknown(unsized_part))
1092                 };
1093                 Ok(FatPointer { metadata: meta, non_zero: non_zero })
1094             }
1095         };
1096
1097         let layout = match ty.sty {
1098             // Basic scalars.
1099             ty::TyBool => Scalar { value: Int(I1), non_zero: false },
1100             ty::TyChar => Scalar { value: Int(I32), non_zero: false },
1101             ty::TyInt(ity) => {
1102                 Scalar {
1103                     value: Int(Integer::from_attr(dl, attr::SignedInt(ity))),
1104                     non_zero: false
1105                 }
1106             }
1107             ty::TyUint(ity) => {
1108                 Scalar {
1109                     value: Int(Integer::from_attr(dl, attr::UnsignedInt(ity))),
1110                     non_zero: false
1111                 }
1112             }
1113             ty::TyFloat(FloatTy::F32) => Scalar { value: F32, non_zero: false },
1114             ty::TyFloat(FloatTy::F64) => Scalar { value: F64, non_zero: false },
1115             ty::TyFnPtr(_) => Scalar { value: Pointer, non_zero: true },
1116
1117             // The never type.
1118             ty::TyNever => Univariant {
1119                 variant: Struct::new(dl, &vec![], &ReprOptions::default(),
1120                   StructKind::AlwaysSizedUnivariant, ty)?,
1121                 non_zero: false
1122             },
1123
1124             // Potentially-fat pointers.
1125             ty::TyRef(_, ty::TypeAndMut { ty: pointee, .. }) |
1126             ty::TyRawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
1127                 ptr_layout(pointee)?
1128             }
1129             ty::TyAdt(def, _) if def.is_box() => {
1130                 ptr_layout(ty.boxed_ty())?
1131             }
1132
1133             // Arrays and slices.
1134             ty::TyArray(element, count) => {
1135                 let element = element.layout(infcx)?;
1136                 let element_size = element.size(dl);
1137                 // FIXME(eddyb) Don't use host `usize` for array lengths.
1138                 let usize_count: usize = count;
1139                 let count = usize_count as u64;
1140                 if element_size.checked_mul(count, dl).is_none() {
1141                     return Err(LayoutError::SizeOverflow(ty));
1142                 }
1143                 Array {
1144                     sized: true,
1145                     align: element.align(dl),
1146                     primitive_align: element.primitive_align(dl),
1147                     element_size: element_size,
1148                     count: count
1149                 }
1150             }
1151             ty::TySlice(element) => {
1152                 let element = element.layout(infcx)?;
1153                 Array {
1154                     sized: false,
1155                     align: element.align(dl),
1156                     primitive_align: element.primitive_align(dl),
1157                     element_size: element.size(dl),
1158                     count: 0
1159                 }
1160             }
1161             ty::TyStr => {
1162                 Array {
1163                     sized: false,
1164                     align: dl.i8_align,
1165                     primitive_align: dl.i8_align,
1166                     element_size: Size::from_bytes(1),
1167                     count: 0
1168                 }
1169             }
1170
1171             // Odd unit types.
1172             ty::TyFnDef(..) => {
1173                 Univariant {
1174                     variant: Struct::new(dl, &vec![],
1175                       &ReprOptions::default(), StructKind::AlwaysSizedUnivariant, ty)?,
1176                     non_zero: false
1177                 }
1178             }
1179             ty::TyDynamic(..) => {
1180                 let mut unit = Struct::new(dl, &vec![], &ReprOptions::default(),
1181                   StructKind::AlwaysSizedUnivariant, ty)?;
1182                 unit.sized = false;
1183                 Univariant { variant: unit, non_zero: false }
1184             }
1185
1186             // Tuples and closures.
1187             ty::TyClosure(def_id, ref substs) => {
1188                 let tys = substs.upvar_tys(def_id, tcx);
1189                 let st = Struct::new(dl,
1190                     &tys.map(|ty| ty.layout(infcx))
1191                       .collect::<Result<Vec<_>, _>>()?,
1192                     &ReprOptions::default(),
1193                     StructKind::AlwaysSizedUnivariant, ty)?;
1194                 Univariant { variant: st, non_zero: false }
1195             }
1196
1197             ty::TyTuple(tys, _) => {
1198                 // FIXME(camlorn): if we ever allow unsized tuples, this needs to be checked.
1199                 // See the univariant case below to learn how.
1200                 let st = Struct::new(dl,
1201                     &tys.iter().map(|ty| ty.layout(infcx))
1202                       .collect::<Result<Vec<_>, _>>()?,
1203                     &ReprOptions::default(), StructKind::AlwaysSizedUnivariant, ty)?;
1204                 Univariant { variant: st, non_zero: false }
1205             }
1206
1207             // SIMD vector types.
1208             ty::TyAdt(def, ..) if def.repr.simd() => {
1209                 let element = ty.simd_type(tcx);
1210                 match *element.layout(infcx)? {
1211                     Scalar { value, .. } => {
1212                         return success(Vector {
1213                             element: value,
1214                             count: ty.simd_size(tcx) as u64
1215                         });
1216                     }
1217                     _ => {
1218                         tcx.sess.fatal(&format!("monomorphising SIMD type `{}` with \
1219                                                 a non-machine element type `{}`",
1220                                                 ty, element));
1221                     }
1222                 }
1223             }
1224
1225             // ADTs.
1226             ty::TyAdt(def, substs) => {
1227                 if def.variants.is_empty() {
1228                     // Uninhabitable; represent as unit
1229                     // (Typechecking will reject discriminant-sizing attrs.)
1230
1231                     return success(Univariant {
1232                         variant: Struct::new(dl, &vec![],
1233                           &def.repr, StructKind::AlwaysSizedUnivariant, ty)?,
1234                         non_zero: false
1235                     });
1236                 }
1237
1238                 if def.is_enum() && def.variants.iter().all(|v| v.fields.is_empty()) {
1239                     // All bodies empty -> intlike
1240                     let (mut min, mut max, mut non_zero) = (i64::max_value(),
1241                                                             i64::min_value(),
1242                                                             true);
1243                     for discr in def.discriminants(tcx) {
1244                         let x = discr.to_u128_unchecked() as i64;
1245                         if x == 0 { non_zero = false; }
1246                         if x < min { min = x; }
1247                         if x > max { max = x; }
1248                     }
1249
1250                     // FIXME: should handle i128? signed-value based impl is weird and hard to
1251                     // grok.
1252                     let (discr, signed) = Integer::repr_discr(tcx, ty, &def.repr, min, max);
1253                     return success(CEnum {
1254                         discr: discr,
1255                         signed: signed,
1256                         non_zero: non_zero,
1257                         // FIXME: should be u128?
1258                         min: min as u64,
1259                         max: max as u64
1260                     });
1261                 }
1262
1263                 if !def.is_enum() || (def.variants.len() == 1 &&
1264                                       !def.repr.inhibit_enum_layout_opt()) {
1265                     // Struct, or union, or univariant enum equivalent to a struct.
1266                     // (Typechecking will reject discriminant-sizing attrs.)
1267
1268                     let kind = if def.is_enum() || def.variants[0].fields.len() == 0{
1269                         StructKind::AlwaysSizedUnivariant
1270                     } else {
1271                         use middle::region::ROOT_CODE_EXTENT;
1272                         let param_env = tcx.construct_parameter_environment(DUMMY_SP,
1273                           def.did, ROOT_CODE_EXTENT);
1274                         let fields = &def.variants[0].fields;
1275                         let last_field = &fields[fields.len()-1];
1276                         let always_sized = last_field.ty(tcx, param_env.free_substs)
1277                           .is_sized(tcx, &param_env, DUMMY_SP);
1278                         if !always_sized { StructKind::MaybeUnsizedUnivariant }
1279                         else { StructKind::AlwaysSizedUnivariant }
1280                     };
1281
1282                     let fields = def.variants[0].fields.iter().map(|field| {
1283                         field.ty(tcx, substs).layout(infcx)
1284                     }).collect::<Result<Vec<_>, _>>()?;
1285                     let layout = if def.is_union() {
1286                         let mut un = Union::new(dl, def.repr.packed());
1287                         un.extend(dl, fields.iter().map(|&f| Ok(f)), ty)?;
1288                         UntaggedUnion { variants: un }
1289                     } else {
1290                         let st = Struct::new(dl, &fields, &def.repr,
1291                           kind, ty)?;
1292                         let non_zero = Some(def.did) == tcx.lang_items.non_zero();
1293                         Univariant { variant: st, non_zero: non_zero }
1294                     };
1295                     return success(layout);
1296                 }
1297
1298                 // Since there's at least one
1299                 // non-empty body, explicit discriminants should have
1300                 // been rejected by a checker before this point.
1301                 for (i, v) in def.variants.iter().enumerate() {
1302                     if v.discr != ty::VariantDiscr::Relative(i) {
1303                         bug!("non-C-like enum {} with specified discriminants",
1304                             tcx.item_path_str(def.did));
1305                     }
1306                 }
1307
1308                 // Cache the substituted and normalized variant field types.
1309                 let variants = def.variants.iter().map(|v| {
1310                     v.fields.iter().map(|field| field.ty(tcx, substs)).collect::<Vec<_>>()
1311                 }).collect::<Vec<_>>();
1312
1313                 if variants.len() == 2 && !def.repr.inhibit_enum_layout_opt() {
1314                     // Nullable pointer optimization
1315                     for discr in 0..2 {
1316                         let other_fields = variants[1 - discr].iter().map(|ty| {
1317                             ty.layout(infcx)
1318                         });
1319                         if !Struct::would_be_zero_sized(dl, other_fields)? {
1320                             continue;
1321                         }
1322                         let paths = Struct::non_zero_field_paths(infcx,
1323                             variants[discr].iter().cloned(),
1324                             None)?;
1325                         let (mut path, mut path_source) = if let Some(p) = paths { p }
1326                           else { continue };
1327
1328                         // FIXME(eddyb) should take advantage of a newtype.
1329                         if path == &[0] && variants[discr].len() == 1 {
1330                             let value = match *variants[discr][0].layout(infcx)? {
1331                                 Scalar { value, .. } => value,
1332                                 CEnum { discr, .. } => Int(discr),
1333                                 _ => bug!("Layout::compute: `{}`'s non-zero \
1334                                            `{}` field not scalar?!",
1335                                            ty, variants[discr][0])
1336                             };
1337                             return success(RawNullablePointer {
1338                                 nndiscr: discr as u64,
1339                                 value: value,
1340                             });
1341                         }
1342
1343                         let st = Struct::new(dl,
1344                             &variants[discr].iter().map(|ty| ty.layout(infcx))
1345                               .collect::<Result<Vec<_>, _>>()?,
1346                             &def.repr, StructKind::AlwaysSizedUnivariant, ty)?;
1347
1348                         // We have to fix the last element of path here.
1349                         let mut i = *path.last().unwrap();
1350                         i = st.memory_index[i as usize];
1351                         *path.last_mut().unwrap() = i;
1352                         path.push(0); // For GEP through a pointer.
1353                         path.reverse();
1354                         path_source.push(0);
1355                         path_source.reverse();
1356
1357                         return success(StructWrappedNullablePointer {
1358                             nndiscr: discr as u64,
1359                             nonnull: st,
1360                             discrfield: path,
1361                             discrfield_source: path_source
1362                         });
1363                     }
1364                 }
1365
1366                 // The general case.
1367                 let discr_max = (variants.len() - 1) as i64;
1368                 assert!(discr_max >= 0);
1369                 let (min_ity, _) = Integer::repr_discr(tcx, ty, &def.repr, 0, discr_max);
1370                 let mut align = dl.aggregate_align;
1371                 let mut primitive_align = dl.aggregate_align;
1372                 let mut size = Size::from_bytes(0);
1373
1374                 // We're interested in the smallest alignment, so start large.
1375                 let mut start_align = Align::from_bytes(256, 256).unwrap();
1376
1377                 // Create the set of structs that represent each variant
1378                 // Use the minimum integer type we figured out above
1379                 let discr = Scalar { value: Int(min_ity), non_zero: false };
1380                 let mut variants = variants.into_iter().map(|fields| {
1381                     let mut fields = fields.into_iter().map(|field| {
1382                         field.layout(infcx)
1383                     }).collect::<Result<Vec<_>, _>>()?;
1384                     fields.insert(0, &discr);
1385                     let st = Struct::new(dl,
1386                         &fields,
1387                         &def.repr, StructKind::EnumVariant, ty)?;
1388                     // Find the first field we can't move later
1389                     // to make room for a larger discriminant.
1390                     // It is important to skip the first field.
1391                     for i in st.field_index_by_increasing_offset().skip(1) {
1392                         let field = fields[i];
1393                         let field_align = field.align(dl);
1394                         if field.size(dl).bytes() != 0 || field_align.abi() != 1 {
1395                             start_align = start_align.min(field_align);
1396                             break;
1397                         }
1398                     }
1399                     size = cmp::max(size, st.min_size);
1400                     align = align.max(st.align);
1401                     primitive_align = primitive_align.max(st.primitive_align);
1402                     Ok(st)
1403                 }).collect::<Result<Vec<_>, _>>()?;
1404
1405                 // Align the maximum variant size to the largest alignment.
1406                 size = size.abi_align(align);
1407
1408                 if size.bytes() >= dl.obj_size_bound() {
1409                     return Err(LayoutError::SizeOverflow(ty));
1410                 }
1411
1412                 let typeck_ity = Integer::from_attr(dl, def.repr.discr_type());
1413                 if typeck_ity < min_ity {
1414                     // It is a bug if Layout decided on a greater discriminant size than typeck for
1415                     // some reason at this point (based on values discriminant can take on). Mostly
1416                     // because this discriminant will be loaded, and then stored into variable of
1417                     // type calculated by typeck. Consider such case (a bug): typeck decided on
1418                     // byte-sized discriminant, but layout thinks we need a 16-bit to store all
1419                     // discriminant values. That would be a bug, because then, in trans, in order
1420                     // to store this 16-bit discriminant into 8-bit sized temporary some of the
1421                     // space necessary to represent would have to be discarded (or layout is wrong
1422                     // on thinking it needs 16 bits)
1423                     bug!("layout decided on a larger discriminant type ({:?}) than typeck ({:?})",
1424                          min_ity, typeck_ity);
1425                     // However, it is fine to make discr type however large (as an optimisation)
1426                     // after this point â€“ we’ll just truncate the value we load in trans.
1427                 }
1428
1429                 // Check to see if we should use a different type for the
1430                 // discriminant. We can safely use a type with the same size
1431                 // as the alignment of the first field of each variant.
1432                 // We increase the size of the discriminant to avoid LLVM copying
1433                 // padding when it doesn't need to. This normally causes unaligned
1434                 // load/stores and excessive memcpy/memset operations. By using a
1435                 // bigger integer size, LLVM can be sure about it's contents and
1436                 // won't be so conservative.
1437
1438                 // Use the initial field alignment
1439                 let mut ity = Integer::for_abi_align(dl, start_align).unwrap_or(min_ity);
1440
1441                 // If the alignment is not larger than the chosen discriminant size,
1442                 // don't use the alignment as the final size.
1443                 if ity <= min_ity {
1444                     ity = min_ity;
1445                 } else {
1446                     // Patch up the variants' first few fields.
1447                     let old_ity_size = Int(min_ity).size(dl);
1448                     let new_ity_size = Int(ity).size(dl);
1449                     for variant in &mut variants {
1450                         for i in variant.offsets.iter_mut() {
1451                             // The first field is the discrimminant, at offset 0.
1452                             // These aren't in order, and we need to skip it.
1453                             if *i <= old_ity_size && *i > Size::from_bytes(0) {
1454                                 *i = new_ity_size;
1455                             }
1456                         }
1457                         // We might be making the struct larger.
1458                         if variant.min_size <= old_ity_size {
1459                             variant.min_size = new_ity_size;
1460                         }
1461                     }
1462                 }
1463
1464                 General {
1465                     discr: ity,
1466                     variants: variants,
1467                     size: size,
1468                     align: align,
1469                     primitive_align: primitive_align
1470                 }
1471             }
1472
1473             // Types with no meaningful known layout.
1474             ty::TyProjection(_) | ty::TyAnon(..) => {
1475                 let normalized = infcx.normalize_projections(ty);
1476                 if ty == normalized {
1477                     return Err(LayoutError::Unknown(ty));
1478                 }
1479                 return normalized.layout(infcx);
1480             }
1481             ty::TyParam(_) => {
1482                 return Err(LayoutError::Unknown(ty));
1483             }
1484             ty::TyInfer(_) | ty::TyError => {
1485                 bug!("Layout::compute: unexpected type `{}`", ty)
1486             }
1487         };
1488
1489         success(layout)
1490     }
1491
1492     /// Returns true if the layout corresponds to an unsized type.
1493     pub fn is_unsized(&self) -> bool {
1494         match *self {
1495             Scalar {..} | Vector {..} | FatPointer {..} |
1496             CEnum {..} | UntaggedUnion {..} | General {..} |
1497             RawNullablePointer {..} |
1498             StructWrappedNullablePointer {..} => false,
1499
1500             Array { sized, .. } |
1501             Univariant { variant: Struct { sized, .. }, .. } => !sized
1502         }
1503     }
1504
1505     pub fn size<C: HasDataLayout>(&self, cx: C) -> Size {
1506         let dl = cx.data_layout();
1507
1508         match *self {
1509             Scalar { value, .. } | RawNullablePointer { value, .. } => {
1510                 value.size(dl)
1511             }
1512
1513             Vector { element, count } => {
1514                 let element_size = element.size(dl);
1515                 let vec_size = match element_size.checked_mul(count, dl) {
1516                     Some(size) => size,
1517                     None => bug!("Layout::size({:?}): {} * {} overflowed",
1518                                  self, element_size.bytes(), count)
1519                 };
1520                 vec_size.abi_align(self.align(dl))
1521             }
1522
1523             Array { element_size, count, .. } => {
1524                 match element_size.checked_mul(count, dl) {
1525                     Some(size) => size,
1526                     None => bug!("Layout::size({:?}): {} * {} overflowed",
1527                                  self, element_size.bytes(), count)
1528                 }
1529             }
1530
1531             FatPointer { metadata, .. } => {
1532                 // Effectively a (ptr, meta) tuple.
1533                 Pointer.size(dl).abi_align(metadata.align(dl))
1534                        .checked_add(metadata.size(dl), dl).unwrap()
1535                        .abi_align(self.align(dl))
1536             }
1537
1538             CEnum { discr, .. } => Int(discr).size(dl),
1539             General { size, .. } => size,
1540             UntaggedUnion { ref variants } => variants.stride(),
1541
1542             Univariant { ref variant, .. } |
1543             StructWrappedNullablePointer { nonnull: ref variant, .. } => {
1544                 variant.stride()
1545             }
1546         }
1547     }
1548
1549     pub fn align<C: HasDataLayout>(&self, cx: C) -> Align {
1550         let dl = cx.data_layout();
1551
1552         match *self {
1553             Scalar { value, .. } | RawNullablePointer { value, .. } => {
1554                 value.align(dl)
1555             }
1556
1557             Vector { element, count } => {
1558                 let elem_size = element.size(dl);
1559                 let vec_size = match elem_size.checked_mul(count, dl) {
1560                     Some(size) => size,
1561                     None => bug!("Layout::align({:?}): {} * {} overflowed",
1562                                  self, elem_size.bytes(), count)
1563                 };
1564                 for &(size, align) in &dl.vector_align {
1565                     if size == vec_size {
1566                         return align;
1567                     }
1568                 }
1569                 // Default to natural alignment, which is what LLVM does.
1570                 // That is, use the size, rounded up to a power of 2.
1571                 let align = vec_size.bytes().next_power_of_two();
1572                 Align::from_bytes(align, align).unwrap()
1573             }
1574
1575             FatPointer { metadata, .. } => {
1576                 // Effectively a (ptr, meta) tuple.
1577                 Pointer.align(dl).max(metadata.align(dl))
1578             }
1579
1580             CEnum { discr, .. } => Int(discr).align(dl),
1581             Array { align, .. } | General { align, .. } => align,
1582             UntaggedUnion { ref variants } => variants.align,
1583
1584             Univariant { ref variant, .. } |
1585             StructWrappedNullablePointer { nonnull: ref variant, .. } => {
1586                 variant.align
1587             }
1588         }
1589     }
1590
1591     /// Returns alignment before repr alignment is applied
1592     pub fn primitive_align(&self, dl: &TargetDataLayout) -> Align {
1593         match *self {
1594             Array { primitive_align, .. } | General { primitive_align, .. } => primitive_align,
1595             Univariant { ref variant, .. } |
1596             StructWrappedNullablePointer { nonnull: ref variant, .. } => {
1597                 variant.primitive_align
1598             },
1599
1600             _ => self.align(dl)
1601         }
1602     }
1603
1604     /// Returns repr alignment if it is greater than the primitive alignment.
1605     pub fn over_align(&self, dl: &TargetDataLayout) -> Option<u32> {
1606         let align = self.align(dl);
1607         let primitive_align = self.primitive_align(dl);
1608         if align.abi() > primitive_align.abi() {
1609             Some(align.abi() as u32)
1610         } else {
1611             None
1612         }
1613     }
1614
1615     pub fn field_offset<C: HasDataLayout>(&self,
1616                                           cx: C,
1617                                           i: usize,
1618                                           variant_index: Option<usize>)
1619                                           -> Size {
1620         let dl = cx.data_layout();
1621
1622         match *self {
1623             Scalar { .. } |
1624             CEnum { .. } |
1625             UntaggedUnion { .. } |
1626             RawNullablePointer { .. } => {
1627                 Size::from_bytes(0)
1628             }
1629
1630             Vector { element, count } => {
1631                 let element_size = element.size(dl);
1632                 let i = i as u64;
1633                 assert!(i < count);
1634                 Size::from_bytes(element_size.bytes() * count)
1635             }
1636
1637             Array { element_size, count, .. } => {
1638                 let i = i as u64;
1639                 assert!(i < count);
1640                 Size::from_bytes(element_size.bytes() * count)
1641             }
1642
1643             FatPointer { metadata, .. } => {
1644                 // Effectively a (ptr, meta) tuple.
1645                 assert!(i < 2);
1646                 if i == 0 {
1647                     Size::from_bytes(0)
1648                 } else {
1649                     Pointer.size(dl).abi_align(metadata.align(dl))
1650                 }
1651             }
1652
1653             Univariant { ref variant, .. } => variant.offsets[i],
1654
1655             General { ref variants, .. } => {
1656                 let v = variant_index.expect("variant index required");
1657                 variants[v].offsets[i + 1]
1658             }
1659
1660             StructWrappedNullablePointer { nndiscr, ref nonnull, .. } => {
1661                 if Some(nndiscr as usize) == variant_index {
1662                     nonnull.offsets[i]
1663                 } else {
1664                     Size::from_bytes(0)
1665                 }
1666             }
1667         }
1668     }
1669 }
1670
1671 /// Type size "skeleton", i.e. the only information determining a type's size.
1672 /// While this is conservative, (aside from constant sizes, only pointers,
1673 /// newtypes thereof and null pointer optimized enums are allowed), it is
1674 /// enough to statically check common usecases of transmute.
1675 #[derive(Copy, Clone, Debug)]
1676 pub enum SizeSkeleton<'tcx> {
1677     /// Any statically computable Layout.
1678     Known(Size),
1679
1680     /// A potentially-fat pointer.
1681     Pointer {
1682         // If true, this pointer is never null.
1683         non_zero: bool,
1684         // The type which determines the unsized metadata, if any,
1685         // of this pointer. Either a type parameter or a projection
1686         // depending on one, with regions erased.
1687         tail: Ty<'tcx>
1688     }
1689 }
1690
1691 impl<'a, 'gcx, 'tcx> SizeSkeleton<'gcx> {
1692     pub fn compute(ty: Ty<'gcx>, infcx: &InferCtxt<'a, 'gcx, 'tcx>)
1693                    -> Result<SizeSkeleton<'gcx>, LayoutError<'gcx>> {
1694         let tcx = infcx.tcx.global_tcx();
1695         assert!(!ty.has_infer_types());
1696
1697         // First try computing a static layout.
1698         let err = match ty.layout(infcx) {
1699             Ok(layout) => {
1700                 return Ok(SizeSkeleton::Known(layout.size(tcx)));
1701             }
1702             Err(err) => err
1703         };
1704
1705         let ptr_skeleton = |pointee: Ty<'gcx>| {
1706             let non_zero = !ty.is_unsafe_ptr();
1707             let tail = tcx.struct_tail(pointee);
1708             match tail.sty {
1709                 ty::TyParam(_) | ty::TyProjection(_) => {
1710                     assert!(tail.has_param_types() || tail.has_self_ty());
1711                     Ok(SizeSkeleton::Pointer {
1712                         non_zero: non_zero,
1713                         tail: tcx.erase_regions(&tail)
1714                     })
1715                 }
1716                 _ => {
1717                     bug!("SizeSkeleton::compute({}): layout errored ({}), yet \
1718                             tail `{}` is not a type parameter or a projection",
1719                             ty, err, tail)
1720                 }
1721             }
1722         };
1723
1724         match ty.sty {
1725             ty::TyRef(_, ty::TypeAndMut { ty: pointee, .. }) |
1726             ty::TyRawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
1727                 ptr_skeleton(pointee)
1728             }
1729             ty::TyAdt(def, _) if def.is_box() => {
1730                 ptr_skeleton(ty.boxed_ty())
1731             }
1732
1733             ty::TyAdt(def, substs) => {
1734                 // Only newtypes and enums w/ nullable pointer optimization.
1735                 if def.is_union() || def.variants.is_empty() || def.variants.len() > 2 {
1736                     return Err(err);
1737                 }
1738
1739                 // Get a zero-sized variant or a pointer newtype.
1740                 let zero_or_ptr_variant = |i: usize| {
1741                     let fields = def.variants[i].fields.iter().map(|field| {
1742                         SizeSkeleton::compute(field.ty(tcx, substs), infcx)
1743                     });
1744                     let mut ptr = None;
1745                     for field in fields {
1746                         let field = field?;
1747                         match field {
1748                             SizeSkeleton::Known(size) => {
1749                                 if size.bytes() > 0 {
1750                                     return Err(err);
1751                                 }
1752                             }
1753                             SizeSkeleton::Pointer {..} => {
1754                                 if ptr.is_some() {
1755                                     return Err(err);
1756                                 }
1757                                 ptr = Some(field);
1758                             }
1759                         }
1760                     }
1761                     Ok(ptr)
1762                 };
1763
1764                 let v0 = zero_or_ptr_variant(0)?;
1765                 // Newtype.
1766                 if def.variants.len() == 1 {
1767                     if let Some(SizeSkeleton::Pointer { non_zero, tail }) = v0 {
1768                         return Ok(SizeSkeleton::Pointer {
1769                             non_zero: non_zero ||
1770                                 Some(def.did) == tcx.lang_items.non_zero(),
1771                             tail: tail
1772                         });
1773                     } else {
1774                         return Err(err);
1775                     }
1776                 }
1777
1778                 let v1 = zero_or_ptr_variant(1)?;
1779                 // Nullable pointer enum optimization.
1780                 match (v0, v1) {
1781                     (Some(SizeSkeleton::Pointer { non_zero: true, tail }), None) |
1782                     (None, Some(SizeSkeleton::Pointer { non_zero: true, tail })) => {
1783                         Ok(SizeSkeleton::Pointer {
1784                             non_zero: false,
1785                             tail: tail
1786                         })
1787                     }
1788                     _ => Err(err)
1789                 }
1790             }
1791
1792             ty::TyProjection(_) | ty::TyAnon(..) => {
1793                 let normalized = infcx.normalize_projections(ty);
1794                 if ty == normalized {
1795                     Err(err)
1796                 } else {
1797                     SizeSkeleton::compute(normalized, infcx)
1798                 }
1799             }
1800
1801             _ => Err(err)
1802         }
1803     }
1804
1805     pub fn same_size(self, other: SizeSkeleton) -> bool {
1806         match (self, other) {
1807             (SizeSkeleton::Known(a), SizeSkeleton::Known(b)) => a == b,
1808             (SizeSkeleton::Pointer { tail: a, .. },
1809              SizeSkeleton::Pointer { tail: b, .. }) => a == b,
1810             _ => false
1811         }
1812     }
1813 }
1814
1815 /// A pair of a type and its layout. Implements various
1816 /// type traversal APIs (e.g. recursing into fields).
1817 #[derive(Copy, Clone, Debug)]
1818 pub struct TyLayout<'tcx> {
1819     pub ty: Ty<'tcx>,
1820     pub layout: &'tcx Layout,
1821     pub variant_index: Option<usize>,
1822 }
1823
1824 impl<'tcx> Deref for TyLayout<'tcx> {
1825     type Target = Layout;
1826     fn deref(&self) -> &Layout {
1827         self.layout
1828     }
1829 }
1830
1831 pub trait HasTyCtxt<'tcx>: HasDataLayout {
1832     fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx>;
1833 }
1834
1835 impl<'a, 'gcx, 'tcx> HasDataLayout for TyCtxt<'a, 'gcx, 'tcx> {
1836     fn data_layout(&self) -> &TargetDataLayout {
1837         &self.data_layout
1838     }
1839 }
1840
1841 impl<'a, 'gcx, 'tcx> HasTyCtxt<'gcx> for TyCtxt<'a, 'gcx, 'tcx> {
1842     fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'gcx> {
1843         self.global_tcx()
1844     }
1845 }
1846
1847 impl<'a, 'gcx, 'tcx> HasDataLayout for &'a InferCtxt<'a, 'gcx, 'tcx> {
1848     fn data_layout(&self) -> &TargetDataLayout {
1849         &self.tcx.data_layout
1850     }
1851 }
1852
1853 impl<'a, 'gcx, 'tcx> HasTyCtxt<'gcx> for &'a InferCtxt<'a, 'gcx, 'tcx> {
1854     fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'gcx> {
1855         self.tcx.global_tcx()
1856     }
1857 }
1858
1859 pub trait LayoutTyper<'tcx>: HasTyCtxt<'tcx> {
1860     type TyLayout;
1861
1862     fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout;
1863     fn normalize_projections(self, ty: Ty<'tcx>) -> Ty<'tcx>;
1864 }
1865
1866 impl<'a, 'gcx, 'tcx> LayoutTyper<'gcx> for &'a InferCtxt<'a, 'gcx, 'tcx> {
1867     type TyLayout = Result<TyLayout<'gcx>, LayoutError<'gcx>>;
1868
1869     fn layout_of(self, ty: Ty<'gcx>) -> Self::TyLayout {
1870         let ty = self.normalize_projections(ty);
1871
1872         Ok(TyLayout {
1873             ty: ty,
1874             layout: ty.layout(self)?,
1875             variant_index: None
1876         })
1877     }
1878
1879     fn normalize_projections(self, ty: Ty<'gcx>) -> Ty<'gcx> {
1880         if !ty.has_projection_types() {
1881             return ty;
1882         }
1883
1884         let mut selcx = traits::SelectionContext::new(self);
1885         let cause = traits::ObligationCause::dummy();
1886         let traits::Normalized { value: result, obligations } =
1887             traits::normalize(&mut selcx, cause, &ty);
1888
1889         let mut fulfill_cx = traits::FulfillmentContext::new();
1890
1891         for obligation in obligations {
1892             fulfill_cx.register_predicate_obligation(self, obligation);
1893         }
1894
1895         self.drain_fulfillment_cx_or_panic(DUMMY_SP, &mut fulfill_cx, &result)
1896     }
1897 }
1898
1899 impl<'a, 'tcx> TyLayout<'tcx> {
1900     pub fn for_variant(&self, variant_index: usize) -> Self {
1901         TyLayout {
1902             variant_index: Some(variant_index),
1903             ..*self
1904         }
1905     }
1906
1907     pub fn field_offset<C: HasDataLayout>(&self, cx: C, i: usize) -> Size {
1908         self.layout.field_offset(cx, i, self.variant_index)
1909     }
1910
1911     pub fn field_count(&self) -> usize {
1912         // Handle enum/union through the type rather than Layout.
1913         if let ty::TyAdt(def, _) = self.ty.sty {
1914             let v = self.variant_index.unwrap_or(0);
1915             if def.variants.is_empty() {
1916                 assert_eq!(v, 0);
1917                 return 0;
1918             } else {
1919                 return def.variants[v].fields.len();
1920             }
1921         }
1922
1923         match *self.layout {
1924             Scalar { .. } => {
1925                 bug!("TyLayout::field_count({:?}): not applicable", self)
1926             }
1927
1928             // Handled above (the TyAdt case).
1929             CEnum { .. } |
1930             General { .. } |
1931             UntaggedUnion { .. } |
1932             RawNullablePointer { .. } |
1933             StructWrappedNullablePointer { .. } => bug!(),
1934
1935             FatPointer { .. } => 2,
1936
1937             Vector { count, .. } |
1938             Array { count, .. } => {
1939                 let usize_count = count as usize;
1940                 assert_eq!(usize_count as u64, count);
1941                 usize_count
1942             }
1943
1944             Univariant { ref variant, .. } => variant.offsets.len(),
1945         }
1946     }
1947
1948     pub fn field_type<C: HasTyCtxt<'tcx>>(&self, cx: C, i: usize) -> Ty<'tcx> {
1949         let tcx = cx.tcx();
1950
1951         let ptr_field_type = |pointee: Ty<'tcx>| {
1952             let slice = |element: Ty<'tcx>| {
1953                 assert!(i < 2);
1954                 if i == 0 {
1955                     tcx.mk_mut_ptr(element)
1956                 } else {
1957                     tcx.types.usize
1958                 }
1959             };
1960             match tcx.struct_tail(pointee).sty {
1961                 ty::TySlice(element) => slice(element),
1962                 ty::TyStr => slice(tcx.types.u8),
1963                 ty::TyDynamic(..) => tcx.mk_mut_ptr(tcx.mk_nil()),
1964                 _ => bug!("TyLayout::field_type({:?}): not applicable", self)
1965             }
1966         };
1967
1968         match self.ty.sty {
1969             ty::TyBool |
1970             ty::TyChar |
1971             ty::TyInt(_) |
1972             ty::TyUint(_) |
1973             ty::TyFloat(_) |
1974             ty::TyFnPtr(_) |
1975             ty::TyNever |
1976             ty::TyFnDef(..) |
1977             ty::TyDynamic(..) => {
1978                 bug!("TyLayout::field_type({:?}): not applicable", self)
1979             }
1980
1981             // Potentially-fat pointers.
1982             ty::TyRef(_, ty::TypeAndMut { ty: pointee, .. }) |
1983             ty::TyRawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
1984                 ptr_field_type(pointee)
1985             }
1986             ty::TyAdt(def, _) if def.is_box() => {
1987                 ptr_field_type(self.ty.boxed_ty())
1988             }
1989
1990             // Arrays and slices.
1991             ty::TyArray(element, _) |
1992             ty::TySlice(element) => element,
1993             ty::TyStr => tcx.types.u8,
1994
1995             // Tuples and closures.
1996             ty::TyClosure(def_id, ref substs) => {
1997                 substs.upvar_tys(def_id, tcx).nth(i).unwrap()
1998             }
1999
2000             ty::TyTuple(tys, _) => tys[i],
2001
2002             // SIMD vector types.
2003             ty::TyAdt(def, ..) if def.repr.simd() => {
2004                 self.ty.simd_type(tcx)
2005             }
2006
2007             // ADTs.
2008             ty::TyAdt(def, substs) => {
2009                 def.variants[self.variant_index.unwrap_or(0)].fields[i].ty(tcx, substs)
2010             }
2011
2012             ty::TyProjection(_) | ty::TyAnon(..) | ty::TyParam(_) |
2013             ty::TyInfer(_) | ty::TyError => {
2014                 bug!("TyLayout::field_type: unexpected type `{}`", self.ty)
2015             }
2016         }
2017     }
2018
2019     pub fn field<C: LayoutTyper<'tcx>>(&self, cx: C, i: usize) -> C::TyLayout {
2020         cx.layout_of(cx.normalize_projections(self.field_type(cx, i)))
2021     }
2022 }