]> git.lizzy.rs Git - rust.git/blob - src/librustc/ty/layout.rs
refactor `ParamEnv::empty(Reveal)` into two distinct methods
[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::Primitive::*;
13
14 use session::{self, DataTypeKind, Session};
15 use ty::{self, Ty, TyCtxt, TypeFoldable, ReprOptions, ReprFlags};
16
17 use syntax::ast::{self, FloatTy, IntTy, UintTy};
18 use syntax::attr;
19 use syntax_pos::DUMMY_SP;
20
21 use std::cmp;
22 use std::fmt;
23 use std::i128;
24 use std::iter;
25 use std::mem;
26 use std::ops::{Add, Sub, Mul, AddAssign, Deref, RangeInclusive};
27
28 use ich::StableHashingContext;
29 use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
30                                            StableHasherResult};
31
32 /// Parsed [Data layout](http://llvm.org/docs/LangRef.html#data-layout)
33 /// for a target, which contains everything needed to compute layouts.
34 pub struct TargetDataLayout {
35     pub endian: Endian,
36     pub i1_align: Align,
37     pub i8_align: Align,
38     pub i16_align: Align,
39     pub i32_align: Align,
40     pub i64_align: Align,
41     pub i128_align: Align,
42     pub f32_align: Align,
43     pub f64_align: Align,
44     pub pointer_size: Size,
45     pub pointer_align: Align,
46     pub aggregate_align: Align,
47
48     /// Alignments for vector types.
49     pub vector_align: Vec<(Size, Align)>
50 }
51
52 impl Default for TargetDataLayout {
53     /// Creates an instance of `TargetDataLayout`.
54     fn default() -> TargetDataLayout {
55         TargetDataLayout {
56             endian: Endian::Big,
57             i1_align: Align::from_bits(8, 8).unwrap(),
58             i8_align: Align::from_bits(8, 8).unwrap(),
59             i16_align: Align::from_bits(16, 16).unwrap(),
60             i32_align: Align::from_bits(32, 32).unwrap(),
61             i64_align: Align::from_bits(32, 64).unwrap(),
62             i128_align: Align::from_bits(32, 64).unwrap(),
63             f32_align: Align::from_bits(32, 32).unwrap(),
64             f64_align: Align::from_bits(64, 64).unwrap(),
65             pointer_size: Size::from_bits(64),
66             pointer_align: Align::from_bits(64, 64).unwrap(),
67             aggregate_align: Align::from_bits(0, 64).unwrap(),
68             vector_align: vec![
69                 (Size::from_bits(64), Align::from_bits(64, 64).unwrap()),
70                 (Size::from_bits(128), Align::from_bits(128, 128).unwrap())
71             ]
72         }
73     }
74 }
75
76 impl TargetDataLayout {
77     pub fn parse(sess: &Session) -> TargetDataLayout {
78         // Parse a bit count from a string.
79         let parse_bits = |s: &str, kind: &str, cause: &str| {
80             s.parse::<u64>().unwrap_or_else(|err| {
81                 sess.err(&format!("invalid {} `{}` for `{}` in \"data-layout\": {}",
82                                   kind, s, cause, err));
83                 0
84             })
85         };
86
87         // Parse a size string.
88         let size = |s: &str, cause: &str| {
89             Size::from_bits(parse_bits(s, "size", cause))
90         };
91
92         // Parse an alignment string.
93         let align = |s: &[&str], cause: &str| {
94             if s.is_empty() {
95                 sess.err(&format!("missing alignment for `{}` in \"data-layout\"", cause));
96             }
97             let abi = parse_bits(s[0], "alignment", cause);
98             let pref = s.get(1).map_or(abi, |pref| parse_bits(pref, "alignment", cause));
99             Align::from_bits(abi, pref).unwrap_or_else(|err| {
100                 sess.err(&format!("invalid alignment for `{}` in \"data-layout\": {}",
101                                   cause, err));
102                 Align::from_bits(8, 8).unwrap()
103             })
104         };
105
106         let mut dl = TargetDataLayout::default();
107         let mut i128_align_src = 64;
108         for spec in sess.target.target.data_layout.split("-") {
109             match &spec.split(":").collect::<Vec<_>>()[..] {
110                 &["e"] => dl.endian = Endian::Little,
111                 &["E"] => dl.endian = Endian::Big,
112                 &["a", ref a..] => dl.aggregate_align = align(a, "a"),
113                 &["f32", ref a..] => dl.f32_align = align(a, "f32"),
114                 &["f64", ref a..] => dl.f64_align = align(a, "f64"),
115                 &[p @ "p", s, ref a..] | &[p @ "p0", s, ref a..] => {
116                     dl.pointer_size = size(s, p);
117                     dl.pointer_align = align(a, p);
118                 }
119                 &[s, ref a..] if s.starts_with("i") => {
120                     let bits = match s[1..].parse::<u64>() {
121                         Ok(bits) => bits,
122                         Err(_) => {
123                             size(&s[1..], "i"); // For the user error.
124                             continue;
125                         }
126                     };
127                     let a = align(a, s);
128                     match bits {
129                         1 => dl.i1_align = a,
130                         8 => dl.i8_align = a,
131                         16 => dl.i16_align = a,
132                         32 => dl.i32_align = a,
133                         64 => dl.i64_align = a,
134                         _ => {}
135                     }
136                     if bits >= i128_align_src && bits <= 128 {
137                         // Default alignment for i128 is decided by taking the alignment of
138                         // largest-sized i{64...128}.
139                         i128_align_src = bits;
140                         dl.i128_align = a;
141                     }
142                 }
143                 &[s, ref a..] if s.starts_with("v") => {
144                     let v_size = size(&s[1..], "v");
145                     let a = align(a, s);
146                     if let Some(v) = dl.vector_align.iter_mut().find(|v| v.0 == v_size) {
147                         v.1 = a;
148                         continue;
149                     }
150                     // No existing entry, add a new one.
151                     dl.vector_align.push((v_size, a));
152                 }
153                 _ => {} // Ignore everything else.
154             }
155         }
156
157         // Perform consistency checks against the Target information.
158         let endian_str = match dl.endian {
159             Endian::Little => "little",
160             Endian::Big => "big"
161         };
162         if endian_str != sess.target.target.target_endian {
163             sess.err(&format!("inconsistent target specification: \"data-layout\" claims \
164                                architecture is {}-endian, while \"target-endian\" is `{}`",
165                               endian_str, sess.target.target.target_endian));
166         }
167
168         if dl.pointer_size.bits().to_string() != sess.target.target.target_pointer_width {
169             sess.err(&format!("inconsistent target specification: \"data-layout\" claims \
170                                pointers are {}-bit, while \"target-pointer-width\" is `{}`",
171                               dl.pointer_size.bits(), sess.target.target.target_pointer_width));
172         }
173
174         dl
175     }
176
177     /// Return exclusive upper bound on object size.
178     ///
179     /// The theoretical maximum object size is defined as the maximum positive `isize` value.
180     /// This ensures that the `offset` semantics remain well-defined by allowing it to correctly
181     /// index every address within an object along with one byte past the end, along with allowing
182     /// `isize` to store the difference between any two pointers into an object.
183     ///
184     /// The upper bound on 64-bit currently needs to be lower because LLVM uses a 64-bit integer
185     /// to represent object size in bits. It would need to be 1 << 61 to account for this, but is
186     /// currently conservatively bounded to 1 << 47 as that is enough to cover the current usable
187     /// address space on 64-bit ARMv8 and x86_64.
188     pub fn obj_size_bound(&self) -> u64 {
189         match self.pointer_size.bits() {
190             16 => 1 << 15,
191             32 => 1 << 31,
192             64 => 1 << 47,
193             bits => bug!("obj_size_bound: unknown pointer bit size {}", bits)
194         }
195     }
196
197     pub fn ptr_sized_integer(&self) -> Integer {
198         match self.pointer_size.bits() {
199             16 => I16,
200             32 => I32,
201             64 => I64,
202             bits => bug!("ptr_sized_integer: unknown pointer bit size {}", bits)
203         }
204     }
205
206     pub fn vector_align(&self, vec_size: Size) -> Align {
207         for &(size, align) in &self.vector_align {
208             if size == vec_size {
209                 return align;
210             }
211         }
212         // Default to natural alignment, which is what LLVM does.
213         // That is, use the size, rounded up to a power of 2.
214         let align = vec_size.bytes().next_power_of_two();
215         Align::from_bytes(align, align).unwrap()
216     }
217 }
218
219 pub trait HasDataLayout: Copy {
220     fn data_layout(&self) -> &TargetDataLayout;
221 }
222
223 impl<'a> HasDataLayout for &'a TargetDataLayout {
224     fn data_layout(&self) -> &TargetDataLayout {
225         self
226     }
227 }
228
229 /// Endianness of the target, which must match cfg(target-endian).
230 #[derive(Copy, Clone)]
231 pub enum Endian {
232     Little,
233     Big
234 }
235
236 /// Size of a type in bytes.
237 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
238 pub struct Size {
239     raw: u64
240 }
241
242 impl Size {
243     pub fn from_bits(bits: u64) -> Size {
244         // Avoid potential overflow from `bits + 7`.
245         Size::from_bytes(bits / 8 + ((bits % 8) + 7) / 8)
246     }
247
248     pub fn from_bytes(bytes: u64) -> Size {
249         if bytes >= (1 << 61) {
250             bug!("Size::from_bytes: {} bytes in bits doesn't fit in u64", bytes)
251         }
252         Size {
253             raw: bytes
254         }
255     }
256
257     pub fn bytes(self) -> u64 {
258         self.raw
259     }
260
261     pub fn bits(self) -> u64 {
262         self.bytes() * 8
263     }
264
265     pub fn abi_align(self, align: Align) -> Size {
266         let mask = align.abi() - 1;
267         Size::from_bytes((self.bytes() + mask) & !mask)
268     }
269
270     pub fn is_abi_aligned(self, align: Align) -> bool {
271         let mask = align.abi() - 1;
272         self.bytes() & mask == 0
273     }
274
275     pub fn checked_add<C: HasDataLayout>(self, offset: Size, cx: C) -> Option<Size> {
276         let dl = cx.data_layout();
277
278         // Each Size is less than dl.obj_size_bound(), so the sum is
279         // also less than 1 << 62 (and therefore can't overflow).
280         let bytes = self.bytes() + offset.bytes();
281
282         if bytes < dl.obj_size_bound() {
283             Some(Size::from_bytes(bytes))
284         } else {
285             None
286         }
287     }
288
289     pub fn checked_mul<C: HasDataLayout>(self, count: u64, cx: C) -> Option<Size> {
290         let dl = cx.data_layout();
291
292         match self.bytes().checked_mul(count) {
293             Some(bytes) if bytes < dl.obj_size_bound() => {
294                 Some(Size::from_bytes(bytes))
295             }
296             _ => None
297         }
298     }
299 }
300
301 // Panicking addition, subtraction and multiplication for convenience.
302 // Avoid during layout computation, return `LayoutError` instead.
303
304 impl Add for Size {
305     type Output = Size;
306     fn add(self, other: Size) -> Size {
307         // Each Size is less than 1 << 61, so the sum is
308         // less than 1 << 62 (and therefore can't overflow).
309         Size::from_bytes(self.bytes() + other.bytes())
310     }
311 }
312
313 impl Sub for Size {
314     type Output = Size;
315     fn sub(self, other: Size) -> Size {
316         // Each Size is less than 1 << 61, so an underflow
317         // would result in a value larger than 1 << 61,
318         // which Size::from_bytes will catch for us.
319         Size::from_bytes(self.bytes() - other.bytes())
320     }
321 }
322
323 impl Mul<u64> for Size {
324     type Output = Size;
325     fn mul(self, count: u64) -> Size {
326         match self.bytes().checked_mul(count) {
327             Some(bytes) => Size::from_bytes(bytes),
328             None => {
329                 bug!("Size::mul: {} * {} doesn't fit in u64", self.bytes(), count)
330             }
331         }
332     }
333 }
334
335 impl AddAssign for Size {
336     fn add_assign(&mut self, other: Size) {
337         *self = *self + other;
338     }
339 }
340
341 /// Alignment of a type in bytes, both ABI-mandated and preferred.
342 /// Each field is a power of two, giving the alignment a maximum
343 /// value of 2<sup>(2<sup>8</sup> - 1)</sup>, which is limited by LLVM to a i32, with
344 /// a maximum capacity of 2<sup>31</sup> - 1 or 2147483647.
345 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
346 pub struct Align {
347     abi: u8,
348     pref: u8,
349 }
350
351 impl Align {
352     pub fn from_bits(abi: u64, pref: u64) -> Result<Align, String> {
353         Align::from_bytes(Size::from_bits(abi).bytes(),
354                           Size::from_bits(pref).bytes())
355     }
356
357     pub fn from_bytes(abi: u64, pref: u64) -> Result<Align, String> {
358         let log2 = |align: u64| {
359             // Treat an alignment of 0 bytes like 1-byte alignment.
360             if align == 0 {
361                 return Ok(0);
362             }
363
364             let mut bytes = align;
365             let mut pow: u8 = 0;
366             while (bytes & 1) == 0 {
367                 pow += 1;
368                 bytes >>= 1;
369             }
370             if bytes != 1 {
371                 Err(format!("`{}` is not a power of 2", align))
372             } else if pow > 30 {
373                 Err(format!("`{}` is too large", align))
374             } else {
375                 Ok(pow)
376             }
377         };
378
379         Ok(Align {
380             abi: log2(abi)?,
381             pref: log2(pref)?,
382         })
383     }
384
385     pub fn abi(self) -> u64 {
386         1 << self.abi
387     }
388
389     pub fn pref(self) -> u64 {
390         1 << self.pref
391     }
392
393     pub fn abi_bits(self) -> u64 {
394         self.abi() * 8
395     }
396
397     pub fn pref_bits(self) -> u64 {
398         self.pref() * 8
399     }
400
401     pub fn min(self, other: Align) -> Align {
402         Align {
403             abi: cmp::min(self.abi, other.abi),
404             pref: cmp::min(self.pref, other.pref),
405         }
406     }
407
408     pub fn max(self, other: Align) -> Align {
409         Align {
410             abi: cmp::max(self.abi, other.abi),
411             pref: cmp::max(self.pref, other.pref),
412         }
413     }
414 }
415
416 /// Integers, also used for enum discriminants.
417 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
418 pub enum Integer {
419     I8,
420     I16,
421     I32,
422     I64,
423     I128,
424 }
425
426 impl<'a, 'tcx> Integer {
427     pub fn size(&self) -> Size {
428         match *self {
429             I8 => Size::from_bytes(1),
430             I16 => Size::from_bytes(2),
431             I32 => Size::from_bytes(4),
432             I64  => Size::from_bytes(8),
433             I128  => Size::from_bytes(16),
434         }
435     }
436
437     pub fn align<C: HasDataLayout>(&self, cx: C) -> Align {
438         let dl = cx.data_layout();
439
440         match *self {
441             I8 => dl.i8_align,
442             I16 => dl.i16_align,
443             I32 => dl.i32_align,
444             I64 => dl.i64_align,
445             I128 => dl.i128_align,
446         }
447     }
448
449     pub fn to_ty(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, signed: bool) -> Ty<'tcx> {
450         match (*self, signed) {
451             (I8, false) => tcx.types.u8,
452             (I16, false) => tcx.types.u16,
453             (I32, false) => tcx.types.u32,
454             (I64, false) => tcx.types.u64,
455             (I128, false) => tcx.types.u128,
456             (I8, true) => tcx.types.i8,
457             (I16, true) => tcx.types.i16,
458             (I32, true) => tcx.types.i32,
459             (I64, true) => tcx.types.i64,
460             (I128, true) => tcx.types.i128,
461         }
462     }
463
464     /// Find the smallest Integer type which can represent the signed value.
465     pub fn fit_signed(x: i128) -> Integer {
466         match x {
467             -0x0000_0000_0000_0080...0x0000_0000_0000_007f => I8,
468             -0x0000_0000_0000_8000...0x0000_0000_0000_7fff => I16,
469             -0x0000_0000_8000_0000...0x0000_0000_7fff_ffff => I32,
470             -0x8000_0000_0000_0000...0x7fff_ffff_ffff_ffff => I64,
471             _ => I128
472         }
473     }
474
475     /// Find the smallest Integer type which can represent the unsigned value.
476     pub fn fit_unsigned(x: u128) -> Integer {
477         match x {
478             0...0x0000_0000_0000_00ff => I8,
479             0...0x0000_0000_0000_ffff => I16,
480             0...0x0000_0000_ffff_ffff => I32,
481             0...0xffff_ffff_ffff_ffff => I64,
482             _ => I128,
483         }
484     }
485
486     /// Find the smallest integer with the given alignment.
487     pub fn for_abi_align<C: HasDataLayout>(cx: C, align: Align) -> Option<Integer> {
488         let dl = cx.data_layout();
489
490         let wanted = align.abi();
491         for &candidate in &[I8, I16, I32, I64, I128] {
492             if wanted == candidate.align(dl).abi() && wanted == candidate.size().bytes() {
493                 return Some(candidate);
494             }
495         }
496         None
497     }
498
499     /// Find the largest integer with the given alignment or less.
500     pub fn approximate_abi_align<C: HasDataLayout>(cx: C, align: Align) -> Integer {
501         let dl = cx.data_layout();
502
503         let wanted = align.abi();
504         // FIXME(eddyb) maybe include I128 in the future, when it works everywhere.
505         for &candidate in &[I64, I32, I16] {
506             if wanted >= candidate.align(dl).abi() && wanted >= candidate.size().bytes() {
507                 return candidate;
508             }
509         }
510         I8
511     }
512
513     /// Get the Integer type from an attr::IntType.
514     pub fn from_attr<C: HasDataLayout>(cx: C, ity: attr::IntType) -> Integer {
515         let dl = cx.data_layout();
516
517         match ity {
518             attr::SignedInt(IntTy::I8) | attr::UnsignedInt(UintTy::U8) => I8,
519             attr::SignedInt(IntTy::I16) | attr::UnsignedInt(UintTy::U16) => I16,
520             attr::SignedInt(IntTy::I32) | attr::UnsignedInt(UintTy::U32) => I32,
521             attr::SignedInt(IntTy::I64) | attr::UnsignedInt(UintTy::U64) => I64,
522             attr::SignedInt(IntTy::I128) | attr::UnsignedInt(UintTy::U128) => I128,
523             attr::SignedInt(IntTy::Isize) | attr::UnsignedInt(UintTy::Usize) => {
524                 dl.ptr_sized_integer()
525             }
526         }
527     }
528
529     /// Find the appropriate Integer type and signedness for the given
530     /// signed discriminant range and #[repr] attribute.
531     /// N.B.: u128 values above i128::MAX will be treated as signed, but
532     /// that shouldn't affect anything, other than maybe debuginfo.
533     fn repr_discr(tcx: TyCtxt<'a, 'tcx, 'tcx>,
534                   ty: Ty<'tcx>,
535                   repr: &ReprOptions,
536                   min: i128,
537                   max: i128)
538                   -> (Integer, bool) {
539         // Theoretically, negative values could be larger in unsigned representation
540         // than the unsigned representation of the signed minimum. However, if there
541         // are any negative values, the only valid unsigned representation is u128
542         // which can fit all i128 values, so the result remains unaffected.
543         let unsigned_fit = Integer::fit_unsigned(cmp::max(min as u128, max as u128));
544         let signed_fit = cmp::max(Integer::fit_signed(min), Integer::fit_signed(max));
545
546         let mut min_from_extern = None;
547         let min_default = I8;
548
549         if let Some(ity) = repr.int {
550             let discr = Integer::from_attr(tcx, ity);
551             let fit = if ity.is_signed() { signed_fit } else { unsigned_fit };
552             if discr < fit {
553                 bug!("Integer::repr_discr: `#[repr]` hint too small for \
554                   discriminant range of enum `{}", ty)
555             }
556             return (discr, ity.is_signed());
557         }
558
559         if repr.c() {
560             match &tcx.sess.target.target.arch[..] {
561                 // WARNING: the ARM EABI has two variants; the one corresponding
562                 // to `at_least == I32` appears to be used on Linux and NetBSD,
563                 // but some systems may use the variant corresponding to no
564                 // lower bound.  However, we don't run on those yet...?
565                 "arm" => min_from_extern = Some(I32),
566                 _ => min_from_extern = Some(I32),
567             }
568         }
569
570         let at_least = min_from_extern.unwrap_or(min_default);
571
572         // If there are no negative values, we can use the unsigned fit.
573         if min >= 0 {
574             (cmp::max(unsigned_fit, at_least), false)
575         } else {
576             (cmp::max(signed_fit, at_least), true)
577         }
578     }
579 }
580
581 /// Fundamental unit of memory access and layout.
582 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
583 pub enum Primitive {
584     /// The `bool` is the signedness of the `Integer` type.
585     ///
586     /// One would think we would not care about such details this low down,
587     /// but some ABIs are described in terms of C types and ISAs where the
588     /// integer arithmetic is done on {sign,zero}-extended registers, e.g.
589     /// a negative integer passed by zero-extension will appear positive in
590     /// the callee, and most operations on it will produce the wrong values.
591     Int(Integer, bool),
592     F32,
593     F64,
594     Pointer
595 }
596
597 impl<'a, 'tcx> Primitive {
598     pub fn size<C: HasDataLayout>(self, cx: C) -> Size {
599         let dl = cx.data_layout();
600
601         match self {
602             Int(i, _) => i.size(),
603             F32 => Size::from_bits(32),
604             F64 => Size::from_bits(64),
605             Pointer => dl.pointer_size
606         }
607     }
608
609     pub fn align<C: HasDataLayout>(self, cx: C) -> Align {
610         let dl = cx.data_layout();
611
612         match self {
613             Int(i, _) => i.align(dl),
614             F32 => dl.f32_align,
615             F64 => dl.f64_align,
616             Pointer => dl.pointer_align
617         }
618     }
619
620     pub fn to_ty(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> {
621         match *self {
622             Int(i, signed) => i.to_ty(tcx, signed),
623             F32 => tcx.types.f32,
624             F64 => tcx.types.f64,
625             Pointer => tcx.mk_mut_ptr(tcx.mk_nil()),
626         }
627     }
628 }
629
630 /// Information about one scalar component of a Rust type.
631 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
632 pub struct Scalar {
633     pub value: Primitive,
634
635     /// Inclusive wrap-around range of valid values, that is, if
636     /// min > max, it represents min..=u128::MAX followed by 0..=max.
637     // FIXME(eddyb) always use the shortest range, e.g. by finding
638     // the largest space between two consecutive valid values and
639     // taking everything else as the (shortest) valid range.
640     pub valid_range: RangeInclusive<u128>,
641 }
642
643 impl Scalar {
644     pub fn is_bool(&self) -> bool {
645         if let Int(I8, _) = self.value {
646             self.valid_range == (0..=1)
647         } else {
648             false
649         }
650     }
651 }
652
653 /// The first half of a fat pointer.
654 ///
655 /// - For a trait object, this is the address of the box.
656 /// - For a slice, this is the base address.
657 pub const FAT_PTR_ADDR: usize = 0;
658
659 /// The second half of a fat pointer.
660 ///
661 /// - For a trait object, this is the address of the vtable.
662 /// - For a slice, this is the length.
663 pub const FAT_PTR_EXTRA: usize = 1;
664
665 /// Describes how the fields of a type are located in memory.
666 #[derive(PartialEq, Eq, Hash, Debug)]
667 pub enum FieldPlacement {
668     /// All fields start at no offset. The `usize` is the field count.
669     Union(usize),
670
671     /// Array/vector-like placement, with all fields of identical types.
672     Array {
673         stride: Size,
674         count: u64
675     },
676
677     /// Struct-like placement, with precomputed offsets.
678     ///
679     /// Fields are guaranteed to not overlap, but note that gaps
680     /// before, between and after all the fields are NOT always
681     /// padding, and as such their contents may not be discarded.
682     /// For example, enum variants leave a gap at the start,
683     /// where the discriminant field in the enum layout goes.
684     Arbitrary {
685         /// Offsets for the first byte of each field,
686         /// ordered to match the source definition order.
687         /// This vector does not go in increasing order.
688         // FIXME(eddyb) use small vector optimization for the common case.
689         offsets: Vec<Size>,
690
691         /// Maps source order field indices to memory order indices,
692         /// depending how fields were permuted.
693         // FIXME(camlorn) also consider small vector  optimization here.
694         memory_index: Vec<u32>
695     }
696 }
697
698 impl FieldPlacement {
699     pub fn count(&self) -> usize {
700         match *self {
701             FieldPlacement::Union(count) => count,
702             FieldPlacement::Array { count, .. } => {
703                 let usize_count = count as usize;
704                 assert_eq!(usize_count as u64, count);
705                 usize_count
706             }
707             FieldPlacement::Arbitrary { ref offsets, .. } => offsets.len()
708         }
709     }
710
711     pub fn offset(&self, i: usize) -> Size {
712         match *self {
713             FieldPlacement::Union(_) => Size::from_bytes(0),
714             FieldPlacement::Array { stride, count } => {
715                 let i = i as u64;
716                 assert!(i < count);
717                 stride * i
718             }
719             FieldPlacement::Arbitrary { ref offsets, .. } => offsets[i]
720         }
721     }
722
723     pub fn memory_index(&self, i: usize) -> usize {
724         match *self {
725             FieldPlacement::Union(_) |
726             FieldPlacement::Array { .. } => i,
727             FieldPlacement::Arbitrary { ref memory_index, .. } => {
728                 let r = memory_index[i];
729                 assert_eq!(r as usize as u32, r);
730                 r as usize
731             }
732         }
733     }
734
735     /// Get source indices of the fields by increasing offsets.
736     #[inline]
737     pub fn index_by_increasing_offset<'a>(&'a self) -> impl iter::Iterator<Item=usize>+'a {
738         let mut inverse_small = [0u8; 64];
739         let mut inverse_big = vec![];
740         let use_small = self.count() <= inverse_small.len();
741
742         // We have to write this logic twice in order to keep the array small.
743         if let FieldPlacement::Arbitrary { ref memory_index, .. } = *self {
744             if use_small {
745                 for i in 0..self.count() {
746                     inverse_small[memory_index[i] as usize] = i as u8;
747                 }
748             } else {
749                 inverse_big = vec![0; self.count()];
750                 for i in 0..self.count() {
751                     inverse_big[memory_index[i] as usize] = i as u32;
752                 }
753             }
754         }
755
756         (0..self.count()).map(move |i| {
757             match *self {
758                 FieldPlacement::Union(_) |
759                 FieldPlacement::Array { .. } => i,
760                 FieldPlacement::Arbitrary { .. } => {
761                     if use_small { inverse_small[i] as usize }
762                     else { inverse_big[i] as usize }
763                 }
764             }
765         })
766     }
767 }
768
769 /// Describes how values of the type are passed by target ABIs,
770 /// in terms of categories of C types there are ABI rules for.
771 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
772 pub enum Abi {
773     Uninhabited,
774     Scalar(Scalar),
775     ScalarPair(Scalar, Scalar),
776     Vector {
777         element: Scalar,
778         count: u64
779     },
780     Aggregate {
781         /// If true, the size is exact, otherwise it's only a lower bound.
782         sized: bool,
783     }
784 }
785
786 impl Abi {
787     /// Returns true if the layout corresponds to an unsized type.
788     pub fn is_unsized(&self) -> bool {
789         match *self {
790             Abi::Uninhabited |
791             Abi::Scalar(_) |
792             Abi::ScalarPair(..) |
793             Abi::Vector { .. } => false,
794             Abi::Aggregate { sized } => !sized
795         }
796     }
797
798     /// Returns true if this is a single signed integer scalar
799     pub fn is_signed(&self) -> bool {
800         match *self {
801             Abi::Scalar(ref scal) => match scal.value {
802                 Primitive::Int(_, signed) => signed,
803                 _ => false,
804             },
805             _ => false,
806         }
807     }
808 }
809
810 #[derive(PartialEq, Eq, Hash, Debug)]
811 pub enum Variants {
812     /// Single enum variants, structs/tuples, unions, and all non-ADTs.
813     Single {
814         index: usize
815     },
816
817     /// General-case enums: for each case there is a struct, and they all have
818     /// all space reserved for the discriminant, and their first field starts
819     /// at a non-0 offset, after where the discriminant would go.
820     Tagged {
821         discr: Scalar,
822         variants: Vec<LayoutDetails>,
823     },
824
825     /// Multiple cases distinguished by a niche (values invalid for a type):
826     /// the variant `dataful_variant` contains a niche at an arbitrary
827     /// offset (field 0 of the enum), which for a variant with discriminant
828     /// `d` is set to `(d - niche_variants.start).wrapping_add(niche_start)`.
829     ///
830     /// For example, `Option<(usize, &T)>`  is represented such that
831     /// `None` has a null pointer for the second tuple field, and
832     /// `Some` is the identity function (with a non-null reference).
833     NicheFilling {
834         dataful_variant: usize,
835         niche_variants: RangeInclusive<usize>,
836         niche: Scalar,
837         niche_start: u128,
838         variants: Vec<LayoutDetails>,
839     }
840 }
841
842 #[derive(Copy, Clone, Debug)]
843 pub enum LayoutError<'tcx> {
844     Unknown(Ty<'tcx>),
845     SizeOverflow(Ty<'tcx>)
846 }
847
848 impl<'tcx> fmt::Display for LayoutError<'tcx> {
849     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
850         match *self {
851             LayoutError::Unknown(ty) => {
852                 write!(f, "the type `{:?}` has an unknown layout", ty)
853             }
854             LayoutError::SizeOverflow(ty) => {
855                 write!(f, "the type `{:?}` is too big for the current architecture", ty)
856             }
857         }
858     }
859 }
860
861 #[derive(PartialEq, Eq, Hash, Debug)]
862 pub struct LayoutDetails {
863     pub variants: Variants,
864     pub fields: FieldPlacement,
865     pub abi: Abi,
866     pub align: Align,
867     pub size: Size
868 }
869
870 impl LayoutDetails {
871     fn scalar<C: HasDataLayout>(cx: C, scalar: Scalar) -> Self {
872         let size = scalar.value.size(cx);
873         let align = scalar.value.align(cx);
874         LayoutDetails {
875             variants: Variants::Single { index: 0 },
876             fields: FieldPlacement::Union(0),
877             abi: Abi::Scalar(scalar),
878             size,
879             align,
880         }
881     }
882
883     fn uninhabited(field_count: usize) -> Self {
884         let align = Align::from_bytes(1, 1).unwrap();
885         LayoutDetails {
886             variants: Variants::Single { index: 0 },
887             fields: FieldPlacement::Union(field_count),
888             abi: Abi::Uninhabited,
889             align,
890             size: Size::from_bytes(0)
891         }
892     }
893 }
894
895 fn layout_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
896                         query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>)
897                         -> Result<&'tcx LayoutDetails, LayoutError<'tcx>>
898 {
899     let (param_env, ty) = query.into_parts();
900
901     let rec_limit = tcx.sess.recursion_limit.get();
902     let depth = tcx.layout_depth.get();
903     if depth > rec_limit {
904         tcx.sess.fatal(
905             &format!("overflow representing the type `{}`", ty));
906     }
907
908     tcx.layout_depth.set(depth+1);
909     let cx = LayoutCx { tcx, param_env };
910     let layout = cx.layout_raw_uncached(ty);
911     tcx.layout_depth.set(depth);
912
913     layout
914 }
915
916 pub fn provide(providers: &mut ty::maps::Providers) {
917     *providers = ty::maps::Providers {
918         layout_raw,
919         ..*providers
920     };
921 }
922
923 #[derive(Copy, Clone)]
924 pub struct LayoutCx<'tcx, C> {
925     pub tcx: C,
926     pub param_env: ty::ParamEnv<'tcx>
927 }
928
929 impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
930     fn layout_raw_uncached(self, ty: Ty<'tcx>)
931                            -> Result<&'tcx LayoutDetails, LayoutError<'tcx>> {
932         let tcx = self.tcx;
933         let param_env = self.param_env;
934         let dl = self.data_layout();
935         let scalar_unit = |value: Primitive| {
936             let bits = value.size(dl).bits();
937             assert!(bits <= 128);
938             Scalar {
939                 value,
940                 valid_range: 0..=(!0 >> (128 - bits))
941             }
942         };
943         let scalar = |value: Primitive| {
944             tcx.intern_layout(LayoutDetails::scalar(self, scalar_unit(value)))
945         };
946         let scalar_pair = |a: Scalar, b: Scalar| {
947             let align = a.value.align(dl).max(b.value.align(dl)).max(dl.aggregate_align);
948             let b_offset = a.value.size(dl).abi_align(b.value.align(dl));
949             let size = (b_offset + b.value.size(dl)).abi_align(align);
950             LayoutDetails {
951                 variants: Variants::Single { index: 0 },
952                 fields: FieldPlacement::Arbitrary {
953                     offsets: vec![Size::from_bytes(0), b_offset],
954                     memory_index: vec![0, 1]
955                 },
956                 abi: Abi::ScalarPair(a, b),
957                 align,
958                 size
959             }
960         };
961
962         #[derive(Copy, Clone, Debug)]
963         enum StructKind {
964             /// A tuple, closure, or univariant which cannot be coerced to unsized.
965             AlwaysSized,
966             /// A univariant, the last field of which may be coerced to unsized.
967             MaybeUnsized,
968             /// A univariant, but with a prefix of an arbitrary size & alignment (e.g. enum tag).
969             Prefixed(Size, Align),
970         }
971         let univariant_uninterned = |fields: &[TyLayout], repr: &ReprOptions, kind| {
972             let packed = repr.packed();
973             if packed && repr.align > 0 {
974                 bug!("struct cannot be packed and aligned");
975             }
976
977             let mut align = if packed {
978                 dl.i8_align
979             } else {
980                 dl.aggregate_align
981             };
982
983             let mut sized = true;
984             let mut offsets = vec![Size::from_bytes(0); fields.len()];
985             let mut inverse_memory_index: Vec<u32> = (0..fields.len() as u32).collect();
986
987             // Anything with repr(C) or repr(packed) doesn't optimize.
988             let mut optimize = (repr.flags & ReprFlags::IS_UNOPTIMISABLE).is_empty();
989             if let StructKind::Prefixed(_, align) = kind {
990                 optimize &= align.abi() == 1;
991             }
992
993             if optimize {
994                 let end = if let StructKind::MaybeUnsized = kind {
995                     fields.len() - 1
996                 } else {
997                     fields.len()
998                 };
999                 let optimizing = &mut inverse_memory_index[..end];
1000                 match kind {
1001                     StructKind::AlwaysSized |
1002                     StructKind::MaybeUnsized => {
1003                         optimizing.sort_by_key(|&x| {
1004                             // Place ZSTs first to avoid "interesting offsets",
1005                             // especially with only one or two non-ZST fields.
1006                             let f = &fields[x as usize];
1007                             (!f.is_zst(), cmp::Reverse(f.align.abi()))
1008                         })
1009                     }
1010                     StructKind::Prefixed(..) => {
1011                         optimizing.sort_by_key(|&x| fields[x as usize].align.abi());
1012                     }
1013                 }
1014             }
1015
1016             // inverse_memory_index holds field indices by increasing memory offset.
1017             // That is, if field 5 has offset 0, the first element of inverse_memory_index is 5.
1018             // We now write field offsets to the corresponding offset slot;
1019             // field 5 with offset 0 puts 0 in offsets[5].
1020             // At the bottom of this function, we use inverse_memory_index to produce memory_index.
1021
1022             let mut offset = Size::from_bytes(0);
1023
1024             if let StructKind::Prefixed(prefix_size, prefix_align) = kind {
1025                 if !packed {
1026                     align = align.max(prefix_align);
1027                 }
1028                 offset = prefix_size.abi_align(prefix_align);
1029             }
1030
1031             for &i in &inverse_memory_index {
1032                 let field = fields[i as usize];
1033                 if !sized {
1034                     bug!("univariant: field #{} of `{}` comes after unsized field",
1035                         offsets.len(), ty);
1036                 }
1037
1038                 if field.abi == Abi::Uninhabited {
1039                     return Ok(LayoutDetails::uninhabited(fields.len()));
1040                 }
1041
1042                 if field.is_unsized() {
1043                     sized = false;
1044                 }
1045
1046                 // Invariant: offset < dl.obj_size_bound() <= 1<<61
1047                 if !packed {
1048                     offset = offset.abi_align(field.align);
1049                     align = align.max(field.align);
1050                 }
1051
1052                 debug!("univariant offset: {:?} field: {:#?}", offset, field);
1053                 offsets[i as usize] = offset;
1054
1055                 offset = offset.checked_add(field.size, dl)
1056                     .ok_or(LayoutError::SizeOverflow(ty))?;
1057             }
1058
1059             if repr.align > 0 {
1060                 let repr_align = repr.align as u64;
1061                 align = align.max(Align::from_bytes(repr_align, repr_align).unwrap());
1062                 debug!("univariant repr_align: {:?}", repr_align);
1063             }
1064
1065             debug!("univariant min_size: {:?}", offset);
1066             let min_size = offset;
1067
1068             // As stated above, inverse_memory_index holds field indices by increasing offset.
1069             // This makes it an already-sorted view of the offsets vec.
1070             // To invert it, consider:
1071             // If field 5 has offset 0, offsets[0] is 5, and memory_index[5] should be 0.
1072             // Field 5 would be the first element, so memory_index is i:
1073             // Note: if we didn't optimize, it's already right.
1074
1075             let mut memory_index;
1076             if optimize {
1077                 memory_index = vec![0; inverse_memory_index.len()];
1078
1079                 for i in 0..inverse_memory_index.len() {
1080                     memory_index[inverse_memory_index[i] as usize]  = i as u32;
1081                 }
1082             } else {
1083                 memory_index = inverse_memory_index;
1084             }
1085
1086             let size = min_size.abi_align(align);
1087             let mut abi = Abi::Aggregate { sized };
1088
1089             // Unpack newtype ABIs and find scalar pairs.
1090             if sized && size.bytes() > 0 {
1091                 // All other fields must be ZSTs, and we need them to all start at 0.
1092                 let mut zst_offsets =
1093                     offsets.iter().enumerate().filter(|&(i, _)| fields[i].is_zst());
1094                 if zst_offsets.all(|(_, o)| o.bytes() == 0) {
1095                     let mut non_zst_fields =
1096                         fields.iter().enumerate().filter(|&(_, f)| !f.is_zst());
1097
1098                     match (non_zst_fields.next(), non_zst_fields.next(), non_zst_fields.next()) {
1099                         // We have exactly one non-ZST field.
1100                         (Some((i, field)), None, None) => {
1101                             // Field fills the struct and it has a scalar or scalar pair ABI.
1102                             if offsets[i].bytes() == 0 &&
1103                                align.abi() == field.align.abi() &&
1104                                size == field.size {
1105                                 match field.abi {
1106                                     // For plain scalars, or vectors of them, we can't unpack
1107                                     // newtypes for `#[repr(C)]`, as that affects C ABIs.
1108                                     Abi::Scalar(_) | Abi::Vector { .. } if optimize => {
1109                                         abi = field.abi.clone();
1110                                     }
1111                                     // But scalar pairs are Rust-specific and get
1112                                     // treated as aggregates by C ABIs anyway.
1113                                     Abi::ScalarPair(..) => {
1114                                         abi = field.abi.clone();
1115                                     }
1116                                     _ => {}
1117                                 }
1118                             }
1119                         }
1120
1121                         // Two non-ZST fields, and they're both scalars.
1122                         (Some((i, &TyLayout {
1123                             details: &LayoutDetails { abi: Abi::Scalar(ref a), .. }, ..
1124                         })), Some((j, &TyLayout {
1125                             details: &LayoutDetails { abi: Abi::Scalar(ref b), .. }, ..
1126                         })), None) => {
1127                             // Order by the memory placement, not source order.
1128                             let ((i, a), (j, b)) = if offsets[i] < offsets[j] {
1129                                 ((i, a), (j, b))
1130                             } else {
1131                                 ((j, b), (i, a))
1132                             };
1133                             let pair = scalar_pair(a.clone(), b.clone());
1134                             let pair_offsets = match pair.fields {
1135                                 FieldPlacement::Arbitrary {
1136                                     ref offsets,
1137                                     ref memory_index
1138                                 } => {
1139                                     assert_eq!(memory_index, &[0, 1]);
1140                                     offsets
1141                                 }
1142                                 _ => bug!()
1143                             };
1144                             if offsets[i] == pair_offsets[0] &&
1145                                offsets[j] == pair_offsets[1] &&
1146                                align == pair.align &&
1147                                size == pair.size {
1148                                 // We can use `ScalarPair` only when it matches our
1149                                 // already computed layout (including `#[repr(C)]`).
1150                                 abi = pair.abi;
1151                             }
1152                         }
1153
1154                         _ => {}
1155                     }
1156                 }
1157             }
1158
1159             Ok(LayoutDetails {
1160                 variants: Variants::Single { index: 0 },
1161                 fields: FieldPlacement::Arbitrary {
1162                     offsets,
1163                     memory_index
1164                 },
1165                 abi,
1166                 align,
1167                 size
1168             })
1169         };
1170         let univariant = |fields: &[TyLayout], repr: &ReprOptions, kind| {
1171             Ok(tcx.intern_layout(univariant_uninterned(fields, repr, kind)?))
1172         };
1173         assert!(!ty.has_infer_types());
1174
1175         Ok(match ty.sty {
1176             // Basic scalars.
1177             ty::TyBool => {
1178                 tcx.intern_layout(LayoutDetails::scalar(self, Scalar {
1179                     value: Int(I8, false),
1180                     valid_range: 0..=1
1181                 }))
1182             }
1183             ty::TyChar => {
1184                 tcx.intern_layout(LayoutDetails::scalar(self, Scalar {
1185                     value: Int(I32, false),
1186                     valid_range: 0..=0x10FFFF
1187                 }))
1188             }
1189             ty::TyInt(ity) => {
1190                 scalar(Int(Integer::from_attr(dl, attr::SignedInt(ity)), true))
1191             }
1192             ty::TyUint(ity) => {
1193                 scalar(Int(Integer::from_attr(dl, attr::UnsignedInt(ity)), false))
1194             }
1195             ty::TyFloat(FloatTy::F32) => scalar(F32),
1196             ty::TyFloat(FloatTy::F64) => scalar(F64),
1197             ty::TyFnPtr(_) => {
1198                 let mut ptr = scalar_unit(Pointer);
1199                 ptr.valid_range.start = 1;
1200                 tcx.intern_layout(LayoutDetails::scalar(self, ptr))
1201             }
1202
1203             // The never type.
1204             ty::TyNever => {
1205                 tcx.intern_layout(LayoutDetails::uninhabited(0))
1206             }
1207
1208             // Potentially-fat pointers.
1209             ty::TyRef(_, ty::TypeAndMut { ty: pointee, .. }) |
1210             ty::TyRawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
1211                 let mut data_ptr = scalar_unit(Pointer);
1212                 if !ty.is_unsafe_ptr() {
1213                     data_ptr.valid_range.start = 1;
1214                 }
1215
1216                 let pointee = tcx.normalize_associated_type_in_env(&pointee, param_env);
1217                 if pointee.is_sized(tcx.at(DUMMY_SP), param_env) {
1218                     return Ok(tcx.intern_layout(LayoutDetails::scalar(self, data_ptr)));
1219                 }
1220
1221                 let unsized_part = tcx.struct_tail(pointee);
1222                 let metadata = match unsized_part.sty {
1223                     ty::TyForeign(..) => {
1224                         return Ok(tcx.intern_layout(LayoutDetails::scalar(self, data_ptr)));
1225                     }
1226                     ty::TySlice(_) | ty::TyStr => {
1227                         scalar_unit(Int(dl.ptr_sized_integer(), false))
1228                     }
1229                     ty::TyDynamic(..) => {
1230                         let mut vtable = scalar_unit(Pointer);
1231                         vtable.valid_range.start = 1;
1232                         vtable
1233                     }
1234                     _ => return Err(LayoutError::Unknown(unsized_part))
1235                 };
1236
1237                 // Effectively a (ptr, meta) tuple.
1238                 tcx.intern_layout(scalar_pair(data_ptr, metadata))
1239             }
1240
1241             // Arrays and slices.
1242             ty::TyArray(element, mut count) => {
1243                 if count.has_projections() {
1244                     count = tcx.normalize_associated_type_in_env(&count, param_env);
1245                     if count.has_projections() {
1246                         return Err(LayoutError::Unknown(ty));
1247                     }
1248                 }
1249
1250                 let element = self.layout_of(element)?;
1251                 let count = count.val.unwrap_u64();
1252                 let size = element.size.checked_mul(count, dl)
1253                     .ok_or(LayoutError::SizeOverflow(ty))?;
1254
1255                 tcx.intern_layout(LayoutDetails {
1256                     variants: Variants::Single { index: 0 },
1257                     fields: FieldPlacement::Array {
1258                         stride: element.size,
1259                         count
1260                     },
1261                     abi: Abi::Aggregate { sized: true },
1262                     align: element.align,
1263                     size
1264                 })
1265             }
1266             ty::TySlice(element) => {
1267                 let element = self.layout_of(element)?;
1268                 tcx.intern_layout(LayoutDetails {
1269                     variants: Variants::Single { index: 0 },
1270                     fields: FieldPlacement::Array {
1271                         stride: element.size,
1272                         count: 0
1273                     },
1274                     abi: Abi::Aggregate { sized: false },
1275                     align: element.align,
1276                     size: Size::from_bytes(0)
1277                 })
1278             }
1279             ty::TyStr => {
1280                 tcx.intern_layout(LayoutDetails {
1281                     variants: Variants::Single { index: 0 },
1282                     fields: FieldPlacement::Array {
1283                         stride: Size::from_bytes(1),
1284                         count: 0
1285                     },
1286                     abi: Abi::Aggregate { sized: false },
1287                     align: dl.i8_align,
1288                     size: Size::from_bytes(0)
1289                 })
1290             }
1291
1292             // Odd unit types.
1293             ty::TyFnDef(..) => {
1294                 univariant(&[], &ReprOptions::default(), StructKind::AlwaysSized)?
1295             }
1296             ty::TyDynamic(..) | ty::TyForeign(..) => {
1297                 let mut unit = univariant_uninterned(&[], &ReprOptions::default(),
1298                   StructKind::AlwaysSized)?;
1299                 match unit.abi {
1300                     Abi::Aggregate { ref mut sized } => *sized = false,
1301                     _ => bug!()
1302                 }
1303                 tcx.intern_layout(unit)
1304             }
1305
1306             // Tuples, generators and closures.
1307             ty::TyGenerator(def_id, ref substs, _) => {
1308                 let tys = substs.field_tys(def_id, tcx);
1309                 univariant(&tys.map(|ty| self.layout_of(ty)).collect::<Result<Vec<_>, _>>()?,
1310                     &ReprOptions::default(),
1311                     StructKind::AlwaysSized)?
1312             }
1313
1314             ty::TyClosure(def_id, ref substs) => {
1315                 let tys = substs.upvar_tys(def_id, tcx);
1316                 univariant(&tys.map(|ty| self.layout_of(ty)).collect::<Result<Vec<_>, _>>()?,
1317                     &ReprOptions::default(),
1318                     StructKind::AlwaysSized)?
1319             }
1320
1321             ty::TyTuple(tys, _) => {
1322                 let kind = if tys.len() == 0 {
1323                     StructKind::AlwaysSized
1324                 } else {
1325                     StructKind::MaybeUnsized
1326                 };
1327
1328                 univariant(&tys.iter().map(|ty| self.layout_of(ty)).collect::<Result<Vec<_>, _>>()?,
1329                     &ReprOptions::default(), kind)?
1330             }
1331
1332             // SIMD vector types.
1333             ty::TyAdt(def, ..) if def.repr.simd() => {
1334                 let element = self.layout_of(ty.simd_type(tcx))?;
1335                 let count = ty.simd_size(tcx) as u64;
1336                 assert!(count > 0);
1337                 let scalar = match element.abi {
1338                     Abi::Scalar(ref scalar) => scalar.clone(),
1339                     _ => {
1340                         tcx.sess.fatal(&format!("monomorphising SIMD type `{}` with \
1341                                                 a non-machine element type `{}`",
1342                                                 ty, element.ty));
1343                     }
1344                 };
1345                 let size = element.size.checked_mul(count, dl)
1346                     .ok_or(LayoutError::SizeOverflow(ty))?;
1347                 let align = dl.vector_align(size);
1348                 let size = size.abi_align(align);
1349
1350                 tcx.intern_layout(LayoutDetails {
1351                     variants: Variants::Single { index: 0 },
1352                     fields: FieldPlacement::Array {
1353                         stride: element.size,
1354                         count
1355                     },
1356                     abi: Abi::Vector {
1357                         element: scalar,
1358                         count
1359                     },
1360                     size,
1361                     align,
1362                 })
1363             }
1364
1365             // ADTs.
1366             ty::TyAdt(def, substs) => {
1367                 // Cache the field layouts.
1368                 let variants = def.variants.iter().map(|v| {
1369                     v.fields.iter().map(|field| {
1370                         self.layout_of(field.ty(tcx, substs))
1371                     }).collect::<Result<Vec<_>, _>>()
1372                 }).collect::<Result<Vec<_>, _>>()?;
1373
1374                 if def.is_union() {
1375                     let packed = def.repr.packed();
1376                     if packed && def.repr.align > 0 {
1377                         bug!("Union cannot be packed and aligned");
1378                     }
1379
1380                     let mut align = if def.repr.packed() {
1381                         dl.i8_align
1382                     } else {
1383                         dl.aggregate_align
1384                     };
1385
1386                     if def.repr.align > 0 {
1387                         let repr_align = def.repr.align as u64;
1388                         align = align.max(
1389                             Align::from_bytes(repr_align, repr_align).unwrap());
1390                     }
1391
1392                     let mut size = Size::from_bytes(0);
1393                     for field in &variants[0] {
1394                         assert!(!field.is_unsized());
1395
1396                         if !packed {
1397                             align = align.max(field.align);
1398                         }
1399                         size = cmp::max(size, field.size);
1400                     }
1401
1402                     return Ok(tcx.intern_layout(LayoutDetails {
1403                         variants: Variants::Single { index: 0 },
1404                         fields: FieldPlacement::Union(variants[0].len()),
1405                         abi: Abi::Aggregate { sized: true },
1406                         align,
1407                         size: size.abi_align(align)
1408                     }));
1409                 }
1410
1411                 let (inh_first, inh_second) = {
1412                     let mut inh_variants = (0..variants.len()).filter(|&v| {
1413                         variants[v].iter().all(|f| f.abi != Abi::Uninhabited)
1414                     });
1415                     (inh_variants.next(), inh_variants.next())
1416                 };
1417                 if inh_first.is_none() {
1418                     // Uninhabited because it has no variants, or only uninhabited ones.
1419                     return Ok(tcx.intern_layout(LayoutDetails::uninhabited(0)));
1420                 }
1421
1422                 let is_struct = !def.is_enum() ||
1423                     // Only one variant is inhabited.
1424                     (inh_second.is_none() &&
1425                     // Representation optimizations are allowed.
1426                      !def.repr.inhibit_enum_layout_opt() &&
1427                     // Inhabited variant either has data ...
1428                      (!variants[inh_first.unwrap()].is_empty() ||
1429                     // ... or there other, uninhabited, variants.
1430                       variants.len() > 1));
1431                 if is_struct {
1432                     // Struct, or univariant enum equivalent to a struct.
1433                     // (Typechecking will reject discriminant-sizing attrs.)
1434
1435                     let v = inh_first.unwrap();
1436                     let kind = if def.is_enum() || variants[v].len() == 0 {
1437                         StructKind::AlwaysSized
1438                     } else {
1439                         let param_env = tcx.param_env(def.did);
1440                         let last_field = def.variants[v].fields.last().unwrap();
1441                         let always_sized = tcx.type_of(last_field.did)
1442                           .is_sized(tcx.at(DUMMY_SP), param_env);
1443                         if !always_sized { StructKind::MaybeUnsized }
1444                         else { StructKind::AlwaysSized }
1445                     };
1446
1447                     let mut st = univariant_uninterned(&variants[v], &def.repr, kind)?;
1448                     st.variants = Variants::Single { index: v };
1449                     // Exclude 0 from the range of a newtype ABI NonZero<T>.
1450                     if Some(def.did) == self.tcx.lang_items().non_zero() {
1451                         match st.abi {
1452                             Abi::Scalar(ref mut scalar) |
1453                             Abi::ScalarPair(ref mut scalar, _) => {
1454                                 if scalar.valid_range.start == 0 {
1455                                     scalar.valid_range.start = 1;
1456                                 }
1457                             }
1458                             _ => {}
1459                         }
1460                     }
1461                     return Ok(tcx.intern_layout(st));
1462                 }
1463
1464                 let no_explicit_discriminants = def.variants.iter().enumerate()
1465                     .all(|(i, v)| v.discr == ty::VariantDiscr::Relative(i));
1466
1467                 // Niche-filling enum optimization.
1468                 if !def.repr.inhibit_enum_layout_opt() && no_explicit_discriminants {
1469                     let mut dataful_variant = None;
1470                     let mut niche_variants = usize::max_value()..=0;
1471
1472                     // Find one non-ZST variant.
1473                     'variants: for (v, fields) in variants.iter().enumerate() {
1474                         for f in fields {
1475                             if f.abi == Abi::Uninhabited {
1476                                 continue 'variants;
1477                             }
1478                             if !f.is_zst() {
1479                                 if dataful_variant.is_none() {
1480                                     dataful_variant = Some(v);
1481                                     continue 'variants;
1482                                 } else {
1483                                     dataful_variant = None;
1484                                     break 'variants;
1485                                 }
1486                             }
1487                         }
1488                         if niche_variants.start > v {
1489                             niche_variants.start = v;
1490                         }
1491                         niche_variants.end = v;
1492                     }
1493
1494                     if niche_variants.start > niche_variants.end {
1495                         dataful_variant = None;
1496                     }
1497
1498                     if let Some(i) = dataful_variant {
1499                         let count = (niche_variants.end - niche_variants.start + 1) as u128;
1500                         for (field_index, field) in variants[i].iter().enumerate() {
1501                             let (offset, niche, niche_start) =
1502                                 match field.find_niche(self, count)? {
1503                                     Some(niche) => niche,
1504                                     None => continue
1505                                 };
1506                             let mut align = dl.aggregate_align;
1507                             let st = variants.iter().enumerate().map(|(j, v)| {
1508                                 let mut st = univariant_uninterned(v,
1509                                     &def.repr, StructKind::AlwaysSized)?;
1510                                 st.variants = Variants::Single { index: j };
1511
1512                                 align = align.max(st.align);
1513
1514                                 Ok(st)
1515                             }).collect::<Result<Vec<_>, _>>()?;
1516
1517                             let offset = st[i].fields.offset(field_index) + offset;
1518                             let size = st[i].size;
1519
1520                             let abi = if offset.bytes() == 0 && niche.value.size(dl) == size {
1521                                 Abi::Scalar(niche.clone())
1522                             } else {
1523                                 Abi::Aggregate { sized: true }
1524                             };
1525
1526                             return Ok(tcx.intern_layout(LayoutDetails {
1527                                 variants: Variants::NicheFilling {
1528                                     dataful_variant: i,
1529                                     niche_variants,
1530                                     niche,
1531                                     niche_start,
1532                                     variants: st,
1533                                 },
1534                                 fields: FieldPlacement::Arbitrary {
1535                                     offsets: vec![offset],
1536                                     memory_index: vec![0]
1537                                 },
1538                                 abi,
1539                                 size,
1540                                 align,
1541                             }));
1542                         }
1543                     }
1544                 }
1545
1546                 let (mut min, mut max) = (i128::max_value(), i128::min_value());
1547                 for (i, discr) in def.discriminants(tcx).enumerate() {
1548                     if variants[i].iter().any(|f| f.abi == Abi::Uninhabited) {
1549                         continue;
1550                     }
1551                     let x = discr.val as i128;
1552                     if x < min { min = x; }
1553                     if x > max { max = x; }
1554                 }
1555                 assert!(min <= max, "discriminant range is {}...{}", min, max);
1556                 let (min_ity, signed) = Integer::repr_discr(tcx, ty, &def.repr, min, max);
1557
1558                 let mut align = dl.aggregate_align;
1559                 let mut size = Size::from_bytes(0);
1560
1561                 // We're interested in the smallest alignment, so start large.
1562                 let mut start_align = Align::from_bytes(256, 256).unwrap();
1563                 assert_eq!(Integer::for_abi_align(dl, start_align), None);
1564
1565                 // repr(C) on an enum tells us to make a (tag, union) layout,
1566                 // so we need to grow the prefix alignment to be at least
1567                 // the alignment of the union. (This value is used both for
1568                 // determining the alignment of the overall enum, and the
1569                 // determining the alignment of the payload after the tag.)
1570                 let mut prefix_align = min_ity.align(dl);
1571                 if def.repr.c() {
1572                     for fields in &variants {
1573                         for field in fields {
1574                             prefix_align = prefix_align.max(field.align);
1575                         }
1576                     }
1577                 }
1578
1579                 // Create the set of structs that represent each variant.
1580                 let mut variants = variants.into_iter().enumerate().map(|(i, field_layouts)| {
1581                     let mut st = univariant_uninterned(&field_layouts,
1582                         &def.repr, StructKind::Prefixed(min_ity.size(), prefix_align))?;
1583                     st.variants = Variants::Single { index: i };
1584                     // Find the first field we can't move later
1585                     // to make room for a larger discriminant.
1586                     for field in st.fields.index_by_increasing_offset().map(|j| field_layouts[j]) {
1587                         if !field.is_zst() || field.align.abi() != 1 {
1588                             start_align = start_align.min(field.align);
1589                             break;
1590                         }
1591                     }
1592                     size = cmp::max(size, st.size);
1593                     align = align.max(st.align);
1594                     Ok(st)
1595                 }).collect::<Result<Vec<_>, _>>()?;
1596
1597                 // Align the maximum variant size to the largest alignment.
1598                 size = size.abi_align(align);
1599
1600                 if size.bytes() >= dl.obj_size_bound() {
1601                     return Err(LayoutError::SizeOverflow(ty));
1602                 }
1603
1604                 let typeck_ity = Integer::from_attr(dl, def.repr.discr_type());
1605                 if typeck_ity < min_ity {
1606                     // It is a bug if Layout decided on a greater discriminant size than typeck for
1607                     // some reason at this point (based on values discriminant can take on). Mostly
1608                     // because this discriminant will be loaded, and then stored into variable of
1609                     // type calculated by typeck. Consider such case (a bug): typeck decided on
1610                     // byte-sized discriminant, but layout thinks we need a 16-bit to store all
1611                     // discriminant values. That would be a bug, because then, in trans, in order
1612                     // to store this 16-bit discriminant into 8-bit sized temporary some of the
1613                     // space necessary to represent would have to be discarded (or layout is wrong
1614                     // on thinking it needs 16 bits)
1615                     bug!("layout decided on a larger discriminant type ({:?}) than typeck ({:?})",
1616                          min_ity, typeck_ity);
1617                     // However, it is fine to make discr type however large (as an optimisation)
1618                     // after this point â€“ we’ll just truncate the value we load in trans.
1619                 }
1620
1621                 // Check to see if we should use a different type for the
1622                 // discriminant. We can safely use a type with the same size
1623                 // as the alignment of the first field of each variant.
1624                 // We increase the size of the discriminant to avoid LLVM copying
1625                 // padding when it doesn't need to. This normally causes unaligned
1626                 // load/stores and excessive memcpy/memset operations. By using a
1627                 // bigger integer size, LLVM can be sure about it's contents and
1628                 // won't be so conservative.
1629
1630                 // Use the initial field alignment
1631                 let mut ity = Integer::for_abi_align(dl, start_align).unwrap_or(min_ity);
1632
1633                 // If the alignment is not larger than the chosen discriminant size,
1634                 // don't use the alignment as the final size.
1635                 if ity <= min_ity {
1636                     ity = min_ity;
1637                 } else {
1638                     // Patch up the variants' first few fields.
1639                     let old_ity_size = min_ity.size();
1640                     let new_ity_size = ity.size();
1641                     for variant in &mut variants {
1642                         if variant.abi == Abi::Uninhabited {
1643                             continue;
1644                         }
1645                         match variant.fields {
1646                             FieldPlacement::Arbitrary { ref mut offsets, .. } => {
1647                                 for i in offsets {
1648                                     if *i <= old_ity_size {
1649                                         assert_eq!(*i, old_ity_size);
1650                                         *i = new_ity_size;
1651                                     }
1652                                 }
1653                                 // We might be making the struct larger.
1654                                 if variant.size <= old_ity_size {
1655                                     variant.size = new_ity_size;
1656                                 }
1657                             }
1658                             _ => bug!()
1659                         }
1660                     }
1661                 }
1662
1663                 let discr = Scalar {
1664                     value: Int(ity, signed),
1665                     valid_range: (min as u128)..=(max as u128)
1666                 };
1667                 let abi = if discr.value.size(dl) == size {
1668                     Abi::Scalar(discr.clone())
1669                 } else {
1670                     Abi::Aggregate { sized: true }
1671                 };
1672                 tcx.intern_layout(LayoutDetails {
1673                     variants: Variants::Tagged {
1674                         discr,
1675                         variants
1676                     },
1677                     fields: FieldPlacement::Arbitrary {
1678                         offsets: vec![Size::from_bytes(0)],
1679                         memory_index: vec![0]
1680                     },
1681                     abi,
1682                     align,
1683                     size
1684                 })
1685             }
1686
1687             // Types with no meaningful known layout.
1688             ty::TyProjection(_) | ty::TyAnon(..) => {
1689                 let normalized = tcx.normalize_associated_type_in_env(&ty, param_env);
1690                 if ty == normalized {
1691                     return Err(LayoutError::Unknown(ty));
1692                 }
1693                 tcx.layout_raw(param_env.and(normalized))?
1694             }
1695             ty::TyParam(_) => {
1696                 return Err(LayoutError::Unknown(ty));
1697             }
1698             ty::TyGeneratorWitness(..) | ty::TyInfer(_) | ty::TyError => {
1699                 bug!("LayoutDetails::compute: unexpected type `{}`", ty)
1700             }
1701         })
1702     }
1703
1704     /// This is invoked by the `layout_raw` query to record the final
1705     /// layout of each type.
1706     #[inline]
1707     fn record_layout_for_printing(self, layout: TyLayout<'tcx>) {
1708         // If we are running with `-Zprint-type-sizes`, record layouts for
1709         // dumping later. Ignore layouts that are done with non-empty
1710         // environments or non-monomorphic layouts, as the user only wants
1711         // to see the stuff resulting from the final trans session.
1712         if
1713             !self.tcx.sess.opts.debugging_opts.print_type_sizes ||
1714             layout.ty.has_param_types() ||
1715             layout.ty.has_self_ty() ||
1716             !self.param_env.caller_bounds.is_empty()
1717         {
1718             return;
1719         }
1720
1721         self.record_layout_for_printing_outlined(layout)
1722     }
1723
1724     fn record_layout_for_printing_outlined(self, layout: TyLayout<'tcx>) {
1725         // (delay format until we actually need it)
1726         let record = |kind, opt_discr_size, variants| {
1727             let type_desc = format!("{:?}", layout.ty);
1728             self.tcx.sess.code_stats.borrow_mut().record_type_size(kind,
1729                                                                    type_desc,
1730                                                                    layout.align,
1731                                                                    layout.size,
1732                                                                    opt_discr_size,
1733                                                                    variants);
1734         };
1735
1736         let adt_def = match layout.ty.sty {
1737             ty::TyAdt(ref adt_def, _) => {
1738                 debug!("print-type-size t: `{:?}` process adt", layout.ty);
1739                 adt_def
1740             }
1741
1742             ty::TyClosure(..) => {
1743                 debug!("print-type-size t: `{:?}` record closure", layout.ty);
1744                 record(DataTypeKind::Closure, None, vec![]);
1745                 return;
1746             }
1747
1748             _ => {
1749                 debug!("print-type-size t: `{:?}` skip non-nominal", layout.ty);
1750                 return;
1751             }
1752         };
1753
1754         let adt_kind = adt_def.adt_kind();
1755
1756         let build_variant_info = |n: Option<ast::Name>,
1757                                   flds: &[ast::Name],
1758                                   layout: TyLayout<'tcx>| {
1759             let mut min_size = Size::from_bytes(0);
1760             let field_info: Vec<_> = flds.iter().enumerate().map(|(i, &name)| {
1761                 match layout.field(self, i) {
1762                     Err(err) => {
1763                         bug!("no layout found for field {}: `{:?}`", name, err);
1764                     }
1765                     Ok(field_layout) => {
1766                         let offset = layout.fields.offset(i);
1767                         let field_end = offset + field_layout.size;
1768                         if min_size < field_end {
1769                             min_size = field_end;
1770                         }
1771                         session::FieldInfo {
1772                             name: name.to_string(),
1773                             offset: offset.bytes(),
1774                             size: field_layout.size.bytes(),
1775                             align: field_layout.align.abi(),
1776                         }
1777                     }
1778                 }
1779             }).collect();
1780
1781             session::VariantInfo {
1782                 name: n.map(|n|n.to_string()),
1783                 kind: if layout.is_unsized() {
1784                     session::SizeKind::Min
1785                 } else {
1786                     session::SizeKind::Exact
1787                 },
1788                 align: layout.align.abi(),
1789                 size: if min_size.bytes() == 0 {
1790                     layout.size.bytes()
1791                 } else {
1792                     min_size.bytes()
1793                 },
1794                 fields: field_info,
1795             }
1796         };
1797
1798         match layout.variants {
1799             Variants::Single { index } => {
1800                 debug!("print-type-size `{:#?}` variant {}",
1801                        layout, adt_def.variants[index].name);
1802                 if !adt_def.variants.is_empty() {
1803                     let variant_def = &adt_def.variants[index];
1804                     let fields: Vec<_> =
1805                         variant_def.fields.iter().map(|f| f.name).collect();
1806                     record(adt_kind.into(),
1807                            None,
1808                            vec![build_variant_info(Some(variant_def.name),
1809                                                    &fields,
1810                                                    layout)]);
1811                 } else {
1812                     // (This case arises for *empty* enums; so give it
1813                     // zero variants.)
1814                     record(adt_kind.into(), None, vec![]);
1815                 }
1816             }
1817
1818             Variants::NicheFilling { .. } |
1819             Variants::Tagged { .. } => {
1820                 debug!("print-type-size `{:#?}` adt general variants def {}",
1821                        layout.ty, adt_def.variants.len());
1822                 let variant_infos: Vec<_> =
1823                     adt_def.variants.iter().enumerate().map(|(i, variant_def)| {
1824                         let fields: Vec<_> =
1825                             variant_def.fields.iter().map(|f| f.name).collect();
1826                         build_variant_info(Some(variant_def.name),
1827                                             &fields,
1828                                             layout.for_variant(self, i))
1829                     })
1830                     .collect();
1831                 record(adt_kind.into(), match layout.variants {
1832                     Variants::Tagged { ref discr, .. } => Some(discr.value.size(self)),
1833                     _ => None
1834                 }, variant_infos);
1835             }
1836         }
1837     }
1838 }
1839
1840 /// Type size "skeleton", i.e. the only information determining a type's size.
1841 /// While this is conservative, (aside from constant sizes, only pointers,
1842 /// newtypes thereof and null pointer optimized enums are allowed), it is
1843 /// enough to statically check common usecases of transmute.
1844 #[derive(Copy, Clone, Debug)]
1845 pub enum SizeSkeleton<'tcx> {
1846     /// Any statically computable Layout.
1847     Known(Size),
1848
1849     /// A potentially-fat pointer.
1850     Pointer {
1851         /// If true, this pointer is never null.
1852         non_zero: bool,
1853         /// The type which determines the unsized metadata, if any,
1854         /// of this pointer. Either a type parameter or a projection
1855         /// depending on one, with regions erased.
1856         tail: Ty<'tcx>
1857     }
1858 }
1859
1860 impl<'a, 'tcx> SizeSkeleton<'tcx> {
1861     pub fn compute(ty: Ty<'tcx>,
1862                    tcx: TyCtxt<'a, 'tcx, 'tcx>,
1863                    param_env: ty::ParamEnv<'tcx>)
1864                    -> Result<SizeSkeleton<'tcx>, LayoutError<'tcx>> {
1865         assert!(!ty.has_infer_types());
1866
1867         // First try computing a static layout.
1868         let err = match tcx.layout_of(param_env.and(ty)) {
1869             Ok(layout) => {
1870                 return Ok(SizeSkeleton::Known(layout.size));
1871             }
1872             Err(err) => err
1873         };
1874
1875         match ty.sty {
1876             ty::TyRef(_, ty::TypeAndMut { ty: pointee, .. }) |
1877             ty::TyRawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
1878                 let non_zero = !ty.is_unsafe_ptr();
1879                 let tail = tcx.struct_tail(pointee);
1880                 match tail.sty {
1881                     ty::TyParam(_) | ty::TyProjection(_) => {
1882                         assert!(tail.has_param_types() || tail.has_self_ty());
1883                         Ok(SizeSkeleton::Pointer {
1884                             non_zero,
1885                             tail: tcx.erase_regions(&tail)
1886                         })
1887                     }
1888                     _ => {
1889                         bug!("SizeSkeleton::compute({}): layout errored ({}), yet \
1890                               tail `{}` is not a type parameter or a projection",
1891                              ty, err, tail)
1892                     }
1893                 }
1894             }
1895
1896             ty::TyAdt(def, substs) => {
1897                 // Only newtypes and enums w/ nullable pointer optimization.
1898                 if def.is_union() || def.variants.is_empty() || def.variants.len() > 2 {
1899                     return Err(err);
1900                 }
1901
1902                 // Get a zero-sized variant or a pointer newtype.
1903                 let zero_or_ptr_variant = |i: usize| {
1904                     let fields = def.variants[i].fields.iter().map(|field| {
1905                         SizeSkeleton::compute(field.ty(tcx, substs), tcx, param_env)
1906                     });
1907                     let mut ptr = None;
1908                     for field in fields {
1909                         let field = field?;
1910                         match field {
1911                             SizeSkeleton::Known(size) => {
1912                                 if size.bytes() > 0 {
1913                                     return Err(err);
1914                                 }
1915                             }
1916                             SizeSkeleton::Pointer {..} => {
1917                                 if ptr.is_some() {
1918                                     return Err(err);
1919                                 }
1920                                 ptr = Some(field);
1921                             }
1922                         }
1923                     }
1924                     Ok(ptr)
1925                 };
1926
1927                 let v0 = zero_or_ptr_variant(0)?;
1928                 // Newtype.
1929                 if def.variants.len() == 1 {
1930                     if let Some(SizeSkeleton::Pointer { non_zero, tail }) = v0 {
1931                         return Ok(SizeSkeleton::Pointer {
1932                             non_zero: non_zero ||
1933                                 Some(def.did) == tcx.lang_items().non_zero(),
1934                             tail,
1935                         });
1936                     } else {
1937                         return Err(err);
1938                     }
1939                 }
1940
1941                 let v1 = zero_or_ptr_variant(1)?;
1942                 // Nullable pointer enum optimization.
1943                 match (v0, v1) {
1944                     (Some(SizeSkeleton::Pointer { non_zero: true, tail }), None) |
1945                     (None, Some(SizeSkeleton::Pointer { non_zero: true, tail })) => {
1946                         Ok(SizeSkeleton::Pointer {
1947                             non_zero: false,
1948                             tail,
1949                         })
1950                     }
1951                     _ => Err(err)
1952                 }
1953             }
1954
1955             ty::TyProjection(_) | ty::TyAnon(..) => {
1956                 let normalized = tcx.normalize_associated_type_in_env(&ty, param_env);
1957                 if ty == normalized {
1958                     Err(err)
1959                 } else {
1960                     SizeSkeleton::compute(normalized, tcx, param_env)
1961                 }
1962             }
1963
1964             _ => Err(err)
1965         }
1966     }
1967
1968     pub fn same_size(self, other: SizeSkeleton) -> bool {
1969         match (self, other) {
1970             (SizeSkeleton::Known(a), SizeSkeleton::Known(b)) => a == b,
1971             (SizeSkeleton::Pointer { tail: a, .. },
1972              SizeSkeleton::Pointer { tail: b, .. }) => a == b,
1973             _ => false
1974         }
1975     }
1976 }
1977
1978 /// The details of the layout of a type, alongside the type itself.
1979 /// Provides various type traversal APIs (e.g. recursing into fields).
1980 ///
1981 /// Note that the details are NOT guaranteed to always be identical
1982 /// to those obtained from `layout_of(ty)`, as we need to produce
1983 /// layouts for which Rust types do not exist, such as enum variants
1984 /// or synthetic fields of enums (i.e. discriminants) and fat pointers.
1985 #[derive(Copy, Clone, Debug)]
1986 pub struct TyLayout<'tcx> {
1987     pub ty: Ty<'tcx>,
1988     details: &'tcx LayoutDetails
1989 }
1990
1991 impl<'tcx> Deref for TyLayout<'tcx> {
1992     type Target = &'tcx LayoutDetails;
1993     fn deref(&self) -> &&'tcx LayoutDetails {
1994         &self.details
1995     }
1996 }
1997
1998 pub trait HasTyCtxt<'tcx>: HasDataLayout {
1999     fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx>;
2000 }
2001
2002 impl<'a, 'gcx, 'tcx> HasDataLayout for TyCtxt<'a, 'gcx, 'tcx> {
2003     fn data_layout(&self) -> &TargetDataLayout {
2004         &self.data_layout
2005     }
2006 }
2007
2008 impl<'a, 'gcx, 'tcx> HasTyCtxt<'gcx> for TyCtxt<'a, 'gcx, 'tcx> {
2009     fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'gcx> {
2010         self.global_tcx()
2011     }
2012 }
2013
2014 impl<'tcx, T: HasDataLayout> HasDataLayout for LayoutCx<'tcx, T> {
2015     fn data_layout(&self) -> &TargetDataLayout {
2016         self.tcx.data_layout()
2017     }
2018 }
2019
2020 impl<'gcx, 'tcx, T: HasTyCtxt<'gcx>> HasTyCtxt<'gcx> for LayoutCx<'tcx, T> {
2021     fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'gcx> {
2022         self.tcx.tcx()
2023     }
2024 }
2025
2026 pub trait MaybeResult<T> {
2027     fn from_ok(x: T) -> Self;
2028     fn map_same<F: FnOnce(T) -> T>(self, f: F) -> Self;
2029 }
2030
2031 impl<T> MaybeResult<T> for T {
2032     fn from_ok(x: T) -> Self {
2033         x
2034     }
2035     fn map_same<F: FnOnce(T) -> T>(self, f: F) -> Self {
2036         f(self)
2037     }
2038 }
2039
2040 impl<T, E> MaybeResult<T> for Result<T, E> {
2041     fn from_ok(x: T) -> Self {
2042         Ok(x)
2043     }
2044     fn map_same<F: FnOnce(T) -> T>(self, f: F) -> Self {
2045         self.map(f)
2046     }
2047 }
2048
2049 pub trait LayoutOf<T> {
2050     type TyLayout;
2051
2052     fn layout_of(self, ty: T) -> Self::TyLayout;
2053 }
2054
2055 impl<'a, 'tcx> LayoutOf<Ty<'tcx>> for LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
2056     type TyLayout = Result<TyLayout<'tcx>, LayoutError<'tcx>>;
2057
2058     /// Computes the layout of a type. Note that this implicitly
2059     /// executes in "reveal all" mode.
2060     fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
2061         let param_env = self.param_env.with_reveal_all();
2062         let ty = self.tcx.normalize_associated_type_in_env(&ty, param_env);
2063         let details = self.tcx.layout_raw(param_env.and(ty))?;
2064         let layout = TyLayout {
2065             ty,
2066             details
2067         };
2068
2069         // NB: This recording is normally disabled; when enabled, it
2070         // can however trigger recursive invocations of `layout_of`.
2071         // Therefore, we execute it *after* the main query has
2072         // completed, to avoid problems around recursive structures
2073         // and the like. (Admittedly, I wasn't able to reproduce a problem
2074         // here, but it seems like the right thing to do. -nmatsakis)
2075         self.record_layout_for_printing(layout);
2076
2077         Ok(layout)
2078     }
2079 }
2080
2081 impl<'a, 'tcx> LayoutOf<Ty<'tcx>> for LayoutCx<'tcx, ty::maps::TyCtxtAt<'a, 'tcx, 'tcx>> {
2082     type TyLayout = Result<TyLayout<'tcx>, LayoutError<'tcx>>;
2083
2084     /// Computes the layout of a type. Note that this implicitly
2085     /// executes in "reveal all" mode.
2086     fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
2087         let param_env = self.param_env.with_reveal_all();
2088         let ty = self.tcx.normalize_associated_type_in_env(&ty, param_env);
2089         let details = self.tcx.layout_raw(param_env.and(ty))?;
2090         let layout = TyLayout {
2091             ty,
2092             details
2093         };
2094
2095         // NB: This recording is normally disabled; when enabled, it
2096         // can however trigger recursive invocations of `layout_of`.
2097         // Therefore, we execute it *after* the main query has
2098         // completed, to avoid problems around recursive structures
2099         // and the like. (Admittedly, I wasn't able to reproduce a problem
2100         // here, but it seems like the right thing to do. -nmatsakis)
2101         let cx = LayoutCx {
2102             tcx: *self.tcx,
2103             param_env: self.param_env
2104         };
2105         cx.record_layout_for_printing(layout);
2106
2107         Ok(layout)
2108     }
2109 }
2110
2111 // Helper (inherent) `layout_of` methods to avoid pushing `LayoutCx` to users.
2112 impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
2113     /// Computes the layout of a type. Note that this implicitly
2114     /// executes in "reveal all" mode.
2115     #[inline]
2116     pub fn layout_of(self, param_env_and_ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>)
2117                      -> Result<TyLayout<'tcx>, LayoutError<'tcx>> {
2118         let cx = LayoutCx {
2119             tcx: self,
2120             param_env: param_env_and_ty.param_env
2121         };
2122         cx.layout_of(param_env_and_ty.value)
2123     }
2124 }
2125
2126 impl<'a, 'tcx> ty::maps::TyCtxtAt<'a, 'tcx, 'tcx> {
2127     /// Computes the layout of a type. Note that this implicitly
2128     /// executes in "reveal all" mode.
2129     #[inline]
2130     pub fn layout_of(self, param_env_and_ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>)
2131                      -> Result<TyLayout<'tcx>, LayoutError<'tcx>> {
2132         let cx = LayoutCx {
2133             tcx: self,
2134             param_env: param_env_and_ty.param_env
2135         };
2136         cx.layout_of(param_env_and_ty.value)
2137     }
2138 }
2139
2140 impl<'a, 'tcx> TyLayout<'tcx> {
2141     pub fn for_variant<C>(&self, cx: C, variant_index: usize) -> Self
2142         where C: LayoutOf<Ty<'tcx>> + HasTyCtxt<'tcx>,
2143               C::TyLayout: MaybeResult<TyLayout<'tcx>>
2144     {
2145         let details = match self.variants {
2146             Variants::Single { index } if index == variant_index => self.details,
2147
2148             Variants::Single { index } => {
2149                 // Deny calling for_variant more than once for non-Single enums.
2150                 cx.layout_of(self.ty).map_same(|layout| {
2151                     assert_eq!(layout.variants, Variants::Single { index });
2152                     layout
2153                 });
2154
2155                 let fields = match self.ty.sty {
2156                     ty::TyAdt(def, _) => def.variants[variant_index].fields.len(),
2157                     _ => bug!()
2158                 };
2159                 let mut details = LayoutDetails::uninhabited(fields);
2160                 details.variants = Variants::Single { index: variant_index };
2161                 cx.tcx().intern_layout(details)
2162             }
2163
2164             Variants::NicheFilling { ref variants, .. } |
2165             Variants::Tagged { ref variants, .. } => {
2166                 &variants[variant_index]
2167             }
2168         };
2169
2170         assert_eq!(details.variants, Variants::Single { index: variant_index });
2171
2172         TyLayout {
2173             ty: self.ty,
2174             details
2175         }
2176     }
2177
2178     pub fn field<C>(&self, cx: C, i: usize) -> C::TyLayout
2179         where C: LayoutOf<Ty<'tcx>> + HasTyCtxt<'tcx>,
2180               C::TyLayout: MaybeResult<TyLayout<'tcx>>
2181     {
2182         let tcx = cx.tcx();
2183         cx.layout_of(match self.ty.sty {
2184             ty::TyBool |
2185             ty::TyChar |
2186             ty::TyInt(_) |
2187             ty::TyUint(_) |
2188             ty::TyFloat(_) |
2189             ty::TyFnPtr(_) |
2190             ty::TyNever |
2191             ty::TyFnDef(..) |
2192             ty::TyGeneratorWitness(..) |
2193             ty::TyForeign(..) |
2194             ty::TyDynamic(..) => {
2195                 bug!("TyLayout::field_type({:?}): not applicable", self)
2196             }
2197
2198             // Potentially-fat pointers.
2199             ty::TyRef(_, ty::TypeAndMut { ty: pointee, .. }) |
2200             ty::TyRawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
2201                 assert!(i < 2);
2202
2203                 // Reuse the fat *T type as its own thin pointer data field.
2204                 // This provides information about e.g. DST struct pointees
2205                 // (which may have no non-DST form), and will work as long
2206                 // as the `Abi` or `FieldPlacement` is checked by users.
2207                 if i == 0 {
2208                     let nil = tcx.mk_nil();
2209                     let ptr_ty = if self.ty.is_unsafe_ptr() {
2210                         tcx.mk_mut_ptr(nil)
2211                     } else {
2212                         tcx.mk_mut_ref(tcx.types.re_static, nil)
2213                     };
2214                     return cx.layout_of(ptr_ty).map_same(|mut ptr_layout| {
2215                         ptr_layout.ty = self.ty;
2216                         ptr_layout
2217                     });
2218                 }
2219
2220                 match tcx.struct_tail(pointee).sty {
2221                     ty::TySlice(_) |
2222                     ty::TyStr => tcx.types.usize,
2223                     ty::TyDynamic(..) => {
2224                         // FIXME(eddyb) use an usize/fn() array with
2225                         // the correct number of vtables slots.
2226                         tcx.mk_imm_ref(tcx.types.re_static, tcx.mk_nil())
2227                     }
2228                     _ => bug!("TyLayout::field_type({:?}): not applicable", self)
2229                 }
2230             }
2231
2232             // Arrays and slices.
2233             ty::TyArray(element, _) |
2234             ty::TySlice(element) => element,
2235             ty::TyStr => tcx.types.u8,
2236
2237             // Tuples, generators and closures.
2238             ty::TyClosure(def_id, ref substs) => {
2239                 substs.upvar_tys(def_id, tcx).nth(i).unwrap()
2240             }
2241
2242             ty::TyGenerator(def_id, ref substs, _) => {
2243                 substs.field_tys(def_id, tcx).nth(i).unwrap()
2244             }
2245
2246             ty::TyTuple(tys, _) => tys[i],
2247
2248             // SIMD vector types.
2249             ty::TyAdt(def, ..) if def.repr.simd() => {
2250                 self.ty.simd_type(tcx)
2251             }
2252
2253             // ADTs.
2254             ty::TyAdt(def, substs) => {
2255                 match self.variants {
2256                     Variants::Single { index } => {
2257                         def.variants[index].fields[i].ty(tcx, substs)
2258                     }
2259
2260                     // Discriminant field for enums (where applicable).
2261                     Variants::Tagged { ref discr, .. } |
2262                     Variants::NicheFilling { niche: ref discr, .. } => {
2263                         assert_eq!(i, 0);
2264                         let layout = LayoutDetails::scalar(tcx, discr.clone());
2265                         return MaybeResult::from_ok(TyLayout {
2266                             details: tcx.intern_layout(layout),
2267                             ty: discr.value.to_ty(tcx)
2268                         });
2269                     }
2270                 }
2271             }
2272
2273             ty::TyProjection(_) | ty::TyAnon(..) | ty::TyParam(_) |
2274             ty::TyInfer(_) | ty::TyError => {
2275                 bug!("TyLayout::field_type: unexpected type `{}`", self.ty)
2276             }
2277         })
2278     }
2279
2280     /// Returns true if the layout corresponds to an unsized type.
2281     pub fn is_unsized(&self) -> bool {
2282         self.abi.is_unsized()
2283     }
2284
2285     /// Returns true if the type is a ZST and not unsized.
2286     pub fn is_zst(&self) -> bool {
2287         match self.abi {
2288             Abi::Uninhabited => true,
2289             Abi::Scalar(_) |
2290             Abi::ScalarPair(..) |
2291             Abi::Vector { .. } => false,
2292             Abi::Aggregate { sized } => sized && self.size.bytes() == 0
2293         }
2294     }
2295
2296     pub fn size_and_align(&self) -> (Size, Align) {
2297         (self.size, self.align)
2298     }
2299
2300     /// Find the offset of a niche leaf field, starting from
2301     /// the given type and recursing through aggregates, which
2302     /// has at least `count` consecutive invalid values.
2303     /// The tuple is `(offset, scalar, niche_value)`.
2304     // FIXME(eddyb) traverse already optimized enums.
2305     fn find_niche<C>(&self, cx: C, count: u128)
2306         -> Result<Option<(Size, Scalar, u128)>, LayoutError<'tcx>>
2307         where C: LayoutOf<Ty<'tcx>, TyLayout = Result<Self, LayoutError<'tcx>>> +
2308                  HasTyCtxt<'tcx>
2309     {
2310         let scalar_component = |scalar: &Scalar, offset| {
2311             let Scalar { value, valid_range: ref v } = *scalar;
2312
2313             let bits = value.size(cx).bits();
2314             assert!(bits <= 128);
2315             let max_value = !0u128 >> (128 - bits);
2316
2317             // Find out how many values are outside the valid range.
2318             let niches = if v.start <= v.end {
2319                 v.start + (max_value - v.end)
2320             } else {
2321                 v.start - v.end - 1
2322             };
2323
2324             // Give up if we can't fit `count` consecutive niches.
2325             if count > niches {
2326                 return None;
2327             }
2328
2329             let niche_start = v.end.wrapping_add(1) & max_value;
2330             let niche_end = v.end.wrapping_add(count) & max_value;
2331             Some((offset, Scalar {
2332                 value,
2333                 valid_range: v.start..=niche_end
2334             }, niche_start))
2335         };
2336
2337         // Locals variables which live across yields are stored
2338         // in the generator type as fields. These may be uninitialized
2339         // so we don't look for niches there.
2340         if let ty::TyGenerator(..) = self.ty.sty {
2341             return Ok(None);
2342         }
2343
2344         match self.abi {
2345             Abi::Scalar(ref scalar) => {
2346                 return Ok(scalar_component(scalar, Size::from_bytes(0)));
2347             }
2348             Abi::ScalarPair(ref a, ref b) => {
2349                 return Ok(scalar_component(a, Size::from_bytes(0)).or_else(|| {
2350                     scalar_component(b, a.value.size(cx).abi_align(b.value.align(cx)))
2351                 }));
2352             }
2353             Abi::Vector { ref element, .. } => {
2354                 return Ok(scalar_component(element, Size::from_bytes(0)));
2355             }
2356             _ => {}
2357         }
2358
2359         // Perhaps one of the fields is non-zero, let's recurse and find out.
2360         if let FieldPlacement::Union(_) = self.fields {
2361             // Only Rust enums have safe-to-inspect fields
2362             // (a discriminant), other unions are unsafe.
2363             if let Variants::Single { .. } = self.variants {
2364                 return Ok(None);
2365             }
2366         }
2367         if let FieldPlacement::Array { .. } = self.fields {
2368             if self.fields.count() > 0 {
2369                 return self.field(cx, 0)?.find_niche(cx, count);
2370             }
2371         }
2372         for i in 0..self.fields.count() {
2373             let r = self.field(cx, i)?.find_niche(cx, count)?;
2374             if let Some((offset, scalar, niche_value)) = r {
2375                 let offset = self.fields.offset(i) + offset;
2376                 return Ok(Some((offset, scalar, niche_value)));
2377             }
2378         }
2379         Ok(None)
2380     }
2381 }
2382
2383 impl<'a> HashStable<StableHashingContext<'a>> for Variants {
2384     fn hash_stable<W: StableHasherResult>(&self,
2385                                           hcx: &mut StableHashingContext<'a>,
2386                                           hasher: &mut StableHasher<W>) {
2387         use ty::layout::Variants::*;
2388         mem::discriminant(self).hash_stable(hcx, hasher);
2389
2390         match *self {
2391             Single { index } => {
2392                 index.hash_stable(hcx, hasher);
2393             }
2394             Tagged {
2395                 ref discr,
2396                 ref variants,
2397             } => {
2398                 discr.hash_stable(hcx, hasher);
2399                 variants.hash_stable(hcx, hasher);
2400             }
2401             NicheFilling {
2402                 dataful_variant,
2403                 niche_variants: RangeInclusive { start, end },
2404                 ref niche,
2405                 niche_start,
2406                 ref variants,
2407             } => {
2408                 dataful_variant.hash_stable(hcx, hasher);
2409                 start.hash_stable(hcx, hasher);
2410                 end.hash_stable(hcx, hasher);
2411                 niche.hash_stable(hcx, hasher);
2412                 niche_start.hash_stable(hcx, hasher);
2413                 variants.hash_stable(hcx, hasher);
2414             }
2415         }
2416     }
2417 }
2418
2419 impl<'a> HashStable<StableHashingContext<'a>> for FieldPlacement {
2420     fn hash_stable<W: StableHasherResult>(&self,
2421                                           hcx: &mut StableHashingContext<'a>,
2422                                           hasher: &mut StableHasher<W>) {
2423         use ty::layout::FieldPlacement::*;
2424         mem::discriminant(self).hash_stable(hcx, hasher);
2425
2426         match *self {
2427             Union(count) => {
2428                 count.hash_stable(hcx, hasher);
2429             }
2430             Array { count, stride } => {
2431                 count.hash_stable(hcx, hasher);
2432                 stride.hash_stable(hcx, hasher);
2433             }
2434             Arbitrary { ref offsets, ref memory_index } => {
2435                 offsets.hash_stable(hcx, hasher);
2436                 memory_index.hash_stable(hcx, hasher);
2437             }
2438         }
2439     }
2440 }
2441
2442 impl<'a> HashStable<StableHashingContext<'a>> for Abi {
2443     fn hash_stable<W: StableHasherResult>(&self,
2444                                           hcx: &mut StableHashingContext<'a>,
2445                                           hasher: &mut StableHasher<W>) {
2446         use ty::layout::Abi::*;
2447         mem::discriminant(self).hash_stable(hcx, hasher);
2448
2449         match *self {
2450             Uninhabited => {}
2451             Scalar(ref value) => {
2452                 value.hash_stable(hcx, hasher);
2453             }
2454             ScalarPair(ref a, ref b) => {
2455                 a.hash_stable(hcx, hasher);
2456                 b.hash_stable(hcx, hasher);
2457             }
2458             Vector { ref element, count } => {
2459                 element.hash_stable(hcx, hasher);
2460                 count.hash_stable(hcx, hasher);
2461             }
2462             Aggregate { sized } => {
2463                 sized.hash_stable(hcx, hasher);
2464             }
2465         }
2466     }
2467 }
2468
2469 impl<'a> HashStable<StableHashingContext<'a>> for Scalar {
2470     fn hash_stable<W: StableHasherResult>(&self,
2471                                           hcx: &mut StableHashingContext<'a>,
2472                                           hasher: &mut StableHasher<W>) {
2473         let Scalar { value, valid_range: RangeInclusive { start, end } } = *self;
2474         value.hash_stable(hcx, hasher);
2475         start.hash_stable(hcx, hasher);
2476         end.hash_stable(hcx, hasher);
2477     }
2478 }
2479
2480 impl_stable_hash_for!(struct ::ty::layout::LayoutDetails {
2481     variants,
2482     fields,
2483     abi,
2484     size,
2485     align
2486 });
2487
2488 impl_stable_hash_for!(enum ::ty::layout::Integer {
2489     I8,
2490     I16,
2491     I32,
2492     I64,
2493     I128
2494 });
2495
2496 impl_stable_hash_for!(enum ::ty::layout::Primitive {
2497     Int(integer, signed),
2498     F32,
2499     F64,
2500     Pointer
2501 });
2502
2503 impl_stable_hash_for!(struct ::ty::layout::Align {
2504     abi,
2505     pref
2506 });
2507
2508 impl_stable_hash_for!(struct ::ty::layout::Size {
2509     raw
2510 });
2511
2512 impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for LayoutError<'gcx>
2513 {
2514     fn hash_stable<W: StableHasherResult>(&self,
2515                                           hcx: &mut StableHashingContext<'a>,
2516                                           hasher: &mut StableHasher<W>) {
2517         use ty::layout::LayoutError::*;
2518         mem::discriminant(self).hash_stable(hcx, hasher);
2519
2520         match *self {
2521             Unknown(t) |
2522             SizeOverflow(t) => t.hash_stable(hcx, hasher)
2523         }
2524     }
2525 }