From 2989fea88a489a01b3e2243bb84b0ec20b8a0e28 Mon Sep 17 00:00:00 2001 From: David Wood Date: Mon, 22 Jun 2020 13:57:03 +0100 Subject: mir: `unused_generic_params` query This commit implements the `unused_generic_params` query, an initial version of polymorphization which detects when an item does not use generic parameters and is being needlessly monomorphized as a result. Signed-off-by: David Wood --- .../polymorphization/const_parameters/closures.rs | 61 +++++++++ .../const_parameters/closures.stderr | 44 +++++++ .../polymorphization/const_parameters/functions.rs | 33 +++++ .../const_parameters/functions.stderr | 17 +++ src/test/ui/polymorphization/drop_shims/simple.rs | 21 +++ .../ui/polymorphization/drop_shims/transitive.rs | 26 ++++ src/test/ui/polymorphization/generators.rs | 88 +++++++++++++ src/test/ui/polymorphization/generators.stderr | 49 +++++++ src/test/ui/polymorphization/lifetimes.rs | 22 ++++ src/test/ui/polymorphization/lifetimes.stderr | 17 +++ src/test/ui/polymorphization/predicates.rs | 21 +++ src/test/ui/polymorphization/predicates.stderr | 8 ++ .../ui/polymorphization/too-many-generic-params.rs | 76 +++++++++++ .../polymorphization/type_parameters/closures.rs | 143 +++++++++++++++++++++ .../type_parameters/closures.stderr | 90 +++++++++++++ .../polymorphization/type_parameters/functions.rs | 84 ++++++++++++ .../type_parameters/functions.stderr | 35 +++++ src/test/ui/polymorphization/unsized_cast.rs | 27 ++++ src/test/ui/polymorphization/unsized_cast.stderr | 29 +++++ 19 files changed, 891 insertions(+) create mode 100644 src/test/ui/polymorphization/const_parameters/closures.rs create mode 100644 src/test/ui/polymorphization/const_parameters/closures.stderr create mode 100644 src/test/ui/polymorphization/const_parameters/functions.rs create mode 100644 src/test/ui/polymorphization/const_parameters/functions.stderr create mode 100644 src/test/ui/polymorphization/drop_shims/simple.rs create mode 100644 src/test/ui/polymorphization/drop_shims/transitive.rs create mode 100644 src/test/ui/polymorphization/generators.rs create mode 100644 src/test/ui/polymorphization/generators.stderr create mode 100644 src/test/ui/polymorphization/lifetimes.rs create mode 100644 src/test/ui/polymorphization/lifetimes.stderr create mode 100644 src/test/ui/polymorphization/predicates.rs create mode 100644 src/test/ui/polymorphization/predicates.stderr create mode 100644 src/test/ui/polymorphization/too-many-generic-params.rs create mode 100644 src/test/ui/polymorphization/type_parameters/closures.rs create mode 100644 src/test/ui/polymorphization/type_parameters/closures.stderr create mode 100644 src/test/ui/polymorphization/type_parameters/functions.rs create mode 100644 src/test/ui/polymorphization/type_parameters/functions.stderr create mode 100644 src/test/ui/polymorphization/unsized_cast.rs create mode 100644 src/test/ui/polymorphization/unsized_cast.stderr (limited to 'src/test/ui/polymorphization') diff --git a/src/test/ui/polymorphization/const_parameters/closures.rs b/src/test/ui/polymorphization/const_parameters/closures.rs new file mode 100644 index 00000000000..da83cc1bee4 --- /dev/null +++ b/src/test/ui/polymorphization/const_parameters/closures.rs @@ -0,0 +1,61 @@ +// build-fail +// compile-flags: -Zpolymorphize-errors +#![feature(const_generics)] +//~^ 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. +pub fn no_parameters() { + let _ = || {}; +} + +// Function has an unused generic parameter in parent and closure. +pub fn unused() -> usize { +//~^ ERROR item has unused generic parameters + let add_one = |x: usize| x + 1; +//~^ ERROR item has unused generic parameters + add_one(3) +} + +// Function has an unused generic parameter in closure, but not in parent. +pub fn used_parent() -> usize { + let x: usize = T; + let add_one = |x: usize| x + 1; +//~^ ERROR item has unused generic parameters + x + add_one(3) +} + +// Function uses generic parameter in value of a binding in closure. +pub fn used_binding() -> usize { + let x = || { + let y: usize = T; + y + }; + + x() +} + +// Closure uses a value as an upvar, which used the generic parameter. +pub fn unused_upvar() -> usize { + let x: usize = T; + let y = || x; +//~^ ERROR item has unused generic parameters + y() +} + +// Closure uses generic parameter in substitutions to another function. +pub fn used_substs() -> usize { + let x = || unused::(); + x() +} + +fn main() { + no_parameters(); + let _ = unused::<1>(); + let _ = used_parent::<1>(); + let _ = used_binding::<1>(); + let _ = unused_upvar::<1>(); + let _ = used_substs::<1>(); +} diff --git a/src/test/ui/polymorphization/const_parameters/closures.stderr b/src/test/ui/polymorphization/const_parameters/closures.stderr new file mode 100644 index 00000000000..73a071f346a --- /dev/null +++ b/src/test/ui/polymorphization/const_parameters/closures.stderr @@ -0,0 +1,44 @@ +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/closures.rs:3:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information + +error: item has unused generic parameters + --> $DIR/closures.rs:17:19 + | +LL | pub fn unused() -> usize { + | - generic parameter `T` is unused +LL | +LL | let add_one = |x: usize| x + 1; + | ^^^^^^^^^^^^^^^^ + +error: item has unused generic parameters + --> $DIR/closures.rs:15:8 + | +LL | pub fn unused() -> usize { + | ^^^^^^ - generic parameter `T` is unused + +error: item has unused generic parameters + --> $DIR/closures.rs:25:19 + | +LL | pub fn used_parent() -> usize { + | - generic parameter `T` is unused +LL | let x: usize = T; +LL | let add_one = |x: usize| x + 1; + | ^^^^^^^^^^^^^^^^ + +error: item has unused generic parameters + --> $DIR/closures.rs:43:13 + | +LL | pub fn unused_upvar() -> usize { + | - generic parameter `T` is unused +LL | let x: usize = T; +LL | let y = || x; + | ^^^^ + +error: aborting due to 4 previous errors; 1 warning emitted + diff --git a/src/test/ui/polymorphization/const_parameters/functions.rs b/src/test/ui/polymorphization/const_parameters/functions.rs new file mode 100644 index 00000000000..1c19f9480b4 --- /dev/null +++ b/src/test/ui/polymorphization/const_parameters/functions.rs @@ -0,0 +1,33 @@ +// build-fail +// compile-flags: -Zpolymorphize-errors +#![feature(const_generics)] +//~^ 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. +pub fn no_parameters() {} + +// Function has an unused generic parameter. +pub fn unused() { +//~^ ERROR item has unused generic parameters +} + +// Function uses generic parameter in value of a binding. +pub fn used_binding() -> usize { + let x: usize = T; + x +} + +// Function uses generic parameter in substitutions to another function. +pub fn used_substs() { + unused::() +} + +fn main() { + no_parameters(); + unused::<1>(); + used_binding::<1>(); + used_substs::<1>(); +} diff --git a/src/test/ui/polymorphization/const_parameters/functions.stderr b/src/test/ui/polymorphization/const_parameters/functions.stderr new file mode 100644 index 00000000000..a503ec51942 --- /dev/null +++ b/src/test/ui/polymorphization/const_parameters/functions.stderr @@ -0,0 +1,17 @@ +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/functions.rs:3:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information + +error: item has unused generic parameters + --> $DIR/functions.rs:13:8 + | +LL | pub fn unused() { + | ^^^^^^ - generic parameter `T` is unused + +error: aborting due to previous error; 1 warning emitted + diff --git a/src/test/ui/polymorphization/drop_shims/simple.rs b/src/test/ui/polymorphization/drop_shims/simple.rs new file mode 100644 index 00000000000..ce56b7a3588 --- /dev/null +++ b/src/test/ui/polymorphization/drop_shims/simple.rs @@ -0,0 +1,21 @@ +// check-pass + +pub struct OnDrop(pub F); + +impl Drop for OnDrop { + fn drop(&mut self) { } +} + +fn foo( + _: R, + _: S, +) { + let bar = || { + let _ = OnDrop(|| ()); + }; + let _ = bar(); +} + +fn main() { + foo(3u32, || {}); +} diff --git a/src/test/ui/polymorphization/drop_shims/transitive.rs b/src/test/ui/polymorphization/drop_shims/transitive.rs new file mode 100644 index 00000000000..b7ea07b6bc6 --- /dev/null +++ b/src/test/ui/polymorphization/drop_shims/transitive.rs @@ -0,0 +1,26 @@ +// check-pass + +pub struct OnDrop(pub F); + +impl Drop for OnDrop { + fn drop(&mut self) { } +} + +fn bar(f: F) { + let _ = OnDrop(|| ()); + f() +} + +fn foo( + _: R, + _: S, +) { + let bar = || { + bar(|| {}) + }; + let _ = bar(); +} + +fn main() { + foo(3u32, || {}); +} diff --git a/src/test/ui/polymorphization/generators.rs b/src/test/ui/polymorphization/generators.rs new file mode 100644 index 00000000000..dd7c3497de2 --- /dev/null +++ b/src/test/ui/polymorphization/generators.rs @@ -0,0 +1,88 @@ +// build-fail +// compile-flags: -Zpolymorphize-errors +#![feature(const_generics, generators, generator_trait)] +//~^ WARN the feature `const_generics` is incomplete + +use std::marker::Unpin; +use std::ops::{Generator, GeneratorState}; +use std::pin::Pin; + +enum YieldOrReturn { + Yield(Y), + Return(R), +} + +fn finish(mut t: T) -> Vec> +where + T: Generator<(), Yield = Y, Return = R> + Unpin, +{ + let mut results = Vec::new(); + loop { + match Pin::new(&mut t).resume(()) { + GeneratorState::Yielded(yielded) => results.push(YieldOrReturn::Yield(yielded)), + GeneratorState::Complete(returned) => { + results.push(YieldOrReturn::Return(returned)); + return results; + } + } + } +} + +// This test checks that the polymorphization analysis functions on generators. + +pub fn unused_type() -> impl Generator<(), Yield = u32, Return = u32> + Unpin { + //~^ ERROR item has unused generic parameters + || { + //~^ ERROR item has unused generic parameters + yield 1; + 2 + } +} + +pub fn used_type_in_yield() -> impl Generator<(), Yield = Y, Return = u32> + Unpin { + || { + yield Y::default(); + 2 + } +} + +pub fn used_type_in_return() -> impl Generator<(), Yield = u32, Return = R> + Unpin { + || { + yield 3; + R::default() + } +} + +pub fn unused_const() -> impl Generator<(), Yield = u32, Return = u32> + Unpin { + //~^ ERROR item has unused generic parameters + || { + //~^ ERROR item has unused generic parameters + yield 1; + 2 + } +} + +pub fn used_const_in_yield() -> impl Generator<(), Yield = u32, Return = u32> + Unpin +{ + || { + yield Y; + 2 + } +} + +pub fn used_const_in_return() -> impl Generator<(), Yield = u32, Return = u32> + Unpin +{ + || { + yield 4; + R + } +} + +fn main() { + finish(unused_type::()); + finish(used_type_in_yield::()); + finish(used_type_in_return::()); + finish(unused_const::<1u32>()); + finish(used_const_in_yield::<1u32>()); + finish(used_const_in_return::<1u32>()); +} diff --git a/src/test/ui/polymorphization/generators.stderr b/src/test/ui/polymorphization/generators.stderr new file mode 100644 index 00000000000..9e3ee130234 --- /dev/null +++ b/src/test/ui/polymorphization/generators.stderr @@ -0,0 +1,49 @@ +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/generators.rs:3:12 + | +LL | #![feature(const_generics, generators, generator_trait)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information + +error: item has unused generic parameters + --> $DIR/generators.rs:35:5 + | +LL | pub fn unused_type() -> impl Generator<(), Yield = u32, Return = u32> + Unpin { + | - generic parameter `T` is unused +LL | +LL | / || { +LL | | +LL | | yield 1; +LL | | 2 +LL | | } + | |_____^ + +error: item has unused generic parameters + --> $DIR/generators.rs:33:8 + | +LL | pub fn unused_type() -> impl Generator<(), Yield = u32, Return = u32> + Unpin { + | ^^^^^^^^^^^ - generic parameter `T` is unused + +error: item has unused generic parameters + --> $DIR/generators.rs:58:5 + | +LL | pub fn unused_const() -> impl Generator<(), Yield = u32, Return = u32> + Unpin { + | - generic parameter `T` is unused +LL | +LL | / || { +LL | | +LL | | yield 1; +LL | | 2 +LL | | } + | |_____^ + +error: item has unused generic parameters + --> $DIR/generators.rs:56:8 + | +LL | pub fn unused_const() -> impl Generator<(), Yield = u32, Return = u32> + Unpin { + | ^^^^^^^^^^^^ - generic parameter `T` is unused + +error: aborting due to 4 previous errors; 1 warning emitted + diff --git a/src/test/ui/polymorphization/lifetimes.rs b/src/test/ui/polymorphization/lifetimes.rs new file mode 100644 index 00000000000..873a9c7baaa --- /dev/null +++ b/src/test/ui/polymorphization/lifetimes.rs @@ -0,0 +1,22 @@ +// build-fail +// compile-flags: -Zpolymorphize-errors + +// 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. +pub fn unused<'a, T>(_: &'a u32) { +//~^ ERROR item has unused generic parameters +} + +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 + add_one(3) +} + +fn main() { + unused::(&3); + used::(&3); +} diff --git a/src/test/ui/polymorphization/lifetimes.stderr b/src/test/ui/polymorphization/lifetimes.stderr new file mode 100644 index 00000000000..5629857f85e --- /dev/null +++ b/src/test/ui/polymorphization/lifetimes.stderr @@ -0,0 +1,17 @@ +error: item has unused generic parameters + --> $DIR/lifetimes.rs:8: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 + | +LL | pub fn used<'a, T: Default>(_: &'a u32) -> u32 { + | - generic parameter `T` is unused +LL | let _: T = Default::default(); +LL | let add_one = |x: u32| x + 1; + | ^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/polymorphization/predicates.rs b/src/test/ui/polymorphization/predicates.rs new file mode 100644 index 00000000000..49f8668cff8 --- /dev/null +++ b/src/test/ui/polymorphization/predicates.rs @@ -0,0 +1,21 @@ +// build-fail +// compile-flags: -Zpolymorphize-errors + +// This test checks that `T` is considered used in `foo`, because it is used in a predicate for +// `I`, which is used. + +fn bar() { +//~^ ERROR item has unused generic parameters +} + +fn foo(_: I) +where + I: Iterator, +{ + bar::() +} + +fn main() { + let x = &[2u32]; + foo(x.iter()); +} diff --git a/src/test/ui/polymorphization/predicates.stderr b/src/test/ui/polymorphization/predicates.stderr new file mode 100644 index 00000000000..b7bc2ccce57 --- /dev/null +++ b/src/test/ui/polymorphization/predicates.stderr @@ -0,0 +1,8 @@ +error: item has unused generic parameters + --> $DIR/predicates.rs:7:4 + | +LL | fn bar() { + | ^^^ - generic parameter `I` is unused + +error: aborting due to previous error + diff --git a/src/test/ui/polymorphization/too-many-generic-params.rs b/src/test/ui/polymorphization/too-many-generic-params.rs new file mode 100644 index 00000000000..3bb77a1c1e6 --- /dev/null +++ b/src/test/ui/polymorphization/too-many-generic-params.rs @@ -0,0 +1,76 @@ +// build-pass +// compile-flags: -Zpolymorphize-errors + +// This test checks that the analysis doesn't panic when there are >64 generic parameters, but +// instead considers those parameters used. + +fn bar() +{ + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option

