Skip to content

Commit

Permalink
mir: use attribute over -Z polymorphize-errors
Browse files Browse the repository at this point in the history
This commit replaces the `-Z polymorphize-errors` debugging flag with a
`#[rustc_polymorphize_error]` attribute for use on functions.

Signed-off-by: David Wood <david@davidtw.co>
  • Loading branch information
davidtwco committed Jul 20, 2020
1 parent 5ce29d3 commit b1f8bd6
Show file tree
Hide file tree
Showing 21 changed files with 125 additions and 76 deletions.
1 change: 1 addition & 0 deletions src/librustc_feature/builtin_attrs.rs
Expand Up @@ -568,6 +568,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
),
rustc_attr!(TEST, rustc_synthetic, AssumedUsed, template!(Word)),
rustc_attr!(TEST, rustc_symbol_name, AssumedUsed, template!(Word)),
rustc_attr!(TEST, rustc_polymorphize_error, AssumedUsed, template!(Word)),
rustc_attr!(TEST, rustc_def_path, AssumedUsed, template!(Word)),
rustc_attr!(TEST, rustc_mir, AssumedUsed, template!(List: "arg1, arg2, ...")),
rustc_attr!(TEST, rustc_dump_program_clauses, AssumedUsed, template!(Word)),
Expand Down
10 changes: 6 additions & 4 deletions src/librustc_mir/monomorphize/polymorphize.rs
Expand Up @@ -16,6 +16,7 @@ use rustc_middle::ty::{
query::Providers,
Const, Ty, TyCtxt,
};
use rustc_span::symbol::sym;
use std::convert::TryInto;

/// Provide implementations of queries relating to polymorphization analysis.
Expand Down Expand Up @@ -77,7 +78,7 @@ fn unused_generic_params(tcx: TyCtxt<'_>, def_id: DefId) -> u64 {

// Emit errors for debugging and testing if enabled.
let is_full = unused_parameters == 0;
if tcx.sess.opts.debugging_opts.polymorphize_errors && !is_full {
if !is_full {
emit_unused_generic_params_error(tcx, def_id, generics, unused_parameters);
}

Expand Down Expand Up @@ -169,16 +170,17 @@ fn mark_used_by_predicates<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, used_paramete
}
}

