diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index 06fc168bd5740..f270d3d3a2a59 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -1,8 +1,7 @@ use crate::hir::CodegenFnAttrFlags; -use crate::hir::Unsafety; use crate::hir::def::Namespace; use crate::hir::def_id::DefId; -use crate::ty::{self, Ty, PolyFnSig, TypeFoldable, SubstsRef, TyCtxt}; +use crate::ty::{self, Ty, TypeFoldable, SubstsRef, TyCtxt}; use crate::ty::print::{FmtPrinter, Printer}; use crate::traits; use crate::middle::lang_items::DropInPlaceFnLangItem; @@ -10,7 +9,6 @@ use rustc_target::spec::abi::Abi; use rustc_macros::HashStable; use std::fmt; -use std::iter; #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] #[derive(HashStable, Lift)] @@ -66,68 +64,6 @@ impl<'tcx> Instance<'tcx> { &ty, ) } - - pub fn fn_sig(&self, tcx: TyCtxt<'tcx>) -> PolyFnSig<'tcx> { - let ty = self.ty(tcx); - match ty.kind { - ty::FnDef(..) | - // Shims currently have type FnPtr. Not sure this should remain. - ty::FnPtr(_) => { - let mut sig = ty.fn_sig(tcx); - if let InstanceDef::VtableShim(..) = self.def { - // Modify `fn(self, ...)` to `fn(self: *mut Self, ...)`. - sig = sig.map_bound(|mut sig| { - let mut inputs_and_output = sig.inputs_and_output.to_vec(); - inputs_and_output[0] = tcx.mk_mut_ptr(inputs_and_output[0]); - sig.inputs_and_output = tcx.intern_type_list(&inputs_and_output); - sig - }); - } - sig - } - ty::Closure(def_id, substs) => { - let sig = substs.as_closure().sig(def_id, tcx); - - let env_ty = tcx.closure_env_ty(def_id, substs).unwrap(); - sig.map_bound(|sig| tcx.mk_fn_sig( - iter::once(*env_ty.skip_binder()).chain(sig.inputs().iter().cloned()), - sig.output(), - sig.c_variadic, - sig.unsafety, - sig.abi - )) - } - ty::Generator(def_id, substs, _) => { - let sig = substs.as_generator().poly_sig(def_id, tcx); - - let env_region = ty::ReLateBound(ty::INNERMOST, ty::BrEnv); - let env_ty = tcx.mk_mut_ref(tcx.mk_region(env_region), ty); - - let pin_did = tcx.lang_items().pin_type().unwrap(); - let pin_adt_ref = tcx.adt_def(pin_did); - let pin_substs = tcx.intern_substs(&[env_ty.into()]); - let env_ty = tcx.mk_adt(pin_adt_ref, pin_substs); - - sig.map_bound(|sig| { - let state_did = tcx.lang_items().gen_state().unwrap(); - let state_adt_ref = tcx.adt_def(state_did); - let state_substs = tcx.intern_substs(&[ - sig.yield_ty.into(), - sig.return_ty.into(), - ]); - let ret_ty = tcx.mk_adt(state_adt_ref, state_substs); - - tcx.mk_fn_sig(iter::once(env_ty), - ret_ty, - false, - Unsafety::Normal, - Abi::Rust - ) - }) - } - _ => bug!("unexpected type {:?} in Instance::fn_sig", ty) - } - } } impl<'tcx> InstanceDef<'tcx> { diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 1662776adf50f..4d48c7841451f 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -2339,6 +2339,76 @@ impl<'a, 'tcx> HashStable> for LayoutError<'tcx> { } } + +impl<'tcx> ty::Instance<'tcx> { + // NOTE(eddyb) this is private to avoid using it from outside of + // `FnAbi::of_instance` - any other uses are either too high-level + // for `Instance` (e.g. typeck would use `Ty::fn_sig` instead), + // or should go through `FnAbi` instead, to avoid losing any + // adjustments `FnAbi::of_instance` might be performing. + fn fn_sig_for_fn_abi(&self, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> { + let ty = self.ty(tcx); + match ty.kind { + ty::FnDef(..) | + // Shims currently have type FnPtr. Not sure this should remain. + ty::FnPtr(_) => { + let mut sig = ty.fn_sig(tcx); + if let ty::InstanceDef::VtableShim(..) = self.def { + // Modify `fn(self, ...)` to `fn(self: *mut Self, ...)`. + sig = sig.map_bound(|mut sig| { + let mut inputs_and_output = sig.inputs_and_output.to_vec(); + inputs_and_output[0] = tcx.mk_mut_ptr(inputs_and_output[0]); + sig.inputs_and_output = tcx.intern_type_list(&inputs_and_output); + sig + }); + } + sig + } + ty::Closure(def_id, substs) => { + let sig = substs.as_closure().sig(def_id, tcx); + + let env_ty = tcx.closure_env_ty(def_id, substs).unwrap(); + sig.map_bound(|sig| tcx.mk_fn_sig( + iter::once(*env_ty.skip_binder()).chain(sig.inputs().iter().cloned()), + sig.output(), + sig.c_variadic, + sig.unsafety, + sig.abi + )) + } + ty::Generator(def_id, substs, _) => { + let sig = substs.as_generator().poly_sig(def_id, tcx); + + let env_region = ty::ReLateBound(ty::INNERMOST, ty::BrEnv); + let env_ty = tcx.mk_mut_ref(tcx.mk_region(env_region), ty); + + let pin_did = tcx.lang_items().pin_type().unwrap(); + let pin_adt_ref = tcx.adt_def(pin_did); + let pin_substs = tcx.intern_substs(&[env_ty.into()]); + let env_ty = tcx.mk_adt(pin_adt_ref, pin_substs); + + sig.map_bound(|sig| { + let state_did = tcx.lang_items().gen_state().unwrap(); + let state_adt_ref = tcx.adt_def(state_did); + let state_substs = tcx.intern_substs(&[ + sig.yield_ty.into(), + sig.return_ty.into(), + ]); + let ret_ty = tcx.mk_adt(state_adt_ref, state_substs); + + tcx.mk_fn_sig(iter::once(env_ty), + ret_ty, + false, + hir::Unsafety::Normal, + rustc_target::spec::abi::Abi::Rust + ) + }) + } + _ => bug!("unexpected type {:?} in Instance::fn_sig", ty) + } + } +} + pub trait FnAbiExt<'tcx, C> where C: LayoutOf, TyLayout = TyLayout<'tcx>> @@ -2371,7 +2441,7 @@ where } fn of_instance(cx: &C, instance: ty::Instance<'tcx>, extra_args: &[Ty<'tcx>]) -> Self { - let sig = instance.fn_sig(cx.tcx()); + let sig = instance.fn_sig_for_fn_abi(cx.tcx()); call::FnAbi::new_internal(cx, sig, extra_args, |ty, arg_idx| { let mut layout = cx.layout_of(ty);