pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
    // Check the cache.
    if let Some(&llty) = cx.lltypes().borrow().get(&t) {
        return llty;
    }

    debug!("type_of {:?}", t);

    assert!(!t.has_escaping_regions(), "{:?} has escaping regions", t);

    // Replace any typedef'd types with their equivalent non-typedef
    // type. This ensures that all LLVM nominal types that contain
    // Rust types are defined as the same LLVM types.  If we don't do
    // this then, e.g. `Option<{myfield: bool}>` would be a different
    // type than `Option<myrec>`.
    let t_norm = cx.tcx().erase_regions(&t);

    if t != t_norm {
        let llty = in_memory_type_of(cx, t_norm);
        debug!("--> normalized {:?} to {:?} llty={:?}", t, t_norm, llty);
        cx.lltypes().borrow_mut().insert(t, llty);
        return llty;
    }

    let ptr_ty = |ty: Ty<'tcx>| {
        if !cx.shared().type_is_sized(ty) {
            if let ty::TyStr = ty.sty {
                // This means we get a nicer name in the output (str is always
                // unsized).
                cx.str_slice_type()
            } else {
                let ptr_ty = in_memory_type_of(cx, ty).ptr_to();
                let info_ty = unsized_info_ty(cx, ty);
                Type::struct_(cx, &[ptr_ty, info_ty], false)
            }
        } else {
            in_memory_type_of(cx, ty).ptr_to()
        }
    };

    let mut llty = match t.sty {
      ty::TyBool => Type::bool(cx),
      ty::TyChar => Type::char(cx),
      ty::TyInt(t) => Type::int_from_ty(cx, t),
      ty::TyUint(t) => Type::uint_from_ty(cx, t),
      ty::TyFloat(t) => Type::float_from_ty(cx, t),
      ty::TyNever => Type::nil(cx),
      ty::TyClosure(..) => {
          // Only create the named struct, but don't fill it in. We
          // fill it in *after* placing it into the type cache.
          adt::incomplete_type_of(cx, t, "closure")
      }

      ty::TyRef(_, ty::TypeAndMut{ty, ..}) |
      ty::TyRawPtr(ty::TypeAndMut{ty, ..}) => {
          ptr_ty(ty)
      }
      ty::TyAdt(def, _) if def.is_box() => {
          ptr_ty(t.boxed_ty())
      }

      ty::TyArray(ty, size) => {
          let size = size as u64;
          let llty = in_memory_type_of(cx, ty);
          Type::array(&llty, size)
      }

      // Unsized slice types (and str) have the type of their element, and
      // traits have the type of u8. This is so that the data pointer inside
      // fat pointers is of the right type (e.g. for array accesses), even
      // when taking the address of an unsized field in a struct.
      ty::TySlice(ty) => in_memory_type_of(cx, ty),
      ty::TyStr | ty::TyDynamic(..) => Type::i8(cx),

      ty::TyFnDef(..) => Type::nil(cx),
      ty::TyFnPtr(sig) => {
        let sig = cx.tcx().erase_late_bound_regions_and_normalize(&sig);
        FnType::new(cx, sig, &[]).llvm_type(cx).ptr_to()
      }
      ty::TyTuple(ref tys, _) if tys.is_empty() => Type::nil(cx),
      ty::TyTuple(..) => {
          adt::type_of(cx, t)
      }
      ty::TyAdt(..) if t.is_simd() => {
          let e = t.simd_type(cx.tcx());
          if !e.is_machine() {
              cx.sess().fatal(&format!("monomorphising SIMD type `{}` with \
                                        a non-machine element type `{}`",
                                       t, e))
          }
          let llet = in_memory_type_of(cx, e);
          let n = t.simd_size(cx.tcx()) as u64;
          Type::vector(&llet, n)
      }
      ty::TyAdt(..) => {
          // Only create the named struct, but don't fill it in. We
          // fill it in *after* placing it into the type cache. This
          // avoids creating more than one copy of the enum when one
          // of the enum's variants refers to the enum itself.
          let name = llvm_type_name(cx, t);
          adt::incomplete_type_of(cx, t, &name[..])
      }

      ty::TyInfer(..) |
      ty::TyProjection(..) |
      ty::TyParam(..) |
      ty::TyAnon(..) |
      ty::TyError => bug!("type_of with {:?}", t),
    };

    debug!("--> mapped t={:?} to llty={:?}", t, llty);

    cx.lltypes().borrow_mut().insert(t, llty);

    // If this was an enum or struct, fill in the type now.
    match t.sty {
        ty::TyAdt(..) | ty::TyClosure(..) if !t.is_simd() && !t.is_box() => {
            adt::finish_type_of(cx, t, &mut llty);
        }
        _ => ()
    }

    llty
}
/// Get the LLVM type corresponding to a Rust type, i.e. `rustc::ty::Ty`.
/// This is the right LLVM type for a field/array element of that type,
/// and is the same as `type_of` for all Sized types.
/// Unsized types, however, are represented by a "minimal unit", e.g.
/// `[T]` becomes `T`, while `str` and `Trait` turn into `i8` - this
/// is useful for indexing slices, as `&[T]`'s data pointer is `T*`.
/// If the type is an unsized struct, the regular layout is generated,
/// with the inner-most trailing unsized field using the "minimal unit"
/// of that field's type - this is useful for taking the address of
/// that field and ensuring the struct has the right alignment.
/// For the LLVM type of a value as a whole, see `type_of`.
Get the LLVM type corresponding to a Rust type, i.e.
Get the LLVM type corresponding to a Rust type i . e .
pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
    // Check the cache.
    if let Some(&llty) = cx.lltypes().borrow().get(&t) {
        return llty;
    }
    debug!("type_of {:?}", t);
    assert!(!t.has_escaping_regions(), "{:?} has escaping regions", t);
    // Replace any typedef'd types with their equivalent non-typedef
    // type. This ensures that all LLVM nominal types that contain
    // Rust types are defined as the same LLVM types.  If we don't do
    // this then, e.g. `Option<{myfield: bool}>` would be a different
    // type than `Option<myrec>`.
    let t_norm = cx.tcx().erase_regions(&t);
    if t != t_norm {
        let llty = in_memory_type_of(cx, t_norm);
        debug!("--> normalized {:?} to {:?} llty={:?}", t, t_norm, llty);
        cx.lltypes().borrow_mut().insert(t, llty);
        return llty;
    }
    let ptr_ty = |ty: Ty<'tcx>| {
        if !cx.shared().type_is_sized(ty) {
            if let ty::TyStr = ty.sty {
                // This means we get a nicer name in the output (str is always
                // unsized).
                cx.str_slice_type()
            } else {
                let ptr_ty = in_memory_type_of(cx, ty).ptr_to();
                let info_ty = unsized_info_ty(cx, ty);
                Type::struct_(cx, &[ptr_ty, info_ty], false)
            }
        } else {
            in_memory_type_of(cx, ty).ptr_to()
        }
    };
    let mut llty = match t.sty {
      ty::TyBool => Type::bool(cx),
      ty::TyChar => Type::char(cx),
      ty::TyInt(t) => Type::int_from_ty(cx, t),
      ty::TyUint(t) => Type::uint_from_ty(cx, t),
      ty::TyFloat(t) => Type::float_from_ty(cx, t),
      ty::TyNever => Type::nil(cx),
      ty::TyClosure(..) => {
          // Only create the named struct, but don't fill it in. We
          // fill it in *after* placing it into the type cache.
          adt::incomplete_type_of(cx, t, "closure")
      }
      ty::TyRef(_, ty::TypeAndMut{ty, ..}) |
      ty::TyRawPtr(ty::TypeAndMut{ty, ..}) => {
          ptr_ty(ty)
      }
      ty::TyAdt(def, _) if def.is_box() => {
          ptr_ty(t.boxed_ty())
      }
      ty::TyArray(ty, size) => {
          let size = size as u64;
          let llty = in_memory_type_of(cx, ty);
          Type::array(&llty, size)
      }
      // Unsized slice types (and str) have the type of their element, and
      // traits have the type of u8. This is so that the data pointer inside
      // fat pointers is of the right type (e.g. for array accesses), even
      // when taking the address of an unsized field in a struct.
      ty::TySlice(ty) => in_memory_type_of(cx, ty),
      ty::TyStr | ty::TyDynamic(..) => Type::i8(cx),
      ty::TyFnDef(..) => Type::nil(cx),
      ty::TyFnPtr(sig) => {
        let sig = cx.tcx().erase_late_bound_regions_and_normalize(&sig);
        FnType::new(cx, sig, &[]).llvm_type(cx).ptr_to()
      }
      ty::TyTuple(ref tys, _) if tys.is_empty() => Type::nil(cx),
      ty::TyTuple(..) => {
          adt::type_of(cx, t)
      }
      ty::TyAdt(..) if t.is_simd() => {
          let e = t.simd_type(cx.tcx());
          if !e.is_machine() {
              cx.sess().fatal(&format!("monomorphising SIMD type `{}` with \
                                        a non-machine element type `{}`",
                                       t, e))
          }
          let llet = in_memory_type_of(cx, e);
          let n = t.simd_size(cx.tcx()) as u64;
          Type::vector(&llet, n)
      }
      ty::TyAdt(..) => {
          // Only create the named struct, but don't fill it in. We
          // fill it in *after* placing it into the type cache. This
          // avoids creating more than one copy of the enum when one
          // of the enum's variants refers to the enum itself.
          let name = llvm_type_name(cx, t);
          adt::incomplete_type_of(cx, t, &name[..])
      }
      ty::TyInfer(..) |
      ty::TyProjection(..) |
      ty::TyParam(..) |
      ty::TyAnon(..) |
      ty::TyError => bug!("type_of with {:?}", t),
    };
    debug!("--> mapped t={:?} to llty={:?}", t, llty);
    cx.lltypes().borrow_mut().insert(t, llty);
    // If this was an enum or struct, fill in the type now.
    match t.sty {
        ty::TyAdt(..) | ty::TyClosure(..) if !t.is_simd() && !t.is_box() => {
            adt::finish_type_of(cx, t, &mut llty);
        }
        _ => ()
    }
    llty
}
pub fn in_memory_type_of < ' a , ' tcx > ( cx : & CrateContext < ' a , ' tcx > , t : Ty < ' tcx > ) -> Type { // Check the cache. if let Some ( & llty ) = cx . lltypes ( ) . borrow ( ) . get ( & t ) { return llty ; } debug ! ( " " t ) ; assert ! ( t has_escaping_regions ( ) " " t ) ; // Replace any typedef'd types with their equivalent non-typedef // type. This ensures that all LLVM nominal types that contain // Rust types are defined as the same LLVM types.  If we don't do // this then, e.g. `Option<{myfield: bool}>` would be a different // type than `Option<myrec>`. let t_norm = cx . tcx ( ) . erase_regions ( & t ) ; if t != t_norm { let llty = in_memory_type_of ( cx , t_norm ) ; debug ! ( " " t t_norm llty ) ; cx . lltypes ( ) . borrow_mut ( ) . insert ( t , llty ) ; return llty ; } let ptr_ty = | ty : Ty < ' tcx > | { if ! cx . shared ( ) . type_is_sized ( ty ) { if let ty :: TyStr = ty . sty { // This means we get a nicer name in the output (str is always // unsized). cx . str_slice_type ( ) } else { let ptr_ty = in_memory_type_of ( cx , ty ) . ptr_to ( ) ; let info_ty = unsized_info_ty ( cx , ty ) ; Type :: struct_ ( cx , & [ ptr_ty , info_ty ] , false ) } } else { in_memory_type_of ( cx , ty ) . ptr_to ( ) } } ; let mut llty = match t . sty { ty :: TyBool => Type :: bool ( cx ) , ty :: TyChar => Type :: char ( cx ) , ty :: TyInt ( t ) => Type :: int_from_ty ( cx , t ) , ty :: TyUint ( t ) => Type :: uint_from_ty ( cx , t ) , ty :: TyFloat ( t ) => Type :: float_from_ty ( cx , t ) , ty :: TyNever => Type :: nil ( cx ) , ty :: TyClosure ( .. ) => { // Only create the named struct, but don't fill it in. We // fill it in *after* placing it into the type cache. adt :: incomplete_type_of ( cx , t , " " ) } ty :: TyRef ( _ , ty :: TypeAndMut { ty , .. } ) | ty :: TyRawPtr ( ty :: TypeAndMut { ty , .. } ) => { ptr_ty ( ty ) } ty :: TyAdt ( def , _ ) if def . is_box ( ) => { ptr_ty ( t . boxed_ty ( ) ) } ty :: TyArray ( ty , size ) => { let size = size as u64 ; let llty = in_memory_type_of ( cx , ty ) ; Type :: array ( & llty , size ) } // Unsized slice types (and str) have the type of their element, and // traits have the type of u8. This is so that the data pointer inside // fat pointers is of the right type (e.g. for array accesses), even // when taking the address of an unsized field in a struct. ty :: TySlice ( ty ) => in_memory_type_of ( cx , ty ) , ty :: TyStr | ty :: TyDynamic ( .. ) => Type :: i8 ( cx ) , ty :: TyFnDef ( .. ) => Type :: nil ( cx ) , ty :: TyFnPtr ( sig ) => { let sig = cx . tcx ( ) . erase_late_bound_regions_and_normalize ( & sig ) ; FnType :: new ( cx , sig , & [ ] ) . llvm_type ( cx ) . ptr_to ( ) } ty :: TyTuple ( ref tys , _ ) if tys . is_empty ( ) => Type :: nil ( cx ) , ty :: TyTuple ( .. ) => { adt :: type_of ( cx , t ) } ty :: TyAdt ( .. ) if t . is_simd ( ) => { let e = t . simd_type ( cx . tcx ( ) ) ; if ! e . is_machine ( ) { cx . sess ( ) . fatal ( & format ! ( " \
 " t e ) ) } let llet = in_memory_type_of ( cx , e ) ; let n = t . simd_size ( cx . tcx ( ) ) as u64 ; Type :: vector ( & llet , n ) } ty :: TyAdt ( .. ) => { // Only create the named struct, but don't fill it in. We // fill it in *after* placing it into the type cache. This // avoids creating more than one copy of the enum when one // of the enum's variants refers to the enum itself. let name = llvm_type_name ( cx , t ) ; adt :: incomplete_type_of ( cx , t , & name [ .. ] ) } ty :: TyInfer ( .. ) | ty :: TyProjection ( .. ) | ty :: TyParam ( .. ) | ty :: TyAnon ( .. ) | ty :: TyError => bug ! ( " " t ) , } ; debug ! ( " " t llty ) ; cx . lltypes ( ) . borrow_mut ( ) . insert ( t , llty ) ; // If this was an enum or struct, fill in the type now. match t . sty { ty :: TyAdt ( .. ) | ty :: TyClosure ( .. ) if ! t . is_simd ( ) && ! t . is_box ( ) => { adt :: finish_type_of ( cx , t , & mut llty ) ; } _ => ( ) } llty }
Get the LLVM type corresponding to a Rust type, i.e.
Get the LLVM type corresponding to a Rust type i . e .
cx
&CrateContext<'a, 'tcx>
t
Ty<'tcx>
cx
&CrateContext<'a, 'tcx>
t
Ty<'tcx>