/// Emit an error for the function represented by `def_id`, labelling each generic parameter which
/// was unused.
/// Emit errors for the function annotated by `#[rustc_polymorphize_error]`, labelling each generic
/// parameter which was unused.
fn emit_unused_generic_params_error<'tcx>(
tcx: TyCtxt<'tcx>,
def_id: DefId,
generics: &'tcx ty::Generics,
unused_parameters: u64,
) {
debug!("emit_unused_generic_params_error: def_id={:?}", def_id);
if !def_id.is_local() {
let base_def_id = tcx.closure_base_def_id(def_id);
if !tcx.get_attrs(base_def_id).iter().any(|a| a.check_name(sym::rustc_polymorphize_error)) {
return;
}

Expand Down
2 changes: 0 additions & 2 deletions src/librustc_session/options.rs
Expand Up @@ -951,8 +951,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
"enable polonius-based borrow-checker (default: no)"),
polymorphize: bool = (true, parse_bool, [TRACKED],
"perform polymorphization analysis"),
polymorphize_errors: bool = (false, parse_bool, [TRACKED],
"emit errors from polymorphization analysis for debugging"),
pre_link_arg: (/* redirected to pre_link_args */) = ((), parse_string_push, [UNTRACKED],
"a single extra argument to prepend the linker invocation (can be used several times)"),
pre_link_args: Vec<String> = (Vec::new(), parse_list, [UNTRACKED],
Expand Down
1 change: 1 addition & 0 deletions src/librustc_span/symbol.rs
Expand Up @@ -921,6 +921,7 @@ symbols! {
rustc_peek_liveness,
rustc_peek_maybe_init,
rustc_peek_maybe_uninit,
rustc_polymorphize_error,
rustc_private,
rustc_proc_macro_decls,
rustc_promotable,
Expand Down
17 changes: 11 additions & 6 deletions src/test/ui/polymorphization/const_parameters/closures.rs
@@ -1,33 +1,36 @@
// build-fail
// compile-flags: -Zpolymorphize-errors
#![feature(const_generics)]
#![feature(const_generics, rustc_attrs)]
//~^ WARN the feature `const_generics` is incomplete

// This test checks that the polymorphization analysis correctly detects unused const
// parameters in closures.

// Function doesn't have any generic parameters to be unused.
#[rustc_polymorphize_error]
pub fn no_parameters() {
let _ = || {};
}

// Function has an unused generic parameter in parent and closure.
#[rustc_polymorphize_error]
pub fn unused<const T: usize>() -> usize {
//~^ ERROR item has unused generic parameters
//~^ ERROR item has unused generic parameters
let add_one = |x: usize| x + 1;
//~^ ERROR item has unused generic parameters
//~^ ERROR item has unused generic parameters
add_one(3)
}

// Function has an unused generic parameter in closure, but not in parent.
#[rustc_polymorphize_error]
pub fn used_parent<const T: usize>() -> usize {
let x: usize = T;
let add_one = |x: usize| x + 1;
//~^ ERROR item has unused generic parameters
//~^ ERROR item has unused generic parameters
x + add_one(3)
}

// Function uses generic parameter in value of a binding in closure.
#[rustc_polymorphize_error]
pub fn used_binding<const T: usize>() -> usize {
let x = || {
let y: usize = T;
Expand All @@ -38,14 +41,16 @@ pub fn used_binding<const T: usize>() -> usize {
}

// Closure uses a value as an upvar, which used the generic parameter.
#[rustc_polymorphize_error]
pub fn unused_upvar<const T: usize>() -> usize {
let x: usize = T;
let y = || x;
//~^ ERROR item has unused generic parameters
//~^ ERROR item has unused generic parameters
y()
}

// Closure uses generic parameter in substitutions to another function.
#[rustc_polymorphize_error]
pub fn used_substs<const T: usize>() -> usize {
let x = || unused::<T>();
x()
Expand Down
12 changes: 6 additions & 6 deletions src/test/ui/polymorphization/const_parameters/closures.stderr
@@ -1,14 +1,14 @@
warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/closures.rs:3:12
--> $DIR/closures.rs:2:12
|
LL | #![feature(const_generics)]
LL | #![feature(const_generics, rustc_attrs)]
| ^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information

error: item has unused generic parameters
--> $DIR/closures.rs:17:19
--> $DIR/closures.rs:18:19
|
LL | pub fn unused<const T: usize>() -> usize {
| - generic parameter `T` is unused
Expand All @@ -17,13 +17,13 @@ LL | let add_one = |x: usize| x + 1;
| ^^^^^^^^^^^^^^^^

error: item has unused generic parameters
--> $DIR/closures.rs:15:8
--> $DIR/closures.rs:16:8
|
LL | pub fn unused<const T: usize>() -> usize {
| ^^^^^^ - generic parameter `T` is unused

error: item has unused generic parameters
--> $DIR/closures.rs:25:19
--> $DIR/closures.rs:27:19
|
LL | pub fn used_parent<const T: usize>() -> usize {
| - generic parameter `T` is unused
Expand All @@ -32,7 +32,7 @@ LL | let add_one = |x: usize| x + 1;
| ^^^^^^^^^^^^^^^^

error: item has unused generic parameters
--> $DIR/closures.rs:43:13
--> $DIR/closures.rs:47:13
|
LL | pub fn unused_upvar<const T: usize>() -> usize {
| - generic parameter `T` is unused
Expand Down
9 changes: 6 additions & 3 deletions src/test/ui/polymorphization/const_parameters/functions.rs
@@ -1,26 +1,29 @@
// build-fail
// compile-flags: -Zpolymorphize-errors
#![feature(const_generics)]
#![feature(const_generics, rustc_attrs)]
//~^ WARN the feature `const_generics` is incomplete

// This test checks that the polymorphization analysis correctly detects unused const
// parameters in functions.

// Function doesn't have any generic parameters to be unused.
#[rustc_polymorphize_error]
pub fn no_parameters() {}

// Function has an unused generic parameter.
#[rustc_polymorphize_error]
pub fn unused<const T: usize>() {
//~^ ERROR item has unused generic parameters
//~^ ERROR item has unused generic parameters
}

// Function uses generic parameter in value of a binding.
#[rustc_polymorphize_error]
pub fn used_binding<const T: usize>() -> usize {
let x: usize = T;
x
}

// Function uses generic parameter in substitutions to another function.
#[rustc_polymorphize_error]
pub fn used_substs<const T: usize>() {
unused::<T>()
}
Expand Down
@@ -1,14 +1,14 @@
warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/functions.rs:3:12
--> $DIR/functions.rs:2:12
|
LL | #![feature(const_generics)]
LL | #![feature(const_generics, rustc_attrs)]
| ^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information

error: item has unused generic parameters
--> $DIR/functions.rs:13:8
--> $DIR/functions.rs:14:8
|
LL | pub fn unused<const T: usize>() {
| ^^^^^^ - generic parameter `T` is unused
Expand Down
9 changes: 7 additions & 2 deletions src/test/ui/polymorphization/generators.rs
@@ -1,6 +1,5 @@
// build-fail
// compile-flags: -Zpolymorphize-errors
#![feature(const_generics, generators, generator_trait)]
#![feature(const_generics, generators, generator_trait, rustc_attrs)]
//~^ WARN the feature `const_generics` is incomplete

use std::marker::Unpin;
Expand Down Expand Up @@ -30,6 +29,7 @@ where

// This test checks that the polymorphization analysis functions on generators.

#[rustc_polymorphize_error]
pub fn unused_type<T>() -> impl Generator<(), Yield = u32, Return = u32> + Unpin {
//~^ ERROR item has unused generic parameters
|| {
Expand All @@ -39,20 +39,23 @@ pub fn unused_type<T>() -> impl Generator<(), Yield = u32, Return = u32> + Unpin
}
}

#[rustc_polymorphize_error]
pub fn used_type_in_yield<Y: Default>() -> impl Generator<(), Yield = Y, Return = u32> + Unpin {
|| {
yield Y::default();
2
}
}

#[rustc_polymorphize_error]
pub fn used_type_in_return<R: Default>() -> impl Generator<(), Yield = u32, Return = R> + Unpin {
|| {
yield 3;
R::default()
}
}

#[rustc_polymorphize_error]
pub fn unused_const<const T: u32>() -> impl Generator<(), Yield = u32, Return = u32> + Unpin {
//~^ ERROR item has unused generic parameters
|| {
Expand All @@ -62,6 +65,7 @@ pub fn unused_const<const T: u32>() -> impl Generator<(), Yield = u32, Return =
}
}

#[rustc_polymorphize_error]
pub fn used_const_in_yield<const Y: u32>() -> impl Generator<(), Yield = u32, Return = u32> + Unpin
{
|| {
Expand All @@ -70,6 +74,7 @@ pub fn used_const_in_yield<const Y: u32>() -> impl Generator<(), Yield = u32, Re
}
}

#[rustc_polymorphize_error]
pub fn used_const_in_return<const R: u32>() -> impl Generator<(), Yield = u32, Return = u32> + Unpin
{
|| {
Expand Down
8 changes: 4 additions & 4 deletions src/test/ui/polymorphization/generators.stderr
@@ -1,7 +1,7 @@
warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/generators.rs:3:12
--> $DIR/generators.rs:2:12
|
LL | #![feature(const_generics, generators, generator_trait)]
LL | #![feature(const_generics, generators, generator_trait, rustc_attrs)]
| ^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default
Expand All @@ -27,7 +27,7 @@ LL | pub fn unused_type<T>() -> impl Generator<(), Yield = u32, Return = u32> +
| ^^^^^^^^^^^ - generic parameter `T` is unused

error: item has unused generic parameters
--> $DIR/generators.rs:58:5
--> $DIR/generators.rs:61:5
|
LL | pub fn unused_const<const T: u32>() -> impl Generator<(), Yield = u32, Return = u32> + Unpin {
| - generic parameter `T` is unused
Expand All @@ -40,7 +40,7 @@ LL | | }
| |_____^

error: item has unused generic parameters
--> $DIR/generators.rs:56:8
--> $DIR/generators.rs:59:8
|
LL | pub fn unused_const<const T: u32>() -> impl Generator<(), Yield = u32, Return = u32> + Unpin {
| ^^^^^^^^^^^^ - generic parameter `T` is unused
Expand Down
8 changes: 5 additions & 3 deletions src/test/ui/polymorphization/lifetimes.rs
@@ -1,18 +1,20 @@
// build-fail
// compile-flags: -Zpolymorphize-errors
#![feature(rustc_attrs)]

// This test checks that the polymorphization analysis doesn't break when the
// function/closure doesn't just have generic parameters.

// Function has an unused generic parameter.
#[rustc_polymorphize_error]
pub fn unused<'a, T>(_: &'a u32) {
//~^ ERROR item has unused generic parameters
//~^ ERROR item has unused generic parameters
}

#[rustc_polymorphize_error]
pub fn used<'a, T: Default>(_: &'a u32) -> u32 {
let _: T = Default::default();
let add_one = |x: u32| x + 1;
//~^ ERROR item has unused generic parameters
//~^ ERROR item has unused generic parameters
add_one(3)
}

Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/polymorphization/lifetimes.stderr
@@ -1,11 +1,11 @@
error: item has unused generic parameters
--> $DIR/lifetimes.rs:8:8
--> $DIR/lifetimes.rs:9:8
|
LL | pub fn unused<'a, T>(_: &'a u32) {
| ^^^^^^ - generic parameter `T` is unused

error: item has unused generic parameters
--> $DIR/lifetimes.rs:14:19
--> $DIR/lifetimes.rs:16:19
|
LL | pub fn used<'a, T: Default>(_: &'a u32) -> u32 {
| - generic parameter `T` is unused
Expand Down
6 changes: 4 additions & 2 deletions src/test/ui/polymorphization/predicates.rs
@@ -1,13 +1,15 @@
// build-fail
// compile-flags: -Zpolymorphize-errors
#![feature(rustc_attrs)]

// This test checks that `T` is considered used in `foo`, because it is used in a predicate for
// `I`, which is used.

#[rustc_polymorphize_error]
fn bar<I>() {
//~^ ERROR item has unused generic parameters
//~^ ERROR item has unused generic parameters
}

#[rustc_polymorphize_error]
fn foo<I, T>(_: I)
where
I: Iterator<Item = T>,
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/polymorphization/predicates.stderr
@@ -1,5 +1,5 @@
error: item has unused generic parameters
--> $DIR/predicates.rs:7:4
--> $DIR/predicates.rs:8:4
|
LL | fn bar<I>() {
| ^^^ - generic parameter `I` is unused
Expand Down
3 changes: 2 additions & 1 deletion src/test/ui/polymorphization/too-many-generic-params.rs
@@ -1,9 +1,10 @@
// build-pass
// compile-flags: -Zpolymorphize-errors
#![feature(rustc_attrs)]

// This test checks that the analysis doesn't panic when there are >64 generic parameters, but
// instead considers those parameters used.

#[rustc_polymorphize_error]
fn bar<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, AA,
AB, AC, AD, AE, AF, AG, AH, AI, AJ, AK, AL, AM, AN, AO, AP, AQ, AR, AS, AT, AU, AV, AW,
AX, AY, AZ, BA, BB, BC, BD, BE, BF, BG, BH, BI, BJ, BK, BL>()
Expand Down

0 comments on commit b1f8bd6

Please sign in to comment.