diff options
| author | David Wood <david@davidtw.co> | 2020-06-22 13:57:03 +0100 |
|---|---|---|
| committer | David Wood <david@davidtw.co> | 2020-07-20 19:35:30 +0100 |
| commit | 2989fea88a489a01b3e2243bb84b0ec20b8a0e28 (patch) | |
| tree | 3fc7bedb5e5c8531c204b79510f7d61dd33f1e65 /src/test/ui/polymorphization | |
| parent | 47756bb0faaf49be5c4086fd0fdbdd57f055781b (diff) | |
| download | rust-2989fea88a489a01b3e2243bb84b0ec20b8a0e28.tar.gz rust-2989fea88a489a01b3e2243bb84b0ec20b8a0e28.zip | |
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 <david@davidtw.co>
Diffstat (limited to 'src/test/ui/polymorphization')
19 files changed, 891 insertions, 0 deletions
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<const T: usize>() -> 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<const T: usize>() -> 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<const T: usize>() -> 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<const T: usize>() -> 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<const T: usize>() -> usize { + let x = || unused::<T>(); + 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 <https://github.com/rust-lang/rust/issues/44580> for more information + +error: item has unused generic parameters + --> $DIR/closures.rs:17:19 + | +LL | pub fn unused<const T: usize>() -> 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<const T: usize>() -> usize { + | ^^^^^^ - generic parameter `T` is unused + +error: item has unused generic parameters + --> $DIR/closures.rs:25:19 + | +LL | pub fn used_parent<const T: usize>() -> 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<const T: usize>() -> 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<const T: usize>() { +//~^ ERROR item has unused generic parameters +} + +// Function uses generic parameter in value of a binding. +pub fn used_binding<const T: usize>() -> usize { + let x: usize = T; + x +} + +// Function uses generic parameter in substitutions to another function. +pub fn used_substs<const T: usize>() { + unused::<T>() +} + +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 <https://github.com/rust-lang/rust/issues/44580> for more information + +error: item has unused generic parameters + --> $DIR/functions.rs:13:8 + | +LL | pub fn unused<const T: usize>() { + | ^^^^^^ - 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<F: Fn()>(pub F); + +impl<F: Fn()> Drop for OnDrop<F> { + fn drop(&mut self) { } +} + +fn foo<R, S: FnOnce()>( + _: 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<F: Fn()>(pub F); + +impl<F: Fn()> Drop for OnDrop<F> { + fn drop(&mut self) { } +} + +fn bar<F: FnOnce()>(f: F) { + let _ = OnDrop(|| ()); + f() +} + +fn foo<R, S: FnOnce()>( + _: 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<Y, R> { + Yield(Y), + Return(R), +} + +fn finish<T, Y, R>(mut t: T) -> Vec<YieldOrReturn<Y, R>> +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<T>() -> 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<Y: Default>() -> impl Generator<(), Yield = Y, Return = u32> + Unpin { + || { + yield Y::default(); + 2 + } +} + +pub fn used_type_in_return<R: Default>() -> impl Generator<(), Yield = u32, Return = R> + Unpin { + || { + yield 3; + R::default() + } +} + +pub fn unused_const<const T: u32>() -> 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<const Y: u32>() -> impl Generator<(), Yield = u32, Return = u32> + Unpin +{ + || { + yield Y; + 2 + } +} + +pub fn used_const_in_return<const R: u32>() -> impl Generator<(), Yield = u32, Return = u32> + Unpin +{ + || { + yield 4; + R + } +} + +fn main() { + finish(unused_type::<u32>()); + finish(used_type_in_yield::<u32>()); + finish(used_type_in_return::<u32>()); + 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 <https://github.com/rust-lang/rust/issues/44580> for more information + +error: item has unused generic parameters + --> $DIR/generators.rs:35:5 + | +LL | pub fn unused_type<T>() -> 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<T>() -> 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<const T: u32>() -> 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<const T: u32>() -> 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::<u32>(&3); + used::<u32>(&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<I>() { +//~^ ERROR item has unused generic parameters +} + +fn foo<I, T>(_: I) +where + I: Iterator<Item = T>, +{ + bar::<I>() +} + +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<I>() { + | ^^^ - 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<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>() +{ + let _: Option<A> = None; + let _: Option<B> = None; + let _: Option<C> = None; + let _: Option<D> = None; + let _: Option<E> = None; + let _: Option<F> = None; + let _: Option<G> = None; + let _: Option<H> = None; + let _: Option<I> = None; + let _: Option<J> = None; + let _: Option<K> = None; + let _: Option<L> = None; + let _: Option<M> = None; + let _: Option<N> = None; + let _: Option<O> = None; + let _: Option<P> = None; + let _: Option<Q> = None; + let _: Option<R> = None; + let _: Option<S> = None; + let _: Option<T> = None; + let _: Option<U> = None; + let _: Option<V> = None; + let _: Option<W> = None; + let _: Option<X> = None; + let _: Option<Y> = None; + let _: Option<Z> = None; + let _: Option<AA> = None; + let _: Option<AB> = None; + let _: Option<AC> = None; + let _: Option<AD> = None; + let _: Option<AE> = None; + let _: Option<AF> = None; + let _: Option<AG> = None; + let _: Option<AH> = None; + let _: Option<AI> = None; + let _: Option<AJ> = None; + let _: Option<AK> = None; + let _: Option<AL> = None; + let _: Option<AM> = None; + let _: Option<AN> = None; + let _: Option<AO> = None; + let _: Option<AP> = None; + let _: Option<AQ> = None; + let _: Option<AR> = None; + let _: Option<AS> = None; + let _: Option<AT> = None; + let _: Option<AU> = None; + let _: Option<AV> = None; + let _: Option<AW> = None; + let _: Option<AX> = None; + let _: Option<AY> = None; + let _: Option<BA> = None; + let _: Option<BB> = None; + let _: Option<BC> = None; + let _: Option<BD> = None; + let _: Option<BE> = None; + let _: Option<BF> = None; + let _: Option<BG> = None; + let _: Option<BH> = None; + let _: Option<BI> = None; + let _: Option<BJ> = None; + let _: Option<BK> = None; + let _: Option<BL> = 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<T>() -> 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<T: Default>() -> 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: Default>() -> 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<T>() -> Option<T> { + let x = || { + let y: Option<T> = None; + y + }; + + x() +} + +// Function and closure uses generic parameter in argument. +pub fn used_argument<T>(t: T) -> u32 { + let x = |_: T| 3; + x(t) +} + +// Closure uses generic parameter in argument. +pub fn used_argument_closure<T: Default>() -> u32 { + let t: T = Default::default(); + let x = |_: T| 3; + x(t) +} + +// Closure uses generic parameter as upvar. +pub fn used_upvar<T: Default>() -> T { + let x: T = Default::default(); + let y = || x; + y() +} + +// Closure uses generic parameter in substitutions to another function. +pub fn used_substs<T>() -> u32 { + let x = || unused::<T>(); + x() +} + +struct Foo<F>(F); + +impl<F: Default> Foo<F> { + // Function has an unused generic parameter from impl and fn. + pub fn unused_all<G: Default>() -> 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<G: Default>() -> 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<G: Default>() -> 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<G: Default>() -> 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::<F>(); + x() + } +} + +fn main() { + no_parameters(); + let _ = unused::<u32>(); + let _ = used_parent::<u32>(); + let _ = used_binding_value::<u32>(); + let _ = used_binding_generic::<u32>(); + let _ = used_argument(3u32); + let _ = used_argument_closure::<u32>(); + let _ = used_upvar::<u32>(); + let _ = used_substs::<u32>(); + + let _ = Foo::<u32>::unused_all::<u32>(); + let _ = Foo::<u32>::used_both::<u32>(); + let _ = Foo::<u32>::used_impl::<u32>(); + let _ = Foo::<u32>::used_fn::<u32>(); + let _ = Foo::<u32>::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<T>() -> 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<T>() -> u32 { + | ^^^^^^ - generic parameter `T` is unused + +error: item has unused generic parameters + --> $DIR/closures.rs:23:19 + | +LL | pub fn used_parent<T: Default>() -> 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<F: Default> Foo<F> { + | - generic parameter `F` is unused +LL | // Function has an unused generic parameter from impl and fn. +LL | pub fn unused_all<G: Default>() -> 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<F: Default> Foo<F> { + | - generic parameter `F` is unused +LL | // Function has an unused generic parameter from impl and fn. +LL | pub fn unused_all<G: Default>() -> u32 { + | ^^^^^^^^^^ - generic parameter `G` is unused + +error: item has unused generic parameters + --> $DIR/closures.rs:111:23 + | +LL | pub fn used_impl<G: Default>() -> 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<G: Default>() -> u32 { + | ^^^^^^^^^ - generic parameter `G` is unused + +error: item has unused generic parameters + --> $DIR/closures.rs:99:23 + | +LL | impl<F: Default> Foo<F> { + | - 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<F: Default> Foo<F> { + | - generic parameter `F` is unused +... +LL | pub fn used_fn<G: Default>() -> 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<T>() { +//~^ ERROR item has unused generic parameters +} + +// Function uses generic parameter in value of a binding. +pub fn used_binding_value<T: Default>() { + let _: T = Default::default(); +} + +// Function uses generic parameter in generic of a binding. +pub fn used_binding_generic<T>() { + let _: Option<T> = None; +} + +// Function uses generic parameter in argument. +pub fn used_argument<T>(_: T) { +} + +// Function uses generic parameter in substitutions to another function. +pub fn used_substs<T>() { + unused::<T>() +} + +struct Foo<F>(F); + +impl<F: Default> Foo<F> { + // 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<G: Default>() { +//~^ 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<G: Default>() { +//~^ ERROR item has unused generic parameters + let _: G = Default::default(); + } + + // Function uses generic parameter from impl. + pub fn used_both<G: Default>() { + let _: F = Default::default(); + let _: G = Default::default(); + } + + // Function uses generic parameter in substitutions to another function. + pub fn used_substs() { + unused::<F>() + } +} + +fn main() { + no_parameters(); + unused::<u32>(); + used_binding_value::<u32>(); + used_binding_generic::<u32>(); + used_argument(3u32); + used_substs::<u32>(); + + Foo::<u32>::unused_impl(); + Foo::<u32>::unused_both::<u32>(); + Foo::<u32>::used_impl(); + Foo::<u32>::used_fn::<u32>(); + Foo::<u32>::used_both::<u32>(); + Foo::<u32>::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<T>() { + | ^^^^^^ - generic parameter `T` is unused + +error: item has unused generic parameters + --> $DIR/functions.rs:38:12 + | +LL | impl<F: Default> Foo<F> { + | - 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<F: Default> Foo<F> { + | - generic parameter `F` is unused +... +LL | pub fn unused_both<G: Default>() { + | ^^^^^^^^^^^ - generic parameter `G` is unused + +error: item has unused generic parameters + --> $DIR/functions.rs:53:12 + | +LL | impl<F: Default> Foo<F> { + | - generic parameter `F` is unused +... +LL | pub fn used_fn<G: Default>() { + | ^^^^^^^ + +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<T: Default>() { + let _: T = Default::default(); + (|| Box::new(|| {}) as Box<dyn Fn()>)(); + //~^ ERROR item has unused generic parameters + //~^^ ERROR item has unused generic parameters +} + +fn foo2<T: Default>() { + let _: T = Default::default(); + (|| { + let call: extern "rust-call" fn(_, _) = Fn::call; + call(&|| {}, ()); + //~^ ERROR item has unused generic parameters + })(); +} + +fn main() { + foo::<u32>(); + foo2::<u32>(); +} 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<T: Default>() { + | - generic parameter `T` is unused +LL | let _: T = Default::default(); +LL | (|| Box::new(|| {}) as Box<dyn Fn()>)(); + | ^^^^^ + +error: item has unused generic parameters + --> $DIR/unsized_cast.rs:10:5 + | +LL | fn foo<T: Default>() { + | - generic parameter `T` is unused +LL | let _: T = Default::default(); +LL | (|| Box::new(|| {}) as Box<dyn Fn()>)(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: item has unused generic parameters + --> $DIR/unsized_cast.rs:19:15 + | +LL | fn foo2<T: Default>() { + | - generic parameter `T` is unused +... +LL | call(&|| {}, ()); + | ^^^^^ + +error: aborting due to 3 previous errors + |
