about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDavid Wood <david@davidtw.co>2020-06-22 14:00:27 +0100
committerDavid Wood <david@davidtw.co>2020-07-20 19:35:32 +0100
commitf52c72948aa1dd718cc1f168d21c91c584c0a662 (patch)
tree1879e860dbd4ac450fb15504a31d41be71d1102b
parent2989fea88a489a01b3e2243bb84b0ec20b8a0e28 (diff)
downloadrust-f52c72948aa1dd718cc1f168d21c91c584c0a662.tar.gz
rust-f52c72948aa1dd718cc1f168d21c91c584c0a662.zip
ty: normalize fn sigs before subst
This commit normalizes function signatures for instances before
substituting, a workaround for polymorphization considering
parameters unused when they show up in the signature, but not the
body (due to being normalized).

Unfortunately, this causes test output to change with the parallel
compiler only.

Signed-off-by: David Wood <david@davidtw.co>
-rw-r--r--src/librustc_middle/ty/layout.rs43
-rw-r--r--src/test/ui/polymorphization/normalized_sig_types.rs25
2 files changed, 51 insertions, 17 deletions
diff --git a/src/librustc_middle/ty/layout.rs b/src/librustc_middle/ty/layout.rs
index 610a7cd41be..cb937bf0112 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 00000000000..fa76b7201e8
--- /dev/null
+++ b/src/test/ui/polymorphization/normalized_sig_types.rs
@@ -0,0 +1,25 @@
+// build-pass
+
+pub trait ParallelIterator: Sized {
+    fn drive<C: Consumer<()>>(_: C) {
+        C::into_folder();
+    }
+}
+
+pub trait Consumer<T>: Sized {
+    type Result;
+    fn into_folder() -> Self::Result;
+}
+
+impl ParallelIterator for () {}
+
+impl<F: Fn(), T> Consumer<T> for F {
+    type Result = ();
+    fn into_folder() -> Self::Result {
+        unimplemented!()
+    }
+}
+
+fn main() {
+    <()>::drive(|| ());
+}