= None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; + let _: Option = None; +} + +fn main() { } diff --git a/src/test/ui/polymorphization/type_parameters/closures.rs b/src/test/ui/polymorphization/type_parameters/closures.rs new file mode 100644 index 00000000000..cf5a4b1cec5 --- /dev/null +++ b/src/test/ui/polymorphization/type_parameters/closures.rs @@ -0,0 +1,143 @@ +// build-fail +// compile-flags: -Zpolymorphize-errors + +// This test checks that the polymorphization analysis correctly detects unused type +// parameters in closures. + +// Function doesn't have any generic parameters to be unused. +pub fn no_parameters() { + let _ = || {}; +} + +// Function has an unused generic parameter in parent and closure. +pub fn unused() -> u32 { +//~^ ERROR item has unused generic parameters + let add_one = |x: u32| x + 1; +//~^ ERROR item has unused generic parameters + add_one(3) +} + +// Function has an unused generic parameter in closure, but not in parent. +pub fn used_parent() -> u32 { + let _: T = Default::default(); + let add_one = |x: u32| x + 1; +//~^ ERROR item has unused generic parameters + add_one(3) +} + +// Function uses generic parameter in value of a binding in closure. +pub fn used_binding_value() -> T { + let x = || { + let y: T = Default::default(); + y + }; + + x() +} + +// Function uses generic parameter in generic of a binding in closure. +pub fn used_binding_generic() -> Option { + let x = || { + let y: Option = None; + y + }; + + x() +} + +// Function and closure uses generic parameter in argument. +pub fn used_argument(t: T) -> u32 { + let x = |_: T| 3; + x(t) +} + +// Closure uses generic parameter in argument. +pub fn used_argument_closure() -> u32 { + let t: T = Default::default(); + let x = |_: T| 3; + x(t) +} + +// Closure uses generic parameter as upvar. +pub fn used_upvar() -> T { + let x: T = Default::default(); + let y = || x; + y() +} + +// Closure uses generic parameter in substitutions to another function. +pub fn used_substs() -> u32 { + let x = || unused::(); + x() +} + +struct Foo(F); + +impl Foo { + // Function has an unused generic parameter from impl and fn. + pub fn unused_all() -> u32 { +//~^ ERROR item has unused generic parameters + let add_one = |x: u32| x + 1; +//~^ ERROR item has unused generic parameters + add_one(3) + } + + // Function uses generic parameter from impl and fn in closure. + pub fn used_both() -> u32 { + let add_one = |x: u32| { + let _: F = Default::default(); + let _: G = Default::default(); + x + 1 + }; + + add_one(3) + } + + // Function uses generic parameter from fn in closure. + pub fn used_fn() -> u32 { +//~^ ERROR item has unused generic parameters + let add_one = |x: u32| { +//~^ ERROR item has unused generic parameters + let _: G = Default::default(); + x + 1 + }; + + add_one(3) + } + + // Function uses generic parameter from impl in closure. + pub fn used_impl() -> u32 { +//~^ ERROR item has unused generic parameters + let add_one = |x: u32| { +//~^ ERROR item has unused generic parameters + let _: F = Default::default(); + x + 1 + }; + + add_one(3) + } + + // Closure uses generic parameter in substitutions to another function. + pub fn used_substs() -> u32 { + let x = || unused::(); + x() + } +} + +fn main() { + no_parameters(); + let _ = unused::(); + let _ = used_parent::(); + let _ = used_binding_value::(); + let _ = used_binding_generic::(); + let _ = used_argument(3u32); + let _ = used_argument_closure::(); + let _ = used_upvar::(); + let _ = used_substs::(); + + let _ = Foo::::unused_all::(); + let _ = Foo::::used_both::(); + let _ = Foo::::used_impl::(); + let _ = Foo::::used_fn::(); + let _ = Foo::::used_substs(); +} diff --git a/src/test/ui/polymorphization/type_parameters/closures.stderr b/src/test/ui/polymorphization/type_parameters/closures.stderr new file mode 100644 index 00000000000..914cb628bd0 --- /dev/null +++ b/src/test/ui/polymorphization/type_parameters/closures.stderr @@ -0,0 +1,90 @@ +error: item has unused generic parameters + --> $DIR/closures.rs:15:19 + | +LL | pub fn unused() -> u32 { + | - generic parameter `T` is unused +LL | +LL | let add_one = |x: u32| x + 1; + | ^^^^^^^^^^^^^^ + +error: item has unused generic parameters + --> $DIR/closures.rs:13:8 + | +LL | pub fn unused() -> u32 { + | ^^^^^^ - generic parameter `T` is unused + +error: item has unused generic parameters + --> $DIR/closures.rs:23:19 + | +LL | pub fn used_parent() -> u32 { + | - generic parameter `T` is unused +LL | let _: T = Default::default(); +LL | let add_one = |x: u32| x + 1; + | ^^^^^^^^^^^^^^ + +error: item has unused generic parameters + --> $DIR/closures.rs:80:23 + | +LL | impl Foo { + | - generic parameter `F` is unused +LL | // Function has an unused generic parameter from impl and fn. +LL | pub fn unused_all() -> u32 { + | - generic parameter `G` is unused +LL | +LL | let add_one = |x: u32| x + 1; + | ^^^^^^^^^^^^^^ + +error: item has unused generic parameters + --> $DIR/closures.rs:78:12 + | +LL | impl Foo { + | - generic parameter `F` is unused +LL | // Function has an unused generic parameter from impl and fn. +LL | pub fn unused_all() -> u32 { + | ^^^^^^^^^^ - generic parameter `G` is unused + +error: item has unused generic parameters + --> $DIR/closures.rs:111:23 + | +LL | pub fn used_impl() -> u32 { + | - generic parameter `G` is unused +LL | +LL | let add_one = |x: u32| { + | _______________________^ +LL | | +LL | | let _: F = Default::default(); +LL | | x + 1 +LL | | }; + | |_________^ + +error: item has unused generic parameters + --> $DIR/closures.rs:109:12 + | +LL | pub fn used_impl() -> u32 { + | ^^^^^^^^^ - generic parameter `G` is unused + +error: item has unused generic parameters + --> $DIR/closures.rs:99:23 + | +LL | impl Foo { + | - generic parameter `F` is unused +... +LL | let add_one = |x: u32| { + | _______________________^ +LL | | +LL | | let _: G = Default::default(); +LL | | x + 1 +LL | | }; + | |_________^ + +error: item has unused generic parameters + --> $DIR/closures.rs:97:12 + | +LL | impl Foo { + | - generic parameter `F` is unused +... +LL | pub fn used_fn() -> u32 { + | ^^^^^^^ + +error: aborting due to 9 previous errors + diff --git a/src/test/ui/polymorphization/type_parameters/functions.rs b/src/test/ui/polymorphization/type_parameters/functions.rs new file mode 100644 index 00000000000..3caf2631a57 --- /dev/null +++ b/src/test/ui/polymorphization/type_parameters/functions.rs @@ -0,0 +1,84 @@ +// build-fail +// compile-flags: -Zpolymorphize-errors + +// This test checks that the polymorphization analysis correctly detects unused type +// parameters in functions. + +// Function doesn't have any generic parameters to be unused. +pub fn no_parameters() {} + +// Function has an unused generic parameter. +pub fn unused() { +//~^ ERROR item has unused generic parameters +} + +// Function uses generic parameter in value of a binding. +pub fn used_binding_value() { + let _: T = Default::default(); +} + +// Function uses generic parameter in generic of a binding. +pub fn used_binding_generic() { + let _: Option = None; +} + +// Function uses generic parameter in argument. +pub fn used_argument(_: T) { +} + +// Function uses generic parameter in substitutions to another function. +pub fn used_substs() { + unused::() +} + +struct Foo(F); + +impl Foo { + // Function has an unused generic parameter from impl. + pub fn unused_impl() { +//~^ ERROR item has unused generic parameters + } + + // Function has an unused generic parameter from impl and fn. + pub fn unused_both() { +//~^ ERROR item has unused generic parameters + } + + // Function uses generic parameter from impl. + pub fn used_impl() { + let _: F = Default::default(); + } + + // Function uses generic parameter from impl. + pub fn used_fn() { +//~^ ERROR item has unused generic parameters + let _: G = Default::default(); + } + + // Function uses generic parameter from impl. + pub fn used_both() { + let _: F = Default::default(); + let _: G = Default::default(); + } + + // Function uses generic parameter in substitutions to another function. + pub fn used_substs() { + unused::() + } +} + +fn main() { + no_parameters(); + unused::(); + used_binding_value::(); + used_binding_generic::(); + used_argument(3u32); + used_substs::(); + + Foo::::unused_impl(); + Foo::::unused_both::(); + Foo::::used_impl(); + Foo::::used_fn::(); + Foo::::used_both::(); + Foo::::used_substs(); +} diff --git a/src/test/ui/polymorphization/type_parameters/functions.stderr b/src/test/ui/polymorphization/type_parameters/functions.stderr new file mode 100644 index 00000000000..a34e677a765 --- /dev/null +++ b/src/test/ui/polymorphization/type_parameters/functions.stderr @@ -0,0 +1,35 @@ +error: item has unused generic parameters + --> $DIR/functions.rs:11:8 + | +LL | pub fn unused() { + | ^^^^^^ - generic parameter `T` is unused + +error: item has unused generic parameters + --> $DIR/functions.rs:38:12 + | +LL | impl Foo { + | - generic parameter `F` is unused +LL | // Function has an unused generic parameter from impl. +LL | pub fn unused_impl() { + | ^^^^^^^^^^^ + +error: item has unused generic parameters + --> $DIR/functions.rs:43:12 + | +LL | impl Foo { + | - generic parameter `F` is unused +... +LL | pub fn unused_both() { + | ^^^^^^^^^^^ - generic parameter `G` is unused + +error: item has unused generic parameters + --> $DIR/functions.rs:53:12 + | +LL | impl Foo { + | - generic parameter `F` is unused +... +LL | pub fn used_fn() { + | ^^^^^^^ + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/polymorphization/unsized_cast.rs b/src/test/ui/polymorphization/unsized_cast.rs new file mode 100644 index 00000000000..3bc25d18981 --- /dev/null +++ b/src/test/ui/polymorphization/unsized_cast.rs @@ -0,0 +1,27 @@ +// build-fail +// compile-flags: -Zpolymorphize-errors +#![feature(fn_traits, unboxed_closures)] + +// This test checks that the polymorphization analysis considers a closure +// as using all generic parameters if it does an unsizing cast. + +fn foo() { + let _: T = Default::default(); + (|| Box::new(|| {}) as Box)(); + //~^ ERROR item has unused generic parameters + //~^^ ERROR item has unused generic parameters +} + +fn foo2() { + let _: T = Default::default(); + (|| { + let call: extern "rust-call" fn(_, _) = Fn::call; + call(&|| {}, ()); + //~^ ERROR item has unused generic parameters + })(); +} + +fn main() { + foo::(); + foo2::(); +} diff --git a/src/test/ui/polymorphization/unsized_cast.stderr b/src/test/ui/polymorphization/unsized_cast.stderr new file mode 100644 index 00000000000..61fd3884117 --- /dev/null +++ b/src/test/ui/polymorphization/unsized_cast.stderr @@ -0,0 +1,29 @@ +error: item has unused generic parameters + --> $DIR/unsized_cast.rs:10:18 + | +LL | fn foo() { + | - generic parameter `T` is unused +LL | let _: T = Default::default(); +LL | (|| Box::new(|| {}) as Box)(); + | ^^^^^ + +error: item has unused generic parameters + --> $DIR/unsized_cast.rs:10:5 + | +LL | fn foo() { + | - generic parameter `T` is unused +LL | let _: T = Default::default(); +LL | (|| Box::new(|| {}) as Box)(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: item has unused generic parameters + --> $DIR/unsized_cast.rs:19:15 + | +LL | fn foo2() { + | - generic parameter `T` is unused +... +LL | call(&|| {}, ()); + | ^^^^^ + +error: aborting due to 3 previous errors + -- cgit 1.4.1-3-g733a5