Skip to content

Commit

Permalink
Auto merge of rust-lang#75260 - davidtwco:polymorphization-promoted-s…
Browse files Browse the repository at this point in the history
…ubsts, r=lcnr

polymorphize: unevaluated constants

This PR makes polymorphization visit the promoted MIR of unevaluated constants with available promoted MIR instead of visiting the substitutions of that constant - which will mark all of the generic parameters as used; in addition polymorphization will now visit non-promoted unevaluated constants rather than visit their substs.

r? @lcnr
  • Loading branch information
bors committed Aug 8, 2020
2 parents 2bac92b + d97f89b commit 3f091ba
Show file tree
Hide file tree
Showing 8 changed files with 104 additions and 15 deletions.
45 changes: 32 additions & 13 deletions src/librustc_mir/monomorphize/polymorphize.rs
Expand Up @@ -15,6 +15,7 @@ use rustc_middle::ty::{
self,
fold::{TypeFoldable, TypeVisitor},
query::Providers,
subst::SubstsRef,
Const, Ty, TyCtxt,
};
use rustc_span::symbol::sym;
Expand Down Expand Up @@ -209,6 +210,25 @@ struct UsedGenericParametersVisitor<'a, 'tcx> {
unused_parameters: &'a mut FiniteBitSet<u32>,
}

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);
Expand Down Expand Up @@ -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),
}
}
Expand All @@ -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) => {
Expand Down
12 changes: 12 additions & 0 deletions 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<T>() {
//~^ ERROR item has unused generic parameters
foo(&());
}
8 changes: 8 additions & 0 deletions 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<T>() {
| ^^^^ - generic parameter `T` is unused

error: aborting due to previous error

16 changes: 16 additions & 0 deletions 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<T>() {
//~^ ERROR item has unused generic parameters
let x = [0; 3 + 4];
}

pub fn caller() {
test::<String>();
test::<Vec<String>>();
}
17 changes: 17 additions & 0 deletions 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 <https://github.com/rust-lang/rust/issues/72219> for more information

error: item has unused generic parameters
--> $DIR/promoted-function-2.rs:8:4
|
LL | fn test<T>() {
| ^^^^ - generic parameter `T` is unused

error: aborting due to previous error; 1 warning emitted

2 changes: 2 additions & 0 deletions src/test/ui/polymorphization/promoted-function.rs
@@ -1,4 +1,6 @@
// run-pass
// compile-flags:-Zpolymorphize=on

fn fop<T>() {}

fn bar<T>() -> &'static fn() {
Expand Down
1 change: 1 addition & 0 deletions src/test/ui/polymorphization/unsized_cast.rs
Expand Up @@ -17,6 +17,7 @@ fn foo<T: Default>() {
fn foo2<T: Default>() {
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
Expand Down
18 changes: 16 additions & 2 deletions src/test/ui/polymorphization/unsized_cast.stderr
Expand Up @@ -17,13 +17,27 @@ LL | (|| Box::new(|| {}) as Box<dyn Fn()>)();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: item has unused generic parameters
--> $DIR/unsized_cast.rs:21:15
--> $DIR/unsized_cast.rs:22:15
|
LL | fn foo2<T: Default>() {
| - generic parameter `T` is unused
...
LL | call(&|| {}, ());
| ^^^^^

error: aborting due to 3 previous errors
error: item has unused generic parameters
--> $DIR/unsized_cast.rs:19:5
|
LL | fn foo2<T: Default>() {
| - 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

0 comments on commit 3f091ba

Please sign in to comment.