diff --git a/src/librustc_middle/ty/layout.rs b/src/librustc_middle/ty/layout.rs index 610a7cd41be2..cb937bf0112a 100644 --- a/src/librustc_middle/ty/layout.rs +++ b/src/librustc_middle/ty/layout.rs @@ -2302,10 +2302,19 @@ impl<'tcx> ty::Instance<'tcx> { // FIXME(davidtwco,eddyb): A `ParamEnv` should be passed through to this function. let ty = self.ty(tcx, ty::ParamEnv::reveal_all()); match ty.kind { - ty::FnDef(..) | - // Shims currently have type FnPtr. Not sure this should remain. - ty::FnPtr(_) => { - let mut sig = ty.fn_sig(tcx); + ty::FnDef(..) => { + // HACK(davidtwco,eddyb): This is a workaround for polymorphization considering + // parameters unused if they show up in the signature, but not in the `mir::Body` + // (i.e. due to being inside a projection that got normalized, see + // `src/test/ui/polymorphization/normalized_sig_types.rs`), and codegen not keeping + // track of a polymorphization `ParamEnv` to allow normalizing later. + let mut sig = match ty.kind { + ty::FnDef(def_id, substs) => tcx + .normalize_erasing_regions(tcx.param_env(def_id), tcx.fn_sig(def_id)) + .subst(tcx, substs), + _ => unreachable!(), + }; + if let ty::InstanceDef::VtableShim(..) = self.def { // Modify `fn(self, ...)` to `fn(self: *mut Self, ...)`. sig = sig.map_bound(|mut sig| { @@ -2321,13 +2330,15 @@ impl<'tcx> ty::Instance<'tcx> { let sig = substs.as_closure().sig(); 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 - )) + 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(_, substs, _) => { let sig = substs.as_generator().poly_sig(); @@ -2343,10 +2354,8 @@ impl<'tcx> ty::Instance<'tcx> { sig.map_bound(|sig| { let state_did = tcx.require_lang_item(GeneratorStateLangItem, None); let state_adt_ref = tcx.adt_def(state_did); - let state_substs = tcx.intern_substs(&[ - sig.yield_ty.into(), - sig.return_ty.into(), - ]); + 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( @@ -2354,11 +2363,11 @@ impl<'tcx> ty::Instance<'tcx> { &ret_ty, false, hir::Unsafety::Normal, - rustc_target::spec::abi::Abi::Rust + rustc_target::spec::abi::Abi::Rust, ) }) } - _ => bug!("unexpected type {:?} in Instance::fn_sig", ty) + _ => bug!("unexpected type {:?} in Instance::fn_sig", ty), } } } diff --git a/src/test/ui/polymorphization/normalized_sig_types.rs b/src/test/ui/polymorphization/normalized_sig_types.rs new file mode 100644 index 000000000000..fa76b7201e8c --- /dev/null +++ b/src/test/ui/polymorphization/normalized_sig_types.rs @@ -0,0 +1,25 @@ +// build-pass + +pub trait ParallelIterator: Sized { + fn drive>(_: C) { + C::into_folder(); + } +} + +pub trait Consumer: Sized { + type Result; + fn into_folder() -> Self::Result; +} + +impl ParallelIterator for () {} + +impl Consumer for F { + type Result = (); + fn into_folder() -> Self::Result { + unimplemented!() + } +} + +fn main() { + <()>::drive(|| ()); +}