summaryrefslogtreecommitdiffstats
path: root/src/test/ui/polymorphization
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
commit698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch)
tree173a775858bd501c378080a10dca74132f05bc50 /src/test/ui/polymorphization
parentInitial commit. (diff)
downloadrustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz
rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--src/test/ui/polymorphization/closure_in_upvar/fn.rs29
-rw-r--r--src/test/ui/polymorphization/closure_in_upvar/fnmut.rs34
-rw-r--r--src/test/ui/polymorphization/closure_in_upvar/fnonce.rs34
-rw-r--r--src/test/ui/polymorphization/closure_in_upvar/other.rs38
-rw-r--r--src/test/ui/polymorphization/const_parameters/closures.rs67
-rw-r--r--src/test/ui/polymorphization/const_parameters/closures.stderr44
-rw-r--r--src/test/ui/polymorphization/const_parameters/functions.rs37
-rw-r--r--src/test/ui/polymorphization/const_parameters/functions.stderr17
-rw-r--r--src/test/ui/polymorphization/drop_shims/simple.rs22
-rw-r--r--src/test/ui/polymorphization/drop_shims/transitive.rs27
-rw-r--r--src/test/ui/polymorphization/generators.rs92
-rw-r--r--src/test/ui/polymorphization/generators.stderr39
-rw-r--r--src/test/ui/polymorphization/issue-74614.rs18
-rw-r--r--src/test/ui/polymorphization/issue-74636.rs16
-rw-r--r--src/test/ui/polymorphization/lifetimes.rs25
-rw-r--r--src/test/ui/polymorphization/lifetimes.stderr17
-rw-r--r--src/test/ui/polymorphization/normalized_sig_types.rs26
-rw-r--r--src/test/ui/polymorphization/predicates.rs95
-rw-r--r--src/test/ui/polymorphization/predicates.stderr51
-rw-r--r--src/test/ui/polymorphization/promoted-function-1.rs12
-rw-r--r--src/test/ui/polymorphization/promoted-function-1.stderr8
-rw-r--r--src/test/ui/polymorphization/promoted-function-2.rs16
-rw-r--r--src/test/ui/polymorphization/promoted-function-2.stderr17
-rw-r--r--src/test/ui/polymorphization/promoted-function-3.rs14
-rw-r--r--src/test/ui/polymorphization/promoted-function.rs15
-rw-r--r--src/test/ui/polymorphization/symbol-ambiguity.rs22
-rw-r--r--src/test/ui/polymorphization/too-many-generic-params.rs85
-rw-r--r--src/test/ui/polymorphization/type_parameters/closures.rs161
-rw-r--r--src/test/ui/polymorphization/type_parameters/closures.stderr80
-rw-r--r--src/test/ui/polymorphization/type_parameters/functions.rs96
-rw-r--r--src/test/ui/polymorphization/type_parameters/functions.stderr35
-rw-r--r--src/test/ui/polymorphization/unsized_cast.rs30
-rw-r--r--src/test/ui/polymorphization/unsized_cast.stderr38
33 files changed, 1357 insertions, 0 deletions
diff --git a/src/test/ui/polymorphization/closure_in_upvar/fn.rs b/src/test/ui/polymorphization/closure_in_upvar/fn.rs
new file mode 100644
index 000000000..e10308588
--- /dev/null
+++ b/src/test/ui/polymorphization/closure_in_upvar/fn.rs
@@ -0,0 +1,29 @@
+// build-pass
+// compile-flags:-Zpolymorphize=on -Csymbol-mangling-version=v0
+
+fn foo(f: impl Fn()) {
+ let x = |_: ()| ();
+
+ // Don't use `f` in `y`, but refer to `x` so that the closure substs contain a reference to
+ // `x` that will differ for each instantiation despite polymorphisation of the varying
+ // argument.
+ let y = || x(());
+
+ // Consider `f` used in `foo`.
+ f();
+ // Use `y` so that it is visited in monomorphisation collection.
+ y();
+}
+
+fn entry_a() {
+ foo(|| ());
+}
+
+fn entry_b() {
+ foo(|| ());
+}
+
+fn main() {
+ entry_a();
+ entry_b();
+}
diff --git a/src/test/ui/polymorphization/closure_in_upvar/fnmut.rs b/src/test/ui/polymorphization/closure_in_upvar/fnmut.rs
new file mode 100644
index 000000000..62164ff94
--- /dev/null
+++ b/src/test/ui/polymorphization/closure_in_upvar/fnmut.rs
@@ -0,0 +1,34 @@
+// build-pass
+// compile-flags:-Zpolymorphize=on -Csymbol-mangling-version=v0
+
+fn foo(f: impl Fn()) {
+ // Mutate an upvar from `x` so that it implements `FnMut`.
+ let mut outer = 3;
+ let mut x = |_: ()| {
+ outer = 4;
+ ()
+ };
+
+ // Don't use `f` in `y`, but refer to `x` so that the closure substs contain a reference to
+ // `x` that will differ for each instantiation despite polymorphisation of the varying
+ // argument.
+ let mut y = || x(());
+
+ // Consider `f` used in `foo`.
+ f();
+ // Use `y` so that it is visited in monomorphisation collection.
+ y();
+}
+
+fn entry_a() {
+ foo(|| ());
+}
+
+fn entry_b() {
+ foo(|| ());
+}
+
+fn main() {
+ entry_a();
+ entry_b();
+}
diff --git a/src/test/ui/polymorphization/closure_in_upvar/fnonce.rs b/src/test/ui/polymorphization/closure_in_upvar/fnonce.rs
new file mode 100644
index 000000000..7a364882f
--- /dev/null
+++ b/src/test/ui/polymorphization/closure_in_upvar/fnonce.rs
@@ -0,0 +1,34 @@
+// build-pass
+// compile-flags:-Zpolymorphize=on -Csymbol-mangling-version=v0
+
+fn foo(f: impl Fn()) {
+ // Move a non-copy type into `x` so that it implements `FnOnce`.
+ let outer = Vec::<u32>::new();
+ let x = move |_: ()| {
+ let inner = outer;
+ ()
+ };
+
+ // Don't use `f` in `y`, but refer to `x` so that the closure substs contain a reference to
+ // `x` that will differ for each instantiation despite polymorphisation of the varying
+ // argument.
+ let y = || x(());
+
+ // Consider `f` used in `foo`.
+ f();
+ // Use `y` so that it is visited in monomorphisation collection.
+ y();
+}
+
+fn entry_a() {
+ foo(|| ());
+}
+
+fn entry_b() {
+ foo(|| ());
+}
+
+fn main() {
+ entry_a();
+ entry_b();
+}
diff --git a/src/test/ui/polymorphization/closure_in_upvar/other.rs b/src/test/ui/polymorphization/closure_in_upvar/other.rs
new file mode 100644
index 000000000..27d59ec88
--- /dev/null
+++ b/src/test/ui/polymorphization/closure_in_upvar/other.rs
@@ -0,0 +1,38 @@
+// build-pass
+// compile-flags:-Zpolymorphize=on -Csymbol-mangling-version=v0
+
+fn y_uses_f(f: impl Fn()) {
+ let x = |_: ()| ();
+
+ let y = || {
+ f();
+ x(());
+ };
+
+ f();
+ y();
+}
+
+fn x_uses_f(f: impl Fn()) {
+ let x = |_: ()| { f(); };
+
+ let y = || x(());
+
+ f();
+ y();
+}
+
+fn entry_a() {
+ x_uses_f(|| ());
+ y_uses_f(|| ());
+}
+
+fn entry_b() {
+ x_uses_f(|| ());
+ y_uses_f(|| ());
+}
+
+fn main() {
+ entry_a();
+ entry_b();
+}
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 000000000..2f41beeb9
--- /dev/null
+++ b/src/test/ui/polymorphization/const_parameters/closures.rs
@@ -0,0 +1,67 @@
+// build-fail
+// compile-flags:-Zpolymorphize=on
+#![feature(generic_const_exprs, rustc_attrs)]
+//~^ WARN the feature `generic_const_exprs` 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
+ 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.
+#[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
+ 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;
+ y
+ };
+
+ x()
+}
+
+// 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
+ 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()
+}
+
+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 000000000..fdf817cae
--- /dev/null
+++ b/src/test/ui/polymorphization/const_parameters/closures.stderr
@@ -0,0 +1,44 @@
+warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/closures.rs:3:12
+ |
+LL | #![feature(generic_const_exprs, rustc_attrs)]
+ | ^^^^^^^^^^^^^^^^^^^
+ |
+ = note: `#[warn(incomplete_features)]` on by default
+ = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
+
+error: item has unused generic parameters
+ --> $DIR/closures.rs:19: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:17:8
+ |
+LL | pub fn unused<const T: usize>() -> usize {
+ | ^^^^^^ -------------- generic parameter `T` is unused
+
+error: item has unused generic parameters
+ --> $DIR/closures.rs:28: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:48: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 000000000..cbc1b63fb
--- /dev/null
+++ b/src/test/ui/polymorphization/const_parameters/functions.rs
@@ -0,0 +1,37 @@
+// build-fail
+// compile-flags:-Zpolymorphize=on
+#![feature(generic_const_exprs, rustc_attrs)]
+//~^ WARN the feature `generic_const_exprs` 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
+}
+
+// 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>()
+}
+
+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 000000000..f2b5a7307
--- /dev/null
+++ b/src/test/ui/polymorphization/const_parameters/functions.stderr
@@ -0,0 +1,17 @@
+warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/functions.rs:3:12
+ |
+LL | #![feature(generic_const_exprs, rustc_attrs)]
+ | ^^^^^^^^^^^^^^^^^^^
+ |
+ = note: `#[warn(incomplete_features)]` on by default
+ = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
+
+error: item has unused generic parameters
+ --> $DIR/functions.rs:15: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 000000000..2695dc6d4
--- /dev/null
+++ b/src/test/ui/polymorphization/drop_shims/simple.rs
@@ -0,0 +1,22 @@
+// check-pass
+// compile-flags:-Zpolymorphize=on
+
+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 000000000..c22891171
--- /dev/null
+++ b/src/test/ui/polymorphization/drop_shims/transitive.rs
@@ -0,0 +1,27 @@
+// check-pass
+// compile-flags:-Zpolymorphize=on
+
+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 000000000..779bac0ac
--- /dev/null
+++ b/src/test/ui/polymorphization/generators.rs
@@ -0,0 +1,92 @@
+// build-fail
+// compile-flags:-Zpolymorphize=on -Zinline-mir=off
+#![feature(generic_const_exprs, generators, generator_trait, rustc_attrs)]
+//~^ WARN the feature `generic_const_exprs` 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.
+
+#[rustc_polymorphize_error]
+pub fn unused_type<T>() -> impl Generator<(), Yield = u32, Return = u32> + Unpin {
+ || {
+ //~^ ERROR item has unused generic parameters
+ yield 1;
+ 2
+ }
+}
+
+#[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
+ yield 1;
+ 2
+ }
+}
+
+#[rustc_polymorphize_error]
+pub fn used_const_in_yield<const Y: u32>() -> impl Generator<(), Yield = u32, Return = u32> + Unpin
+{
+ || {
+ yield Y;
+ 2
+ }
+}
+
+#[rustc_polymorphize_error]
+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 000000000..a24eee5fe
--- /dev/null
+++ b/src/test/ui/polymorphization/generators.stderr
@@ -0,0 +1,39 @@
+warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/generators.rs:3:12
+ |
+LL | #![feature(generic_const_exprs, generators, generator_trait, rustc_attrs)]
+ | ^^^^^^^^^^^^^^^^^^^
+ |
+ = note: `#[warn(incomplete_features)]` on by default
+ = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> 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 | || {
+ | ^^
+
+note: the above error was encountered while instantiating `fn finish::<[generator@$DIR/generators.rs:35:5: 35:7], u32, u32>`
+ --> $DIR/generators.rs:86:5
+ |
+LL | finish(unused_type::<u32>());
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: item has unused generic parameters
+ --> $DIR/generators.rs:60:5
+ |
+LL | pub fn unused_const<const T: u32>() -> impl Generator<(), Yield = u32, Return = u32> + Unpin {
+ | ------------ generic parameter `T` is unused
+LL | || {
+ | ^^
+
+note: the above error was encountered while instantiating `fn finish::<[generator@$DIR/generators.rs:60:5: 60:7], u32, u32>`
+ --> $DIR/generators.rs:89:5
+ |
+LL | finish(unused_const::<1u32>());
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
diff --git a/src/test/ui/polymorphization/issue-74614.rs b/src/test/ui/polymorphization/issue-74614.rs
new file mode 100644
index 000000000..8b0c00b13
--- /dev/null
+++ b/src/test/ui/polymorphization/issue-74614.rs
@@ -0,0 +1,18 @@
+// compile-flags:-Zpolymorphize=on
+// build-pass
+
+fn test<T>() {
+ std::mem::size_of::<T>();
+}
+
+pub fn foo<T>(_: T) -> &'static fn() {
+ &(test::<T> as fn())
+}
+
+fn outer<T>() {
+ foo(|| ());
+}
+
+fn main() {
+ outer::<u8>();
+}
diff --git a/src/test/ui/polymorphization/issue-74636.rs b/src/test/ui/polymorphization/issue-74636.rs
new file mode 100644
index 000000000..4c532f451
--- /dev/null
+++ b/src/test/ui/polymorphization/issue-74636.rs
@@ -0,0 +1,16 @@
+// compile-flags:-Zpolymorphize=on
+// build-pass
+
+use std::any::TypeId;
+
+pub fn foo<T: 'static>(_: T) -> TypeId {
+ TypeId::of::<T>()
+}
+
+fn outer<T: 'static>() {
+ foo(|| ());
+}
+
+fn main() {
+ outer::<u8>();
+}
diff --git a/src/test/ui/polymorphization/lifetimes.rs b/src/test/ui/polymorphization/lifetimes.rs
new file mode 100644
index 000000000..f26df4523
--- /dev/null
+++ b/src/test/ui/polymorphization/lifetimes.rs
@@ -0,0 +1,25 @@
+// build-fail
+// compile-flags:-Zpolymorphize=on
+#![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
+}
+
+#[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
+ 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 000000000..4773dd4fa
--- /dev/null
+++ b/src/test/ui/polymorphization/lifetimes.stderr
@@ -0,0 +1,17 @@
+error: item has unused generic parameters
+ --> $DIR/lifetimes.rs:10:8
+ |
+LL | pub fn unused<'a, T>(_: &'a u32) {
+ | ^^^^^^ - generic parameter `T` is unused
+
+error: item has unused generic parameters
+ --> $DIR/lifetimes.rs:17: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/normalized_sig_types.rs b/src/test/ui/polymorphization/normalized_sig_types.rs
new file mode 100644
index 000000000..d732b1071
--- /dev/null
+++ b/src/test/ui/polymorphization/normalized_sig_types.rs
@@ -0,0 +1,26 @@
+// build-pass
+// compile-flags:-Zpolymorphize=on
+
+pub trait ParallelIterator: Sized {
+ fn drive<C: Consumer<()>>(_: C) {
+ C::into_folder();
+ }
+}
+
+pub trait Consumer<T>: Sized {
+ type Result;
+ fn into_folder() -> Self::Result;
+}
+
+impl ParallelIterator for () {}
+
+impl<F: Fn(), T> Consumer<T> for F {
+ type Result = ();
+ fn into_folder() -> Self::Result {
+ unimplemented!()
+ }
+}
+
+fn main() {
+ <()>::drive(|| ());
+}
diff --git a/src/test/ui/polymorphization/predicates.rs b/src/test/ui/polymorphization/predicates.rs
new file mode 100644
index 000000000..6a5fc2e33
--- /dev/null
+++ b/src/test/ui/polymorphization/predicates.rs
@@ -0,0 +1,95 @@
+// build-fail
+// compile-flags: -Copt-level=0 -Zpolymorphize=on
+
+#![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
+}
+
+#[rustc_polymorphize_error]
+fn foo<I, T>(_: I)
+//~^ ERROR item has unused generic parameters
+where
+ I: Iterator<Item = T>,
+{
+ bar::<I>()
+}
+
+#[rustc_polymorphize_error]
+fn baz<I, T>(_: I)
+//~^ ERROR item has unused generic parameters
+where
+ std::iter::Repeat<I>: Iterator<Item = T>,
+{
+ bar::<I>()
+}
+
+// In addition, check that `I` is considered used in `next::{{closure}}`, because `T` is used and
+// `T` is really just `I::Item`. `E` is used due to the fixed-point marking of predicates.
+
+pub(crate) struct Foo<'a, I, E>(I, &'a E);
+
+impl<'a, I, T: 'a, E> Iterator for Foo<'a, I, E>
+where
+ I: Iterator<Item = &'a (T, E)>,
+{
+ type Item = T;
+
+ #[rustc_polymorphize_error]
+ fn next(&mut self) -> Option<Self::Item> {
+ self.find(|_| true)
+ //~^ ERROR item has unused generic parameters
+ }
+}
+
+// Furthermore, check that `B` is considered used because `C` is used, and that `A` is considered
+// used because `B` is now used.
+
+trait Baz<Z> {}
+
+impl Baz<u16> for u8 {}
+impl Baz<u32> for u16 {}
+
+#[rustc_polymorphize_error]
+fn quux<A, B, C: Default>() -> usize
+//~^ ERROR item has unused generic parameters
+where
+ A: Baz<B>,
+ B: Baz<C>,
+{
+ std::mem::size_of::<C>()
+}
+
+// Finally, check that `F` is considered used because `G` is used when neither are in the self-ty
+// of the predicate.
+
+trait Foobar<F, G> {}
+
+impl Foobar<u32, u32> for () {}
+
+#[rustc_polymorphize_error]
+fn foobar<F, G>() -> usize
+//~^ ERROR item has unused generic parameters
+where
+ (): Foobar<F, G>,
+{
+ std::mem::size_of::<G>()
+}
+
+fn main() {
+ let x = &[2u32];
+ foo(x.iter());
+ baz(x.iter());
+
+ let mut a = Foo([(1u32, 1u16)].iter(), &1u16);
+ let _ = a.next();
+
+ let _ = quux::<u8, u16, u32>();
+
+ let _ = foobar::<u32, u32>();
+}
diff --git a/src/test/ui/polymorphization/predicates.stderr b/src/test/ui/polymorphization/predicates.stderr
new file mode 100644
index 000000000..e5af1d751
--- /dev/null
+++ b/src/test/ui/polymorphization/predicates.stderr
@@ -0,0 +1,51 @@
+error: item has unused generic parameters
+ --> $DIR/predicates.rs:15:4
+ |
+LL | fn foo<I, T>(_: I)
+ | ^^^ - generic parameter `T` is unused
+
+error: item has unused generic parameters
+ --> $DIR/predicates.rs:24:4
+ |
+LL | fn baz<I, T>(_: I)
+ | ^^^ - generic parameter `T` is unused
+
+error: item has unused generic parameters
+ --> $DIR/predicates.rs:45:19
+ |
+LL | impl<'a, I, T: 'a, E> Iterator for Foo<'a, I, E>
+ | - - generic parameter `E` is unused
+ | |
+ | generic parameter `I` is unused
+...
+LL | self.find(|_| true)
+ | ^^^
+
+error: item has unused generic parameters
+ --> $DIR/predicates.rs:59:4
+ |
+LL | fn quux<A, B, C: Default>() -> usize
+ | ^^^^ - - generic parameter `B` is unused
+ | |
+ | generic parameter `A` is unused
+
+error: item has unused generic parameters
+ --> $DIR/predicates.rs:76:4
+ |
+LL | fn foobar<F, G>() -> usize
+ | ^^^^^^ - generic parameter `F` is unused
+
+error: item has unused generic parameters
+ --> $DIR/predicates.rs:10:4
+ |
+LL | fn bar<I>() {
+ | ^^^ - generic parameter `I` is unused
+
+note: the above error was encountered while instantiating `fn foo::<std::slice::Iter<u32>, T>`
+ --> $DIR/predicates.rs:86:5
+ |
+LL | foo(x.iter());
+ | ^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
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 000000000..2cd026734
--- /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<T>() {
+ //~^ 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 000000000..fcbb86949
--- /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<T>() {
+ | ^^^^ - 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 000000000..d2d0f3368
--- /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(generic_const_exprs, rustc_attrs)]
+//~^ WARN the feature `generic_const_exprs` 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>>();
+}
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 000000000..4d7bab6aa
--- /dev/null
+++ b/src/test/ui/polymorphization/promoted-function-2.stderr
@@ -0,0 +1,17 @@
+warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/promoted-function-2.rs:4:12
+ |
+LL | #![feature(generic_const_exprs, rustc_attrs)]
+ | ^^^^^^^^^^^^^^^^^^^
+ |
+ = note: `#[warn(incomplete_features)]` on by default
+ = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> 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
+
diff --git a/src/test/ui/polymorphization/promoted-function-3.rs b/src/test/ui/polymorphization/promoted-function-3.rs
new file mode 100644
index 000000000..bbd991e36
--- /dev/null
+++ b/src/test/ui/polymorphization/promoted-function-3.rs
@@ -0,0 +1,14 @@
+// run-pass
+// compile-flags: -Zpolymorphize=on -Zmir-opt-level=4
+
+fn caller<T, U>() -> &'static usize {
+ callee::<U>()
+}
+
+fn callee<T>() -> &'static usize {
+ &std::mem::size_of::<T>()
+}
+
+fn main() {
+ assert_eq!(caller::<(), ()>(), &0);
+}
diff --git a/src/test/ui/polymorphization/promoted-function.rs b/src/test/ui/polymorphization/promoted-function.rs
new file mode 100644
index 000000000..a56a8e70e
--- /dev/null
+++ b/src/test/ui/polymorphization/promoted-function.rs
@@ -0,0 +1,15 @@
+// run-pass
+// compile-flags:-Zpolymorphize=on
+
+fn fop<T>() {}
+
+fn bar<T>() -> &'static fn() {
+ &(fop::<T> as fn())
+}
+pub const FN: &'static fn() = &(fop::<i32> as fn());
+
+fn main() {
+ bar::<u32>();
+ bar::<i32>();
+ (FN)();
+}
diff --git a/src/test/ui/polymorphization/symbol-ambiguity.rs b/src/test/ui/polymorphization/symbol-ambiguity.rs
new file mode 100644
index 000000000..6277a902f
--- /dev/null
+++ b/src/test/ui/polymorphization/symbol-ambiguity.rs
@@ -0,0 +1,22 @@
+// build-pass
+// compile-flags: -Zpolymorphize=on -Csymbol-mangling-version=v0
+
+pub(crate) struct Foo<'a, I, E>(I, &'a E);
+
+impl<'a, I, T: 'a, E> Iterator for Foo<'a, I, E>
+where
+ I: Iterator<Item = &'a (T, E)>,
+{
+ type Item = T;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.find(|_| true)
+ }
+}
+
+fn main() {
+ let mut a = Foo([(1u32, 1u16)].iter(), &1u16);
+ let mut b = Foo([(1u16, 1u32)].iter(), &1u32);
+ let _ = a.next();
+ let _ = b.next();
+}
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 000000000..ec6244630
--- /dev/null
+++ b/src/test/ui/polymorphization/too-many-generic-params.rs
@@ -0,0 +1,85 @@
+// build-pass
+#![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, BM>()
+{
+ 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<AZ> = 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;
+ let _: Option<BM> = None;
+}
+
+fn main() {
+ bar::<u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32,
+ u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32,
+ u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32,
+ u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32,
+ u32>();
+}
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 000000000..07ab1355a
--- /dev/null
+++ b/src/test/ui/polymorphization/type_parameters/closures.rs
@@ -0,0 +1,161 @@
+// build-fail
+// compile-flags:-Zpolymorphize=on
+#![feature(stmt_expr_attributes, rustc_attrs)]
+
+// This test checks that the polymorphization analysis correctly detects unused type
+// 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<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.
+#[rustc_polymorphize_error]
+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.
+#[rustc_polymorphize_error]
+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.
+#[rustc_polymorphize_error]
+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.
+#[rustc_polymorphize_error]
+pub fn used_argument<T>(t: T) -> u32 {
+ let x = |_: T| 3;
+ x(t)
+}
+
+// Closure uses generic parameter in argument.
+#[rustc_polymorphize_error]
+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.
+#[rustc_polymorphize_error]
+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.
+#[rustc_polymorphize_error]
+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.
+ #[rustc_polymorphize_error]
+ 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.
+ #[rustc_polymorphize_error]
+ 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.
+ #[rustc_polymorphize_error]
+ 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.
+ #[rustc_polymorphize_error]
+ 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.
+ #[rustc_polymorphize_error]
+ 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 000000000..94a4a08bd
--- /dev/null
+++ b/src/test/ui/polymorphization/type_parameters/closures.stderr
@@ -0,0 +1,80 @@
+error: item has unused generic parameters
+ --> $DIR/closures.rs:19:19
+ |
+LL | pub fn unused<T>() -> u32 {
+ | - generic parameter `T` is unused
+...
+LL | let add_one = |x: u32| x + 1;
+ | ^^^^^^^^
+
+error: item has unused generic parameters
+ --> $DIR/closures.rs:16:8
+ |
+LL | pub fn unused<T>() -> u32 {
+ | ^^^^^^ - generic parameter `T` is unused
+
+error: item has unused generic parameters
+ --> $DIR/closures.rs:28: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:94:23
+ |
+LL | impl<F: Default> Foo<F> {
+ | - generic parameter `F` is unused
+...
+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:92:12
+ |
+LL | impl<F: Default> Foo<F> {
+ | - generic parameter `F` is unused
+...
+LL | pub fn unused_all<G: Default>() -> u32 {
+ | ^^^^^^^^^^ - generic parameter `G` is unused
+
+error: item has unused generic parameters
+ --> $DIR/closures.rs:128:23
+ |
+LL | pub fn used_impl<G: Default>() -> u32 {
+ | - generic parameter `G` is unused
+LL |
+LL | let add_one = |x: u32| {
+ | ^^^^^^^^
+
+error: item has unused generic parameters
+ --> $DIR/closures.rs:126:12
+ |
+LL | pub fn used_impl<G: Default>() -> u32 {
+ | ^^^^^^^^^ - generic parameter `G` is unused
+
+error: item has unused generic parameters
+ --> $DIR/closures.rs:115:23
+ |
+LL | impl<F: Default> Foo<F> {
+ | - generic parameter `F` is unused
+...
+LL | let add_one = |x: u32| {
+ | ^^^^^^^^
+
+error: item has unused generic parameters
+ --> $DIR/closures.rs:113: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 000000000..aad957e1d
--- /dev/null
+++ b/src/test/ui/polymorphization/type_parameters/functions.rs
@@ -0,0 +1,96 @@
+// build-fail
+// compile-flags:-Zpolymorphize=on
+#![feature(rustc_attrs)]
+
+// This test checks that the polymorphization analysis correctly detects unused type
+// 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<T>() {
+ //~^ ERROR item has unused generic parameters
+}
+
+// Function uses generic parameter in value of a binding.
+#[rustc_polymorphize_error]
+pub fn used_binding_value<T: Default>() {
+ let _: T = Default::default();
+}
+
+// Function uses generic parameter in generic of a binding.
+#[rustc_polymorphize_error]
+pub fn used_binding_generic<T>() {
+ let _: Option<T> = None;
+}
+
+// Function uses generic parameter in argument.
+#[rustc_polymorphize_error]
+pub fn used_argument<T>(_: T) {}
+
+// Function uses generic parameter in substitutions to another function.
+#[rustc_polymorphize_error]
+pub fn used_substs<T>() {
+ unused::<T>()
+}
+
+struct Foo<F>(F);
+
+impl<F: Default> Foo<F> {
+ // Function has an unused generic parameter from impl.
+ #[rustc_polymorphize_error]
+ pub fn unused_impl() {
+ //~^ ERROR item has unused generic parameters
+ }
+
+ // Function has an unused generic parameter from impl and fn.
+ #[rustc_polymorphize_error]
+ pub fn unused_both<G: Default>() {
+ //~^ ERROR item has unused generic parameters
+ }
+
+ // Function uses generic parameter from impl.
+ #[rustc_polymorphize_error]
+ pub fn used_impl() {
+ let _: F = Default::default();
+ }
+
+ // Function uses generic parameter from impl.
+ #[rustc_polymorphize_error]
+ pub fn used_fn<G: Default>() {
+ //~^ ERROR item has unused generic parameters
+ let _: G = Default::default();
+ }
+
+ // Function uses generic parameter from impl.
+ #[rustc_polymorphize_error]
+ pub fn used_both<G: Default>() {
+ let _: F = Default::default();
+ let _: G = Default::default();
+ }
+
+ // Function uses generic parameter in substitutions to another function.
+ #[rustc_polymorphize_error]
+ 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 000000000..d629ff7bb
--- /dev/null
+++ b/src/test/ui/polymorphization/type_parameters/functions.stderr
@@ -0,0 +1,35 @@
+error: item has unused generic parameters
+ --> $DIR/functions.rs:14:8
+ |
+LL | pub fn unused<T>() {
+ | ^^^^^^ - generic parameter `T` is unused
+
+error: item has unused generic parameters
+ --> $DIR/functions.rs:45:12
+ |
+LL | impl<F: Default> Foo<F> {
+ | - generic parameter `F` is unused
+...
+LL | pub fn unused_impl() {
+ | ^^^^^^^^^^^
+
+error: item has unused generic parameters
+ --> $DIR/functions.rs:51: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:63: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 000000000..b803fec2c
--- /dev/null
+++ b/src/test/ui/polymorphization/unsized_cast.rs
@@ -0,0 +1,30 @@
+// build-fail
+// compile-flags:-Zpolymorphize=on
+#![feature(fn_traits, rustc_attrs, unboxed_closures)]
+
+// This test checks that the polymorphization analysis considers a closure
+// as using all generic parameters if it does an unsizing cast.
+
+#[rustc_polymorphize_error]
+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
+}
+
+#[rustc_polymorphize_error]
+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
+ })();
+}
+
+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 000000000..27f88d281
--- /dev/null
+++ b/src/test/ui/polymorphization/unsized_cast.stderr
@@ -0,0 +1,38 @@
+error: item has unused generic parameters
+ --> $DIR/unsized_cast.rs:11: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:11:6
+ |
+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:22:15
+ |
+LL | fn foo2<T: Default>() {
+ | - generic parameter `T` is unused
+...
+LL | call(&|| {}, ());
+ | ^^
+
+error: item has unused generic parameters
+ --> $DIR/unsized_cast.rs:19:6
+ |
+LL | fn foo2<T: Default>() {
+ | - generic parameter `T` is unused
+LL | let _: T = Default::default();
+LL | (|| {
+ | ^^
+
+error: aborting due to 4 previous errors
+