|
8 | 8 | // option. This file may not be copied, modified, or distributed |
9 | 9 | // except according to those terms. |
10 | 10 |
|
| 11 | +use hir::Unsafety; |
11 | 12 | use hir::def_id::DefId; |
12 | | -use ty::{self, Ty, TypeFoldable, Substs, TyCtxt}; |
| 13 | +use ty::{self, Ty, PolyFnSig, TypeFoldable, Substs, TyCtxt}; |
13 | 14 | use traits; |
14 | 15 | use rustc_target::spec::abi::Abi; |
15 | 16 | use util::ppaux; |
16 | 17 |
|
17 | 18 | use std::fmt; |
| 19 | +use std::iter; |
18 | 20 |
|
19 | 21 | #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] |
20 | 22 | pub struct Instance<'tcx> { |
@@ -59,6 +61,65 @@ impl<'a, 'tcx> Instance<'tcx> { |
59 | 61 | &ty, |
60 | 62 | ) |
61 | 63 | } |
| 64 | + |
| 65 | + fn fn_sig_noadjust(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> PolyFnSig<'tcx> { |
| 66 | + let ty = self.ty(tcx); |
| 67 | + match ty.sty { |
| 68 | + ty::FnDef(..) | |
| 69 | + // Shims currently have type FnPtr. Not sure this should remain. |
| 70 | + ty::FnPtr(_) => ty.fn_sig(tcx), |
| 71 | + ty::Closure(def_id, substs) => { |
| 72 | + let sig = substs.closure_sig(def_id, tcx); |
| 73 | + |
| 74 | + let env_ty = tcx.closure_env_ty(def_id, substs).unwrap(); |
| 75 | + sig.map_bound(|sig| tcx.mk_fn_sig( |
| 76 | + iter::once(*env_ty.skip_binder()).chain(sig.inputs().iter().cloned()), |
| 77 | + sig.output(), |
| 78 | + sig.variadic, |
| 79 | + sig.unsafety, |
| 80 | + sig.abi |
| 81 | + )) |
| 82 | + } |
| 83 | + ty::Generator(def_id, substs, _) => { |
| 84 | + let sig = substs.poly_sig(def_id, tcx); |
| 85 | + |
| 86 | + let env_region = ty::ReLateBound(ty::INNERMOST, ty::BrEnv); |
| 87 | + let env_ty = tcx.mk_mut_ref(tcx.mk_region(env_region), ty); |
| 88 | + |
| 89 | + sig.map_bound(|sig| { |
| 90 | + let state_did = tcx.lang_items().gen_state().unwrap(); |
| 91 | + let state_adt_ref = tcx.adt_def(state_did); |
| 92 | + let state_substs = tcx.intern_substs(&[ |
| 93 | + sig.yield_ty.into(), |
| 94 | + sig.return_ty.into(), |
| 95 | + ]); |
| 96 | + let ret_ty = tcx.mk_adt(state_adt_ref, state_substs); |
| 97 | + |
| 98 | + tcx.mk_fn_sig(iter::once(env_ty), |
| 99 | + ret_ty, |
| 100 | + false, |
| 101 | + Unsafety::Normal, |
| 102 | + Abi::Rust |
| 103 | + ) |
| 104 | + }) |
| 105 | + } |
| 106 | + _ => bug!("unexpected type {:?} in Instance::fn_sig_noadjust", ty) |
| 107 | + } |
| 108 | + } |
| 109 | + |
| 110 | + pub fn fn_sig(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ty::PolyFnSig<'tcx> { |
| 111 | + let mut fn_sig = self.fn_sig_noadjust(tcx); |
| 112 | + if let InstanceDef::VtableShim(..) = self.def { |
| 113 | + // Modify fn(self, ...) to fn(self: *mut Self, ...) |
| 114 | + fn_sig = fn_sig.map_bound(|mut fn_sig| { |
| 115 | + let mut inputs_and_output = fn_sig.inputs_and_output.to_vec(); |
| 116 | + inputs_and_output[0] = tcx.mk_mut_ptr(inputs_and_output[0]); |
| 117 | + fn_sig.inputs_and_output = tcx.intern_type_list(&inputs_and_output); |
| 118 | + fn_sig |
| 119 | + }); |
| 120 | + } |
| 121 | + fn_sig |
| 122 | + } |
62 | 123 | } |
63 | 124 |
|
64 | 125 | impl<'tcx> InstanceDef<'tcx> { |
|
0 commit comments