diff --git a/src/librustc_mir/monomorphize/polymorphize.rs b/src/librustc_mir/monomorphize/polymorphize.rs index 592c809c1dec6..a996b6fb9d924 100644 --- a/src/librustc_mir/monomorphize/polymorphize.rs +++ b/src/librustc_mir/monomorphize/polymorphize.rs @@ -15,6 +15,7 @@ use rustc_middle::ty::{ self, fold::{TypeFoldable, TypeVisitor}, query::Providers, + subst::SubstsRef, Const, Ty, TyCtxt, }; use rustc_span::symbol::sym; @@ -209,6 +210,25 @@ struct UsedGenericParametersVisitor<'a, 'tcx> { unused_parameters: &'a mut FiniteBitSet, } +impl<'a, 'tcx> UsedGenericParametersVisitor<'a, 'tcx> { + /// Invoke `unused_generic_params` on a body contained within the current item (e.g. + /// a closure, generator or constant). + fn visit_child_body(&mut self, def_id: DefId, substs: SubstsRef<'tcx>) { + let unused = self.tcx.unused_generic_params(def_id); + debug!( + "visit_child_body: unused_parameters={:?} unused={:?}", + self.unused_parameters, unused + ); + for (i, arg) in substs.iter().enumerate() { + let i = i.try_into().unwrap(); + if !unused.contains(i).unwrap_or(false) { + arg.visit_with(self); + } + } + debug!("visit_child_body: unused_parameters={:?}", self.unused_parameters); + } +} + impl<'a, 'tcx> Visitor<'tcx> for UsedGenericParametersVisitor<'a, 'tcx> { fn visit_local_decl(&mut self, local: Local, local_decl: &LocalDecl<'tcx>) { debug!("visit_local_decl: local_decl={:?}", local_decl); @@ -249,6 +269,17 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for UsedGenericParametersVisitor<'a, 'tcx> { self.unused_parameters.clear(param.index); false } + ty::ConstKind::Unevaluated(_, _, Some(p)) => { + // If there is a promoted, don't look at the substs - since it will always contain + // the generic parameters, instead, traverse the promoted MIR. + let promoted = self.tcx.promoted_mir(self.def_id); + self.visit_body(&promoted[p]); + false + } + ty::ConstKind::Unevaluated(def_id, unevaluated_substs, None) => { + self.visit_child_body(def_id.did, unevaluated_substs); + false + } _ => c.super_visit_with(self), } } @@ -269,19 +300,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for UsedGenericParametersVisitor<'a, 'tcx> { // Consider any generic parameters used by any closures/generators as used in the // parent. - let unused = self.tcx.unused_generic_params(def_id); - debug!( - "visit_ty: unused_parameters={:?} unused={:?}", - self.unused_parameters, unused - ); - for (i, arg) in substs.iter().enumerate() { - let i = i.try_into().unwrap(); - if !unused.contains(i).unwrap_or(false) { - arg.visit_with(self); - } - } - debug!("visit_ty: unused_parameters={:?}", self.unused_parameters); - + self.visit_child_body(def_id, substs); false } ty::Param(param) => { diff --git a/src/test/ui/polymorphization/promoted-function-1.rs b/src/test/ui/polymorphization/promoted-function-1.rs new file mode 100644 index 0000000000000..2cd02673442fe --- /dev/null +++ b/src/test/ui/polymorphization/promoted-function-1.rs @@ -0,0 +1,12 @@ +// build-fail +// compile-flags: -Zpolymorphize=on +#![crate_type = "lib"] +#![feature(rustc_attrs)] + +fn foo<'a>(_: &'a ()) {} + +#[rustc_polymorphize_error] +pub fn test() { + //~^ ERROR item has unused generic parameters + foo(&()); +} diff --git a/src/test/ui/polymorphization/promoted-function-1.stderr b/src/test/ui/polymorphization/promoted-function-1.stderr new file mode 100644 index 0000000000000..fcbb86949232b --- /dev/null +++ b/src/test/ui/polymorphization/promoted-function-1.stderr @@ -0,0 +1,8 @@ +error: item has unused generic parameters + --> $DIR/promoted-function-1.rs:9:8 + | +LL | pub fn test() { + | ^^^^ - generic parameter `T` is unused + +error: aborting due to previous error + diff --git a/src/test/ui/polymorphization/promoted-function-2.rs b/src/test/ui/polymorphization/promoted-function-2.rs new file mode 100644 index 0000000000000..2831f861f5561 --- /dev/null +++ b/src/test/ui/polymorphization/promoted-function-2.rs @@ -0,0 +1,16 @@ +// build-fail +// compile-flags:-Zpolymorphize=on +#![crate_type = "lib"] +#![feature(lazy_normalization_consts, rustc_attrs)] +//~^ WARN the feature `lazy_normalization_consts` is incomplete + +#[rustc_polymorphize_error] +fn test() { + //~^ ERROR item has unused generic parameters + let x = [0; 3 + 4]; +} + +pub fn caller() { + test::(); + test::>(); +} diff --git a/src/test/ui/polymorphization/promoted-function-2.stderr b/src/test/ui/polymorphization/promoted-function-2.stderr new file mode 100644 index 0000000000000..38d4808c48c03 --- /dev/null +++ b/src/test/ui/polymorphization/promoted-function-2.stderr @@ -0,0 +1,17 @@ +warning: the feature `lazy_normalization_consts` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/promoted-function-2.rs:4:12 + | +LL | #![feature(lazy_normalization_consts, rustc_attrs)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #72219 for more information + +error: item has unused generic parameters + --> $DIR/promoted-function-2.rs:8:4 + | +LL | fn test() { + | ^^^^ - generic parameter `T` is unused + +error: aborting due to previous error; 1 warning emitted + diff --git a/src/test/ui/polymorphization/promoted-function.rs b/src/test/ui/polymorphization/promoted-function.rs index 0d3af7a89c2aa..a56a8e70e4c50 100644 --- a/src/test/ui/polymorphization/promoted-function.rs +++ b/src/test/ui/polymorphization/promoted-function.rs @@ -1,4 +1,6 @@ // run-pass +// compile-flags:-Zpolymorphize=on + fn fop() {} fn bar() -> &'static fn() { diff --git a/src/test/ui/polymorphization/unsized_cast.rs b/src/test/ui/polymorphization/unsized_cast.rs index b8facc1607010..b803fec2ccfdb 100644 --- a/src/test/ui/polymorphization/unsized_cast.rs +++ b/src/test/ui/polymorphization/unsized_cast.rs @@ -17,6 +17,7 @@ fn foo() { fn foo2() { let _: T = Default::default(); (|| { + //~^ ERROR item has unused generic parameters let call: extern "rust-call" fn(_, _) = Fn::call; call(&|| {}, ()); //~^ ERROR item has unused generic parameters diff --git a/src/test/ui/polymorphization/unsized_cast.stderr b/src/test/ui/polymorphization/unsized_cast.stderr index d4727acca9afd..b51cc5c719f0b 100644 --- a/src/test/ui/polymorphization/unsized_cast.stderr +++ b/src/test/ui/polymorphization/unsized_cast.stderr @@ -17,7 +17,7 @@ LL | (|| Box::new(|| {}) as Box)(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: item has unused generic parameters - --> $DIR/unsized_cast.rs:21:15 + --> $DIR/unsized_cast.rs:22:15 | LL | fn foo2() { | - generic parameter `T` is unused @@ -25,5 +25,19 @@ LL | fn foo2() { LL | call(&|| {}, ()); | ^^^^^ -error: aborting due to 3 previous errors +error: item has unused generic parameters + --> $DIR/unsized_cast.rs:19:5 + | +LL | fn foo2() { + | - generic parameter `T` is unused +LL | let _: T = Default::default(); +LL | / (|| { +LL | | +LL | | let call: extern "rust-call" fn(_, _) = Fn::call; +LL | | call(&|| {}, ()); +LL | | +LL | | })(); + | |______^ + +error: aborting due to 4 previous errors