summaryrefslogtreecommitdiffstats
path: root/tests/ui/lint/unused
diff options
context:
space:
mode:
Diffstat (limited to 'tests/ui/lint/unused')
-rw-r--r--tests/ui/lint/unused/auxiliary/lint_unused_extern_crate.rs1
-rw-r--r--tests/ui/lint/unused/auxiliary/lint_unused_extern_crate2.rs1
-rw-r--r--tests/ui/lint/unused/auxiliary/lint_unused_extern_crate3.rs1
-rw-r--r--tests/ui/lint/unused/auxiliary/lint_unused_extern_crate4.rs1
-rw-r--r--tests/ui/lint/unused/auxiliary/lint_unused_extern_crate5.rs1
-rw-r--r--tests/ui/lint/unused/issue-104397.rs18
-rw-r--r--tests/ui/lint/unused/issue-105061-array-lint.rs11
-rw-r--r--tests/ui/lint/unused/issue-105061-array-lint.stderr56
-rw-r--r--tests/ui/lint/unused/issue-105061-should-lint.rs23
-rw-r--r--tests/ui/lint/unused/issue-105061-should-lint.stderr32
-rw-r--r--tests/ui/lint/unused/issue-105061.rs17
-rw-r--r--tests/ui/lint/unused/issue-105061.stderr20
-rw-r--r--tests/ui/lint/unused/issue-30730.rs5
-rw-r--r--tests/ui/lint/unused/issue-30730.stderr15
-rw-r--r--tests/ui/lint/unused/issue-46576.rs21
-rw-r--r--tests/ui/lint/unused/issue-46576.stderr14
-rw-r--r--tests/ui/lint/unused/issue-47390-unused-variable-in-struct-pattern.rs88
-rw-r--r--tests/ui/lint/unused/issue-47390-unused-variable-in-struct-pattern.stderr116
-rw-r--r--tests/ui/lint/unused/issue-54180-unused-ref-field.fixed34
-rw-r--r--tests/ui/lint/unused/issue-54180-unused-ref-field.rs34
-rw-r--r--tests/ui/lint/unused/issue-54180-unused-ref-field.stderr33
-rw-r--r--tests/ui/lint/unused/issue-54538-unused-parens-lint.fixed113
-rw-r--r--tests/ui/lint/unused/issue-54538-unused-parens-lint.rs113
-rw-r--r--tests/ui/lint/unused/issue-54538-unused-parens-lint.stderr295
-rw-r--r--tests/ui/lint/unused/issue-59896.rs9
-rw-r--r--tests/ui/lint/unused/issue-59896.stderr17
-rw-r--r--tests/ui/lint/unused/issue-67691-unused-field-in-or-pattern.rs85
-rw-r--r--tests/ui/lint/unused/issue-67691-unused-field-in-or-pattern.stderr74
-rw-r--r--tests/ui/lint/unused/issue-70041.rs13
-rw-r--r--tests/ui/lint/unused/issue-70041.stderr18
-rw-r--r--tests/ui/lint/unused/issue-71290-unused-paren-binop.rs23
-rw-r--r--tests/ui/lint/unused/issue-74883-unused-paren-baren-yield.rs26
-rw-r--r--tests/ui/lint/unused/issue-74883-unused-paren-baren-yield.stderr84
-rw-r--r--tests/ui/lint/unused/issue-81314-unused-span-ident.fixed12
-rw-r--r--tests/ui/lint/unused/issue-81314-unused-span-ident.rs12
-rw-r--r--tests/ui/lint/unused/issue-81314-unused-span-ident.stderr21
-rw-r--r--tests/ui/lint/unused/issue-85913.rs13
-rw-r--r--tests/ui/lint/unused/issue-85913.stderr18
-rw-r--r--tests/ui/lint/unused/issue-88519-unused-paren.rs85
-rw-r--r--tests/ui/lint/unused/issue-90807-unused-paren-error.rs9
-rw-r--r--tests/ui/lint/unused/issue-90807-unused-paren-error.stderr31
-rw-r--r--tests/ui/lint/unused/issue-90807-unused-paren.rs8
-rw-r--r--tests/ui/lint/unused/issue-92751.rs9
-rw-r--r--tests/ui/lint/unused/issue-92751.stderr32
-rw-r--r--tests/ui/lint/unused/lint-unused-extern-crate.rs35
-rw-r--r--tests/ui/lint/unused/lint-unused-extern-crate.stderr20
-rw-r--r--tests/ui/lint/unused/lint-unused-imports.rs90
-rw-r--r--tests/ui/lint/unused/lint-unused-imports.stderr78
-rw-r--r--tests/ui/lint/unused/lint-unused-mut-self.fixed14
-rw-r--r--tests/ui/lint/unused/lint-unused-mut-self.rs14
-rw-r--r--tests/ui/lint/unused/lint-unused-mut-self.stderr24
-rw-r--r--tests/ui/lint/unused/lint-unused-mut-variables.rs207
-rw-r--r--tests/ui/lint/unused/lint-unused-mut-variables.stderr222
-rw-r--r--tests/ui/lint/unused/lint-unused-variables.rs79
-rw-r--r--tests/ui/lint/unused/lint-unused-variables.stderr74
-rw-r--r--tests/ui/lint/unused/must-use-box-from-raw.rs11
-rw-r--r--tests/ui/lint/unused/must-use-box-from-raw.stderr15
-rw-r--r--tests/ui/lint/unused/must-use-ops.rs51
-rw-r--r--tests/ui/lint/unused/must-use-ops.stderr238
-rw-r--r--tests/ui/lint/unused/must_use-array.rs54
-rw-r--r--tests/ui/lint/unused/must_use-array.stderr50
-rw-r--r--tests/ui/lint/unused/must_use-in-stdlib-traits.rs47
-rw-r--r--tests/ui/lint/unused/must_use-in-stdlib-traits.stderr47
-rw-r--r--tests/ui/lint/unused/must_use-trait.rs39
-rw-r--r--tests/ui/lint/unused/must_use-trait.stderr38
-rw-r--r--tests/ui/lint/unused/must_use-tuple.rs17
-rw-r--r--tests/ui/lint/unused/must_use-tuple.stderr47
-rw-r--r--tests/ui/lint/unused/must_use-unit.rs16
-rw-r--r--tests/ui/lint/unused/must_use-unit.stderr20
-rw-r--r--tests/ui/lint/unused/no-unused-parens-return-block.rs9
-rw-r--r--tests/ui/lint/unused/unused-async.rs62
-rw-r--r--tests/ui/lint/unused/unused-async.stderr55
-rw-r--r--tests/ui/lint/unused/unused-attr-duplicate.rs105
-rw-r--r--tests/ui/lint/unused/unused-attr-duplicate.stderr293
-rw-r--r--tests/ui/lint/unused/unused-attr-macro-rules.rs33
-rw-r--r--tests/ui/lint/unused/unused-attr-macro-rules.stderr26
-rw-r--r--tests/ui/lint/unused/unused-closure.rs35
-rw-r--r--tests/ui/lint/unused/unused-closure.stderr65
-rw-r--r--tests/ui/lint/unused/unused-doc-comments-edge-cases.rs46
-rw-r--r--tests/ui/lint/unused/unused-doc-comments-edge-cases.stderr95
-rw-r--r--tests/ui/lint/unused/unused-doc-comments-for-macros.rs17
-rw-r--r--tests/ui/lint/unused/unused-doc-comments-for-macros.stderr31
-rw-r--r--tests/ui/lint/unused/unused-macro-rules-compile-error.rs27
-rw-r--r--tests/ui/lint/unused/unused-macro-rules-compile-error.stderr26
-rw-r--r--tests/ui/lint/unused/unused-macro-rules-decl.rs49
-rw-r--r--tests/ui/lint/unused/unused-macro-rules-decl.stderr26
-rw-r--r--tests/ui/lint/unused/unused-macro-rules-malformed-rule.rs11
-rw-r--r--tests/ui/lint/unused/unused-macro-rules-malformed-rule.stderr8
-rw-r--r--tests/ui/lint/unused/unused-macro-rules.rs47
-rw-r--r--tests/ui/lint/unused/unused-macro-rules.stderr26
-rw-r--r--tests/ui/lint/unused/unused-macro-with-bad-frag-spec.rs9
-rw-r--r--tests/ui/lint/unused/unused-macro-with-bad-frag-spec.stderr10
-rw-r--r--tests/ui/lint/unused/unused-macro-with-follow-violation.rs7
-rw-r--r--tests/ui/lint/unused/unused-macro-with-follow-violation.stderr10
-rw-r--r--tests/ui/lint/unused/unused-macros-decl.rs28
-rw-r--r--tests/ui/lint/unused/unused-macros-decl.stderr32
-rw-r--r--tests/ui/lint/unused/unused-macros-malformed-rule.rs15
-rw-r--r--tests/ui/lint/unused/unused-macros-malformed-rule.stderr26
-rw-r--r--tests/ui/lint/unused/unused-macros.rs31
-rw-r--r--tests/ui/lint/unused/unused-macros.stderr32
-rw-r--r--tests/ui/lint/unused/unused-mut-warning-captured-var.fixed9
-rw-r--r--tests/ui/lint/unused/unused-mut-warning-captured-var.rs9
-rw-r--r--tests/ui/lint/unused/unused-mut-warning-captured-var.stderr16
-rw-r--r--tests/ui/lint/unused/unused-result.rs42
-rw-r--r--tests/ui/lint/unused/unused-result.stderr48
-rw-r--r--tests/ui/lint/unused/unused-supertrait.rs11
-rw-r--r--tests/ui/lint/unused/unused-supertrait.stderr15
-rw-r--r--tests/ui/lint/unused/unused_attributes-must_use.rs131
-rw-r--r--tests/ui/lint/unused/unused_attributes-must_use.stderr187
-rw-r--r--tests/ui/lint/unused/useless-comment.rs45
-rw-r--r--tests/ui/lint/unused/useless-comment.stderr110
111 files changed, 5124 insertions, 0 deletions
diff --git a/tests/ui/lint/unused/auxiliary/lint_unused_extern_crate.rs b/tests/ui/lint/unused/auxiliary/lint_unused_extern_crate.rs
new file mode 100644
index 000000000..b76b4321d
--- /dev/null
+++ b/tests/ui/lint/unused/auxiliary/lint_unused_extern_crate.rs
@@ -0,0 +1 @@
+pub fn foo() {}
diff --git a/tests/ui/lint/unused/auxiliary/lint_unused_extern_crate2.rs b/tests/ui/lint/unused/auxiliary/lint_unused_extern_crate2.rs
new file mode 100644
index 000000000..b76b4321d
--- /dev/null
+++ b/tests/ui/lint/unused/auxiliary/lint_unused_extern_crate2.rs
@@ -0,0 +1 @@
+pub fn foo() {}
diff --git a/tests/ui/lint/unused/auxiliary/lint_unused_extern_crate3.rs b/tests/ui/lint/unused/auxiliary/lint_unused_extern_crate3.rs
new file mode 100644
index 000000000..b76b4321d
--- /dev/null
+++ b/tests/ui/lint/unused/auxiliary/lint_unused_extern_crate3.rs
@@ -0,0 +1 @@
+pub fn foo() {}
diff --git a/tests/ui/lint/unused/auxiliary/lint_unused_extern_crate4.rs b/tests/ui/lint/unused/auxiliary/lint_unused_extern_crate4.rs
new file mode 100644
index 000000000..d11c69f81
--- /dev/null
+++ b/tests/ui/lint/unused/auxiliary/lint_unused_extern_crate4.rs
@@ -0,0 +1 @@
+// intentionally empty
diff --git a/tests/ui/lint/unused/auxiliary/lint_unused_extern_crate5.rs b/tests/ui/lint/unused/auxiliary/lint_unused_extern_crate5.rs
new file mode 100644
index 000000000..d11c69f81
--- /dev/null
+++ b/tests/ui/lint/unused/auxiliary/lint_unused_extern_crate5.rs
@@ -0,0 +1 @@
+// intentionally empty
diff --git a/tests/ui/lint/unused/issue-104397.rs b/tests/ui/lint/unused/issue-104397.rs
new file mode 100644
index 000000000..94e15cd96
--- /dev/null
+++ b/tests/ui/lint/unused/issue-104397.rs
@@ -0,0 +1,18 @@
+// check-pass
+
+#![warn(unused)]
+#![deny(warnings)]
+
+struct Inv<'a>(&'a mut &'a ());
+
+trait Trait {}
+impl Trait for for<'a> fn(Inv<'a>) {}
+
+fn with_bound()
+where
+ (for<'a> fn(Inv<'a>)): Trait,
+{}
+
+fn main() {
+ with_bound();
+}
diff --git a/tests/ui/lint/unused/issue-105061-array-lint.rs b/tests/ui/lint/unused/issue-105061-array-lint.rs
new file mode 100644
index 000000000..9b06a4fde
--- /dev/null
+++ b/tests/ui/lint/unused/issue-105061-array-lint.rs
@@ -0,0 +1,11 @@
+#![warn(unused)]
+#![deny(warnings)]
+
+fn main() {
+ let _x: ([u32; 3]); //~ ERROR unnecessary parentheses around type
+ let _y: [u8; (3)]; //~ ERROR unnecessary parentheses around const expression
+ let _z: ([u8; (3)]);
+ //~^ ERROR unnecessary parentheses around const expression
+ //~| ERROR unnecessary parentheses around type
+
+}
diff --git a/tests/ui/lint/unused/issue-105061-array-lint.stderr b/tests/ui/lint/unused/issue-105061-array-lint.stderr
new file mode 100644
index 000000000..7eb761aee
--- /dev/null
+++ b/tests/ui/lint/unused/issue-105061-array-lint.stderr
@@ -0,0 +1,56 @@
+error: unnecessary parentheses around type
+ --> $DIR/issue-105061-array-lint.rs:5:13
+ |
+LL | let _x: ([u32; 3]);
+ | ^ ^
+ |
+note: the lint level is defined here
+ --> $DIR/issue-105061-array-lint.rs:2:9
+ |
+LL | #![deny(warnings)]
+ | ^^^^^^^^
+ = note: `#[deny(unused_parens)]` implied by `#[deny(warnings)]`
+help: remove these parentheses
+ |
+LL - let _x: ([u32; 3]);
+LL + let _x: [u32; 3];
+ |
+
+error: unnecessary parentheses around const expression
+ --> $DIR/issue-105061-array-lint.rs:6:18
+ |
+LL | let _y: [u8; (3)];
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - let _y: [u8; (3)];
+LL + let _y: [u8; 3];
+ |
+
+error: unnecessary parentheses around type
+ --> $DIR/issue-105061-array-lint.rs:7:13
+ |
+LL | let _z: ([u8; (3)]);
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - let _z: ([u8; (3)]);
+LL + let _z: [u8; (3)];
+ |
+
+error: unnecessary parentheses around const expression
+ --> $DIR/issue-105061-array-lint.rs:7:19
+ |
+LL | let _z: ([u8; (3)]);
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - let _z: ([u8; (3)]);
+LL + let _z: ([u8; 3]);
+ |
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/lint/unused/issue-105061-should-lint.rs b/tests/ui/lint/unused/issue-105061-should-lint.rs
new file mode 100644
index 000000000..7e4e09473
--- /dev/null
+++ b/tests/ui/lint/unused/issue-105061-should-lint.rs
@@ -0,0 +1,23 @@
+#![warn(unused)]
+#![deny(warnings)]
+
+struct Inv<'a>(&'a mut &'a ());
+
+trait Trait<'a> {}
+impl<'b> Trait<'b> for for<'a> fn(Inv<'a>) {}
+
+fn with_bound()
+where
+ for<'b> (for<'a> fn(Inv<'a>)): Trait<'b>, //~ ERROR unnecessary parentheses around type
+{}
+
+trait Hello<T> {}
+fn with_dyn_bound<T>()
+where
+ (dyn Hello<(for<'b> fn(&'b ()))>): Hello<T> //~ ERROR unnecessary parentheses around type
+{}
+
+fn main() {
+ with_bound();
+ with_dyn_bound();
+}
diff --git a/tests/ui/lint/unused/issue-105061-should-lint.stderr b/tests/ui/lint/unused/issue-105061-should-lint.stderr
new file mode 100644
index 000000000..e591f1ffb
--- /dev/null
+++ b/tests/ui/lint/unused/issue-105061-should-lint.stderr
@@ -0,0 +1,32 @@
+error: unnecessary parentheses around type
+ --> $DIR/issue-105061-should-lint.rs:11:13
+ |
+LL | for<'b> (for<'a> fn(Inv<'a>)): Trait<'b>,
+ | ^ ^
+ |
+note: the lint level is defined here
+ --> $DIR/issue-105061-should-lint.rs:2:9
+ |
+LL | #![deny(warnings)]
+ | ^^^^^^^^
+ = note: `#[deny(unused_parens)]` implied by `#[deny(warnings)]`
+help: remove these parentheses
+ |
+LL - for<'b> (for<'a> fn(Inv<'a>)): Trait<'b>,
+LL + for<'b> for<'a> fn(Inv<'a>): Trait<'b>,
+ |
+
+error: unnecessary parentheses around type
+ --> $DIR/issue-105061-should-lint.rs:17:16
+ |
+LL | (dyn Hello<(for<'b> fn(&'b ()))>): Hello<T>
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - (dyn Hello<(for<'b> fn(&'b ()))>): Hello<T>
+LL + (dyn Hello<for<'b> fn(&'b ())>): Hello<T>
+ |
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/lint/unused/issue-105061.rs b/tests/ui/lint/unused/issue-105061.rs
new file mode 100644
index 000000000..92d636d0a
--- /dev/null
+++ b/tests/ui/lint/unused/issue-105061.rs
@@ -0,0 +1,17 @@
+#![warn(unused)]
+#![deny(warnings)]
+
+struct Inv<'a>(&'a mut &'a ());
+
+trait Trait {}
+impl Trait for (for<'a> fn(Inv<'a>),) {}
+
+
+fn with_bound()
+where
+ ((for<'a> fn(Inv<'a>)),): Trait, //~ ERROR unnecessary parentheses around type
+{}
+
+fn main() {
+ with_bound();
+}
diff --git a/tests/ui/lint/unused/issue-105061.stderr b/tests/ui/lint/unused/issue-105061.stderr
new file mode 100644
index 000000000..f07aa2012
--- /dev/null
+++ b/tests/ui/lint/unused/issue-105061.stderr
@@ -0,0 +1,20 @@
+error: unnecessary parentheses around type
+ --> $DIR/issue-105061.rs:12:6
+ |
+LL | ((for<'a> fn(Inv<'a>)),): Trait,
+ | ^ ^
+ |
+note: the lint level is defined here
+ --> $DIR/issue-105061.rs:2:9
+ |
+LL | #![deny(warnings)]
+ | ^^^^^^^^
+ = note: `#[deny(unused_parens)]` implied by `#[deny(warnings)]`
+help: remove these parentheses
+ |
+LL - ((for<'a> fn(Inv<'a>)),): Trait,
+LL + (for<'a> fn(Inv<'a>),): Trait,
+ |
+
+error: aborting due to previous error
+
diff --git a/tests/ui/lint/unused/issue-30730.rs b/tests/ui/lint/unused/issue-30730.rs
new file mode 100644
index 000000000..d6be90c81
--- /dev/null
+++ b/tests/ui/lint/unused/issue-30730.rs
@@ -0,0 +1,5 @@
+#![warn(unused)]
+#![deny(warnings)]
+use std::thread;
+//~^ ERROR: unused import
+fn main() {}
diff --git a/tests/ui/lint/unused/issue-30730.stderr b/tests/ui/lint/unused/issue-30730.stderr
new file mode 100644
index 000000000..b299e99a3
--- /dev/null
+++ b/tests/ui/lint/unused/issue-30730.stderr
@@ -0,0 +1,15 @@
+error: unused import: `std::thread`
+ --> $DIR/issue-30730.rs:3:5
+ |
+LL | use std::thread;
+ | ^^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/issue-30730.rs:2:9
+ |
+LL | #![deny(warnings)]
+ | ^^^^^^^^
+ = note: `#[deny(unused_imports)]` implied by `#[deny(warnings)]`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/lint/unused/issue-46576.rs b/tests/ui/lint/unused/issue-46576.rs
new file mode 100644
index 000000000..15f458f38
--- /dev/null
+++ b/tests/ui/lint/unused/issue-46576.rs
@@ -0,0 +1,21 @@
+#![allow(dead_code)]
+#![deny(unused_imports)]
+
+use std::fs::File;
+use std::io::{BufRead, BufReader, Read};
+//~^ ERROR unused import: `BufRead`
+
+pub fn read_from_file(path: &str) {
+ let file = File::open(&path).unwrap();
+ let mut reader = BufReader::new(file);
+ let mut s = String::new();
+ reader.read_to_string(&mut s).unwrap();
+}
+
+pub fn read_lines(s: &str) {
+ for _line in s.lines() {
+
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/lint/unused/issue-46576.stderr b/tests/ui/lint/unused/issue-46576.stderr
new file mode 100644
index 000000000..6f4d97068
--- /dev/null
+++ b/tests/ui/lint/unused/issue-46576.stderr
@@ -0,0 +1,14 @@
+error: unused import: `BufRead`
+ --> $DIR/issue-46576.rs:5:15
+ |
+LL | use std::io::{BufRead, BufReader, Read};
+ | ^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/issue-46576.rs:2:9
+ |
+LL | #![deny(unused_imports)]
+ | ^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/lint/unused/issue-47390-unused-variable-in-struct-pattern.rs b/tests/ui/lint/unused/issue-47390-unused-variable-in-struct-pattern.rs
new file mode 100644
index 000000000..4822a9b2c
--- /dev/null
+++ b/tests/ui/lint/unused/issue-47390-unused-variable-in-struct-pattern.rs
@@ -0,0 +1,88 @@
+// check-pass
+
+#![feature(box_patterns)]
+
+#![warn(unused)] // UI tests pass `-A unused` (#43896)
+
+struct SoulHistory {
+ corridors_of_light: usize,
+ hours_are_suns: bool,
+ endless_and_singing: bool
+}
+
+struct LovelyAmbition {
+ lips: usize,
+ fire: usize
+}
+
+#[derive(Clone, Copy)]
+enum Large {
+ Suit { case: () }
+}
+
+struct Tuple(Large, ());
+
+fn main() {
+ let i_think_continually = 2; //~ WARNING unused variable: `i_think_continually`
+ let who_from_the_womb_remembered = SoulHistory {
+ corridors_of_light: 5,
+ hours_are_suns: true,
+ endless_and_singing: true
+ };
+
+ let mut mut_unused_var = 1;
+ //~^ WARNING unused variable: `mut_unused_var`
+ //~| WARNING variable does not need to be mutable
+
+ let (mut var, unused_var) = (1, 2);
+ //~^ WARNING unused variable: `var`
+ //~| WARNING unused variable: `unused_var`
+ //~| WARNING variable does not need to be mutable
+ // NOTE: `var` comes after `unused_var` lexicographically yet the warning
+ // for `var` will be emitted before the one for `unused_var`. We use an
+ // `IndexMap` to ensure this is the case instead of a `BTreeMap`.
+
+ if let SoulHistory { corridors_of_light, //~ WARNING unused variable: `corridors_of_light`
+ mut hours_are_suns, //~ WARNING `hours_are_suns` is assigned to, but
+ endless_and_singing: true } = who_from_the_womb_remembered {
+ hours_are_suns = false; //~ WARNING unused_assignments
+ }
+
+ let the_spirit = LovelyAmbition { lips: 1, fire: 2 };
+ let LovelyAmbition { lips, fire } = the_spirit; //~ WARNING unused variable: `fire`
+ println!("{}", lips);
+
+ let bag = Large::Suit {
+ case: ()
+ };
+
+ // Plain struct
+ match bag {
+ Large::Suit { case } => {} //~ WARNING unused variable: `case`
+ };
+
+ // Referenced struct
+ match &bag {
+ &Large::Suit { case } => {} //~ WARNING unused variable: `case`
+ };
+
+ // Boxed struct
+ match Box::new(bag) {
+ box Large::Suit { case } => {} //~ WARNING unused variable: `case`
+ };
+
+ // Tuple with struct
+ match (bag,) {
+ (Large::Suit { case },) => {} //~ WARNING unused variable: `case`
+ };
+
+ // Slice with struct
+ match [bag] {
+ [Large::Suit { case }] => {} //~ WARNING unused variable: `case`
+ };
+
+ // Tuple struct with struct
+ match Tuple(bag, ()) {
+ Tuple(Large::Suit { case }, ()) => {} //~ WARNING unused variable: `case`
+ };
+}
diff --git a/tests/ui/lint/unused/issue-47390-unused-variable-in-struct-pattern.stderr b/tests/ui/lint/unused/issue-47390-unused-variable-in-struct-pattern.stderr
new file mode 100644
index 000000000..fe2e3afc8
--- /dev/null
+++ b/tests/ui/lint/unused/issue-47390-unused-variable-in-struct-pattern.stderr
@@ -0,0 +1,116 @@
+warning: unused variable: `i_think_continually`
+ --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:26:9
+ |
+LL | let i_think_continually = 2;
+ | ^^^^^^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_i_think_continually`
+ |
+note: the lint level is defined here
+ --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:5:9
+ |
+LL | #![warn(unused)] // UI tests pass `-A unused` (#43896)
+ | ^^^^^^
+ = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]`
+
+warning: unused variable: `mut_unused_var`
+ --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:33:13
+ |
+LL | let mut mut_unused_var = 1;
+ | ^^^^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_mut_unused_var`
+
+warning: unused variable: `var`
+ --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:37:14
+ |
+LL | let (mut var, unused_var) = (1, 2);
+ | ^^^ help: if this is intentional, prefix it with an underscore: `_var`
+
+warning: unused variable: `unused_var`
+ --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:37:19
+ |
+LL | let (mut var, unused_var) = (1, 2);
+ | ^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused_var`
+
+warning: unused variable: `corridors_of_light`
+ --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:45:26
+ |
+LL | if let SoulHistory { corridors_of_light,
+ | ^^^^^^^^^^^^^^^^^^ help: try ignoring the field: `corridors_of_light: _`
+
+warning: variable `hours_are_suns` is assigned to, but never used
+ --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:46:30
+ |
+LL | mut hours_are_suns,
+ | ^^^^^^^^^^^^^^
+ |
+ = note: consider using `_hours_are_suns` instead
+
+warning: value assigned to `hours_are_suns` is never read
+ --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:48:9
+ |
+LL | hours_are_suns = false;
+ | ^^^^^^^^^^^^^^
+ |
+ = help: maybe it is overwritten before being read?
+ = note: `#[warn(unused_assignments)]` implied by `#[warn(unused)]`
+
+warning: unused variable: `fire`
+ --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:52:32
+ |
+LL | let LovelyAmbition { lips, fire } = the_spirit;
+ | ^^^^ help: try ignoring the field: `fire: _`
+
+warning: unused variable: `case`
+ --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:61:23
+ |
+LL | Large::Suit { case } => {}
+ | ^^^^ help: try ignoring the field: `case: _`
+
+warning: unused variable: `case`
+ --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:66:24
+ |
+LL | &Large::Suit { case } => {}
+ | ^^^^ help: try ignoring the field: `case: _`
+
+warning: unused variable: `case`
+ --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:71:27
+ |
+LL | box Large::Suit { case } => {}
+ | ^^^^ help: try ignoring the field: `case: _`
+
+warning: unused variable: `case`
+ --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:76:24
+ |
+LL | (Large::Suit { case },) => {}
+ | ^^^^ help: try ignoring the field: `case: _`
+
+warning: unused variable: `case`
+ --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:81:24
+ |
+LL | [Large::Suit { case }] => {}
+ | ^^^^ help: try ignoring the field: `case: _`
+
+warning: unused variable: `case`
+ --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:86:29
+ |
+LL | Tuple(Large::Suit { case }, ()) => {}
+ | ^^^^ help: try ignoring the field: `case: _`
+
+warning: variable does not need to be mutable
+ --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:33:9
+ |
+LL | let mut mut_unused_var = 1;
+ | ----^^^^^^^^^^^^^^
+ | |
+ | help: remove this `mut`
+ |
+ = note: `#[warn(unused_mut)]` implied by `#[warn(unused)]`
+
+warning: variable does not need to be mutable
+ --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:37:10
+ |
+LL | let (mut var, unused_var) = (1, 2);
+ | ----^^^
+ | |
+ | help: remove this `mut`
+
+warning: 16 warnings emitted
+
diff --git a/tests/ui/lint/unused/issue-54180-unused-ref-field.fixed b/tests/ui/lint/unused/issue-54180-unused-ref-field.fixed
new file mode 100644
index 000000000..1350b7ca6
--- /dev/null
+++ b/tests/ui/lint/unused/issue-54180-unused-ref-field.fixed
@@ -0,0 +1,34 @@
+// run-rustfix
+
+#![deny(unused)]
+
+pub struct S {
+ pub f1: i32,
+}
+
+pub struct Point {
+ pub x: i32,
+ pub y: i32,
+}
+
+pub enum E {
+ Variant { field: String }
+}
+
+pub fn foo(arg: &E) {
+ match arg {
+ E::Variant { field: _ } => (), //~ ERROR unused variable
+ }
+}
+
+fn main() {
+ let s = S { f1: 123 };
+ let S { f1: _ } = s; //~ ERROR unused variable
+
+ let points = vec![Point { x: 1, y: 2 }];
+ let _: i32 = points.iter().map(|Point { x: _, y }| y).sum(); //~ ERROR unused variable
+
+ match (Point { x: 1, y: 2 }) {
+ Point { y, x: _ } => y, //~ ERROR unused variable
+ };
+}
diff --git a/tests/ui/lint/unused/issue-54180-unused-ref-field.rs b/tests/ui/lint/unused/issue-54180-unused-ref-field.rs
new file mode 100644
index 000000000..7b3392b60
--- /dev/null
+++ b/tests/ui/lint/unused/issue-54180-unused-ref-field.rs
@@ -0,0 +1,34 @@
+// run-rustfix
+
+#![deny(unused)]
+
+pub struct S {
+ pub f1: i32,
+}
+
+pub struct Point {
+ pub x: i32,
+ pub y: i32,
+}
+
+pub enum E {
+ Variant { field: String }
+}
+
+pub fn foo(arg: &E) {
+ match arg {
+ E::Variant { ref field } => (), //~ ERROR unused variable
+ }
+}
+
+fn main() {
+ let s = S { f1: 123 };
+ let S { ref f1 } = s; //~ ERROR unused variable
+
+ let points = vec![Point { x: 1, y: 2 }];
+ let _: i32 = points.iter().map(|Point { x, y }| y).sum(); //~ ERROR unused variable
+
+ match (Point { x: 1, y: 2 }) {
+ Point { y, ref mut x } => y, //~ ERROR unused variable
+ };
+}
diff --git a/tests/ui/lint/unused/issue-54180-unused-ref-field.stderr b/tests/ui/lint/unused/issue-54180-unused-ref-field.stderr
new file mode 100644
index 000000000..f2e616899
--- /dev/null
+++ b/tests/ui/lint/unused/issue-54180-unused-ref-field.stderr
@@ -0,0 +1,33 @@
+error: unused variable: `field`
+ --> $DIR/issue-54180-unused-ref-field.rs:20:22
+ |
+LL | E::Variant { ref field } => (),
+ | ^^^^^^^^^ help: try ignoring the field: `field: _`
+ |
+note: the lint level is defined here
+ --> $DIR/issue-54180-unused-ref-field.rs:3:9
+ |
+LL | #![deny(unused)]
+ | ^^^^^^
+ = note: `#[deny(unused_variables)]` implied by `#[deny(unused)]`
+
+error: unused variable: `f1`
+ --> $DIR/issue-54180-unused-ref-field.rs:26:13
+ |
+LL | let S { ref f1 } = s;
+ | ^^^^^^ help: try ignoring the field: `f1: _`
+
+error: unused variable: `x`
+ --> $DIR/issue-54180-unused-ref-field.rs:32:20
+ |
+LL | Point { y, ref mut x } => y,
+ | ^^^^^^^^^ help: try ignoring the field: `x: _`
+
+error: unused variable: `x`
+ --> $DIR/issue-54180-unused-ref-field.rs:29:45
+ |
+LL | let _: i32 = points.iter().map(|Point { x, y }| y).sum();
+ | ^ help: try ignoring the field: `x: _`
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/lint/unused/issue-54538-unused-parens-lint.fixed b/tests/ui/lint/unused/issue-54538-unused-parens-lint.fixed
new file mode 100644
index 000000000..71ebaea8e
--- /dev/null
+++ b/tests/ui/lint/unused/issue-54538-unused-parens-lint.fixed
@@ -0,0 +1,113 @@
+// run-rustfix
+
+#![feature(box_patterns, stmt_expr_attributes, yeet_expr)]
+
+#![allow(
+ dead_code,
+ ellipsis_inclusive_range_patterns,
+ irrefutable_let_patterns,
+ unreachable_patterns,
+ unused_mut,
+ unused_variables
+)]
+#![deny(unused_parens)]
+
+fn lint_on_top_level() {
+ let a = 0; //~ ERROR unnecessary parentheses around pattern
+ for a in 0..1 {} //~ ERROR unnecessary parentheses around pattern
+ if let a = 0 {} //~ ERROR unnecessary parentheses around pattern
+ while let a = 0 {} //~ ERROR unnecessary parentheses around pattern
+ fn foo(a: u8) {} //~ ERROR unnecessary parentheses around pattern
+ let _ = |a: u8| 0; //~ ERROR unnecessary parentheses around pattern
+}
+
+fn _no_lint_attr() {
+ let _x = #[allow(dead_code)] (1 + 2);
+}
+
+fn _no_lint_yeet() -> Result<(), ()> {
+ #[allow(unreachable_code)]
+ if (do yeet) {}
+
+ Ok(())
+}
+
+// Don't lint in these cases (#64106).
+fn or_patterns_no_lint() {
+ match Box::new(0) {
+ box (0 | 1) => {} // Should not lint as `box 0 | 1` binds as `(box 0) | 1`.
+ _ => {}
+ }
+
+ match 0 {
+ x @ (0 | 1) => {} // Should not lint as `x @ 0 | 1` binds as `(x @ 0) | 1`.
+ _ => {}
+ }
+
+ if let &(0 | 1) = &0 {} // Should also not lint.
+ if let &mut (0 | 1) = &mut 0 {} // Same.
+
+ fn foo((Ok(a) | Err(a)): Result<u8, u8>) {} // Doesn't parse if we remove parens for now.
+
+ let _ = |(Ok(a) | Err(a)): Result<u8, u8>| 1; // `|Ok(a) | Err(a)| 1` parses as bit-or.
+}
+
+fn or_patterns_will_lint() {
+ if let 0 | 1 = 0 {} //~ ERROR unnecessary parentheses around pattern
+ if let (0 | 1,) = (0,) {} //~ ERROR unnecessary parentheses around pattern
+ if let [0 | 1] = [0] {} //~ ERROR unnecessary parentheses around pattern
+ if let 0 | 1 | 2 = 0 {} //~ ERROR unnecessary parentheses around pattern
+ struct TS(u8);
+ if let TS(0 | 1) = TS(0) {} //~ ERROR unnecessary parentheses around pattern
+ struct NS { f: u8 }
+ if let NS { f: 0 | 1 } = (NS { f: 0 }) {} //~ ERROR unnecessary parentheses around pattern
+}
+
+// Don't lint on `&(mut x)` because `&mut x` means something else (#55342).
+fn deref_mut_binding_no_lint() {
+ let &(mut x) = &0;
+}
+
+fn main() {
+ match 1 {
+ _ => {} //~ ERROR unnecessary parentheses around pattern
+ y => {} //~ ERROR unnecessary parentheses around pattern
+ ref r => {} //~ ERROR unnecessary parentheses around pattern
+ e @ 1...2 => {} //~ ERROR unnecessary parentheses around pattern
+ (1...2) => {} // Non ambiguous range pattern should not warn
+ e @ (3...4) => {} // Non ambiguous range pattern should not warn
+ }
+
+ match &1 {
+ e @ &(1...2) => {} //~ ERROR unnecessary parentheses around pattern
+ &_ => {} //~ ERROR unnecessary parentheses around pattern
+ e @ &(1...2) => {} // Ambiguous range pattern should not warn
+ &(1...2) => {} // Ambiguous range pattern should not warn
+ }
+
+ match &1 {
+ e @ &(1...2) | e @ &(3...4) => {} // Complex ambiguous pattern should not warn
+ &_ => {}
+ }
+
+ match 1 {
+ _ => {} //~ ERROR unnecessary parentheses around pattern
+ y => {} //~ ERROR unnecessary parentheses around pattern
+ ref r => {} //~ ERROR unnecessary parentheses around pattern
+ e @ 1..=2 => {} //~ ERROR unnecessary parentheses around pattern
+ (1..=2) => {} // Non ambiguous range pattern should not warn
+ e @ (3..=4) => {} // Non ambiguous range pattern should not warn
+ }
+
+ match &1 {
+ e @ &(1..=2) => {} //~ ERROR unnecessary parentheses around pattern
+ &_ => {} //~ ERROR unnecessary parentheses around pattern
+ e @ &(1..=2) => {} // Ambiguous range pattern should not warn
+ &(1..=2) => {} // Ambiguous range pattern should not warn
+ }
+
+ match &1 {
+ e @ &(1..=2) | e @ &(3..=4) => {} // Complex ambiguous pattern should not warn
+ &_ => {}
+ }
+}
diff --git a/tests/ui/lint/unused/issue-54538-unused-parens-lint.rs b/tests/ui/lint/unused/issue-54538-unused-parens-lint.rs
new file mode 100644
index 000000000..28b662dd0
--- /dev/null
+++ b/tests/ui/lint/unused/issue-54538-unused-parens-lint.rs
@@ -0,0 +1,113 @@
+// run-rustfix
+
+#![feature(box_patterns, stmt_expr_attributes, yeet_expr)]
+
+#![allow(
+ dead_code,
+ ellipsis_inclusive_range_patterns,
+ irrefutable_let_patterns,
+ unreachable_patterns,
+ unused_mut,
+ unused_variables
+)]
+#![deny(unused_parens)]
+
+fn lint_on_top_level() {
+ let (a) = 0; //~ ERROR unnecessary parentheses around pattern
+ for (a) in 0..1 {} //~ ERROR unnecessary parentheses around pattern
+ if let (a) = 0 {} //~ ERROR unnecessary parentheses around pattern
+ while let (a) = 0 {} //~ ERROR unnecessary parentheses around pattern
+ fn foo((a): u8) {} //~ ERROR unnecessary parentheses around pattern
+ let _ = |(a): u8| 0; //~ ERROR unnecessary parentheses around pattern
+}
+
+fn _no_lint_attr() {
+ let _x = #[allow(dead_code)] (1 + 2);
+}
+
+fn _no_lint_yeet() -> Result<(), ()> {
+ #[allow(unreachable_code)]
+ if (do yeet) {}
+
+ Ok(())
+}
+
+// Don't lint in these cases (#64106).
+fn or_patterns_no_lint() {
+ match Box::new(0) {
+ box (0 | 1) => {} // Should not lint as `box 0 | 1` binds as `(box 0) | 1`.
+ _ => {}
+ }
+
+ match 0 {
+ x @ (0 | 1) => {} // Should not lint as `x @ 0 | 1` binds as `(x @ 0) | 1`.
+ _ => {}
+ }
+
+ if let &(0 | 1) = &0 {} // Should also not lint.
+ if let &mut (0 | 1) = &mut 0 {} // Same.
+
+ fn foo((Ok(a) | Err(a)): Result<u8, u8>) {} // Doesn't parse if we remove parens for now.
+
+ let _ = |(Ok(a) | Err(a)): Result<u8, u8>| 1; // `|Ok(a) | Err(a)| 1` parses as bit-or.
+}
+
+fn or_patterns_will_lint() {
+ if let (0 | 1) = 0 {} //~ ERROR unnecessary parentheses around pattern
+ if let ((0 | 1),) = (0,) {} //~ ERROR unnecessary parentheses around pattern
+ if let [(0 | 1)] = [0] {} //~ ERROR unnecessary parentheses around pattern
+ if let 0 | (1 | 2) = 0 {} //~ ERROR unnecessary parentheses around pattern
+ struct TS(u8);
+ if let TS((0 | 1)) = TS(0) {} //~ ERROR unnecessary parentheses around pattern
+ struct NS { f: u8 }
+ if let NS { f: (0 | 1) } = (NS { f: 0 }) {} //~ ERROR unnecessary parentheses around pattern
+}
+
+// Don't lint on `&(mut x)` because `&mut x` means something else (#55342).
+fn deref_mut_binding_no_lint() {
+ let &(mut x) = &0;
+}
+
+fn main() {
+ match 1 {
+ (_) => {} //~ ERROR unnecessary parentheses around pattern
+ (y) => {} //~ ERROR unnecessary parentheses around pattern
+ (ref r) => {} //~ ERROR unnecessary parentheses around pattern
+ (e @ 1...2) => {} //~ ERROR unnecessary parentheses around pattern
+ (1...2) => {} // Non ambiguous range pattern should not warn
+ e @ (3...4) => {} // Non ambiguous range pattern should not warn
+ }
+
+ match &1 {
+ (e @ &(1...2)) => {} //~ ERROR unnecessary parentheses around pattern
+ &(_) => {} //~ ERROR unnecessary parentheses around pattern
+ e @ &(1...2) => {} // Ambiguous range pattern should not warn
+ &(1...2) => {} // Ambiguous range pattern should not warn
+ }
+
+ match &1 {
+ e @ &(1...2) | e @ &(3...4) => {} // Complex ambiguous pattern should not warn
+ &_ => {}
+ }
+
+ match 1 {
+ (_) => {} //~ ERROR unnecessary parentheses around pattern
+ (y) => {} //~ ERROR unnecessary parentheses around pattern
+ (ref r) => {} //~ ERROR unnecessary parentheses around pattern
+ (e @ 1..=2) => {} //~ ERROR unnecessary parentheses around pattern
+ (1..=2) => {} // Non ambiguous range pattern should not warn
+ e @ (3..=4) => {} // Non ambiguous range pattern should not warn
+ }
+
+ match &1 {
+ (e @ &(1..=2)) => {} //~ ERROR unnecessary parentheses around pattern
+ &(_) => {} //~ ERROR unnecessary parentheses around pattern
+ e @ &(1..=2) => {} // Ambiguous range pattern should not warn
+ &(1..=2) => {} // Ambiguous range pattern should not warn
+ }
+
+ match &1 {
+ e @ &(1..=2) | e @ &(3..=4) => {} // Complex ambiguous pattern should not warn
+ &_ => {}
+ }
+}
diff --git a/tests/ui/lint/unused/issue-54538-unused-parens-lint.stderr b/tests/ui/lint/unused/issue-54538-unused-parens-lint.stderr
new file mode 100644
index 000000000..a5e69e6d9
--- /dev/null
+++ b/tests/ui/lint/unused/issue-54538-unused-parens-lint.stderr
@@ -0,0 +1,295 @@
+error: unnecessary parentheses around pattern
+ --> $DIR/issue-54538-unused-parens-lint.rs:16:9
+ |
+LL | let (a) = 0;
+ | ^ ^
+ |
+note: the lint level is defined here
+ --> $DIR/issue-54538-unused-parens-lint.rs:13:9
+ |
+LL | #![deny(unused_parens)]
+ | ^^^^^^^^^^^^^
+help: remove these parentheses
+ |
+LL - let (a) = 0;
+LL + let a = 0;
+ |
+
+error: unnecessary parentheses around pattern
+ --> $DIR/issue-54538-unused-parens-lint.rs:17:9
+ |
+LL | for (a) in 0..1 {}
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - for (a) in 0..1 {}
+LL + for a in 0..1 {}
+ |
+
+error: unnecessary parentheses around pattern
+ --> $DIR/issue-54538-unused-parens-lint.rs:18:12
+ |
+LL | if let (a) = 0 {}
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - if let (a) = 0 {}
+LL + if let a = 0 {}
+ |
+
+error: unnecessary parentheses around pattern
+ --> $DIR/issue-54538-unused-parens-lint.rs:19:15
+ |
+LL | while let (a) = 0 {}
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - while let (a) = 0 {}
+LL + while let a = 0 {}
+ |
+
+error: unnecessary parentheses around pattern
+ --> $DIR/issue-54538-unused-parens-lint.rs:20:12
+ |
+LL | fn foo((a): u8) {}
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - fn foo((a): u8) {}
+LL + fn foo(a: u8) {}
+ |
+
+error: unnecessary parentheses around pattern
+ --> $DIR/issue-54538-unused-parens-lint.rs:21:14
+ |
+LL | let _ = |(a): u8| 0;
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - let _ = |(a): u8| 0;
+LL + let _ = |a: u8| 0;
+ |
+
+error: unnecessary parentheses around pattern
+ --> $DIR/issue-54538-unused-parens-lint.rs:56:12
+ |
+LL | if let (0 | 1) = 0 {}
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - if let (0 | 1) = 0 {}
+LL + if let 0 | 1 = 0 {}
+ |
+
+error: unnecessary parentheses around pattern
+ --> $DIR/issue-54538-unused-parens-lint.rs:57:13
+ |
+LL | if let ((0 | 1),) = (0,) {}
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - if let ((0 | 1),) = (0,) {}
+LL + if let (0 | 1,) = (0,) {}
+ |
+
+error: unnecessary parentheses around pattern
+ --> $DIR/issue-54538-unused-parens-lint.rs:58:13
+ |
+LL | if let [(0 | 1)] = [0] {}
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - if let [(0 | 1)] = [0] {}
+LL + if let [0 | 1] = [0] {}
+ |
+
+error: unnecessary parentheses around pattern
+ --> $DIR/issue-54538-unused-parens-lint.rs:59:16
+ |
+LL | if let 0 | (1 | 2) = 0 {}
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - if let 0 | (1 | 2) = 0 {}
+LL + if let 0 | 1 | 2 = 0 {}
+ |
+
+error: unnecessary parentheses around pattern
+ --> $DIR/issue-54538-unused-parens-lint.rs:61:15
+ |
+LL | if let TS((0 | 1)) = TS(0) {}
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - if let TS((0 | 1)) = TS(0) {}
+LL + if let TS(0 | 1) = TS(0) {}
+ |
+
+error: unnecessary parentheses around pattern
+ --> $DIR/issue-54538-unused-parens-lint.rs:63:20
+ |
+LL | if let NS { f: (0 | 1) } = (NS { f: 0 }) {}
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - if let NS { f: (0 | 1) } = (NS { f: 0 }) {}
+LL + if let NS { f: 0 | 1 } = (NS { f: 0 }) {}
+ |
+
+error: unnecessary parentheses around pattern
+ --> $DIR/issue-54538-unused-parens-lint.rs:73:9
+ |
+LL | (_) => {}
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - (_) => {}
+LL + _ => {}
+ |
+
+error: unnecessary parentheses around pattern
+ --> $DIR/issue-54538-unused-parens-lint.rs:74:9
+ |
+LL | (y) => {}
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - (y) => {}
+LL + y => {}
+ |
+
+error: unnecessary parentheses around pattern
+ --> $DIR/issue-54538-unused-parens-lint.rs:75:9
+ |
+LL | (ref r) => {}
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - (ref r) => {}
+LL + ref r => {}
+ |
+
+error: unnecessary parentheses around pattern
+ --> $DIR/issue-54538-unused-parens-lint.rs:76:9
+ |
+LL | (e @ 1...2) => {}
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - (e @ 1...2) => {}
+LL + e @ 1...2 => {}
+ |
+
+error: unnecessary parentheses around pattern
+ --> $DIR/issue-54538-unused-parens-lint.rs:82:9
+ |
+LL | (e @ &(1...2)) => {}
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - (e @ &(1...2)) => {}
+LL + e @ &(1...2) => {}
+ |
+
+error: unnecessary parentheses around pattern
+ --> $DIR/issue-54538-unused-parens-lint.rs:83:10
+ |
+LL | &(_) => {}
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - &(_) => {}
+LL + &_ => {}
+ |
+
+error: unnecessary parentheses around pattern
+ --> $DIR/issue-54538-unused-parens-lint.rs:94:9
+ |
+LL | (_) => {}
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - (_) => {}
+LL + _ => {}
+ |
+
+error: unnecessary parentheses around pattern
+ --> $DIR/issue-54538-unused-parens-lint.rs:95:9
+ |
+LL | (y) => {}
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - (y) => {}
+LL + y => {}
+ |
+
+error: unnecessary parentheses around pattern
+ --> $DIR/issue-54538-unused-parens-lint.rs:96:9
+ |
+LL | (ref r) => {}
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - (ref r) => {}
+LL + ref r => {}
+ |
+
+error: unnecessary parentheses around pattern
+ --> $DIR/issue-54538-unused-parens-lint.rs:97:9
+ |
+LL | (e @ 1..=2) => {}
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - (e @ 1..=2) => {}
+LL + e @ 1..=2 => {}
+ |
+
+error: unnecessary parentheses around pattern
+ --> $DIR/issue-54538-unused-parens-lint.rs:103:9
+ |
+LL | (e @ &(1..=2)) => {}
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - (e @ &(1..=2)) => {}
+LL + e @ &(1..=2) => {}
+ |
+
+error: unnecessary parentheses around pattern
+ --> $DIR/issue-54538-unused-parens-lint.rs:104:10
+ |
+LL | &(_) => {}
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - &(_) => {}
+LL + &_ => {}
+ |
+
+error: aborting due to 24 previous errors
+
diff --git a/tests/ui/lint/unused/issue-59896.rs b/tests/ui/lint/unused/issue-59896.rs
new file mode 100644
index 000000000..ff9f19acf
--- /dev/null
+++ b/tests/ui/lint/unused/issue-59896.rs
@@ -0,0 +1,9 @@
+#![deny(unused_imports)]
+
+struct S;
+
+fn main() {
+ use S; //~ ERROR the item `S` is imported redundantly
+
+ let _s = S;
+}
diff --git a/tests/ui/lint/unused/issue-59896.stderr b/tests/ui/lint/unused/issue-59896.stderr
new file mode 100644
index 000000000..95b7938ae
--- /dev/null
+++ b/tests/ui/lint/unused/issue-59896.stderr
@@ -0,0 +1,17 @@
+error: the item `S` is imported redundantly
+ --> $DIR/issue-59896.rs:6:9
+ |
+LL | struct S;
+ | --------- the item `S` is already defined here
+...
+LL | use S;
+ | ^
+ |
+note: the lint level is defined here
+ --> $DIR/issue-59896.rs:1:9
+ |
+LL | #![deny(unused_imports)]
+ | ^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/lint/unused/issue-67691-unused-field-in-or-pattern.rs b/tests/ui/lint/unused/issue-67691-unused-field-in-or-pattern.rs
new file mode 100644
index 000000000..e3631d014
--- /dev/null
+++ b/tests/ui/lint/unused/issue-67691-unused-field-in-or-pattern.rs
@@ -0,0 +1,85 @@
+// FIXME: should be run-rustfix, but rustfix doesn't currently support multipart suggestions, see
+// #53934
+
+#![deny(unused)]
+
+pub enum MyEnum {
+ A { i: i32, j: i32 },
+ B { i: i32, j: i32 },
+}
+
+pub enum MixedEnum {
+ A { i: i32 },
+ B(i32),
+}
+
+pub fn no_ref(x: MyEnum) {
+ use MyEnum::*;
+
+ match x {
+ A { i, j } | B { i, j } => { //~ ERROR unused variable
+ println!("{}", i);
+ }
+ }
+}
+
+pub fn with_ref(x: MyEnum) {
+ use MyEnum::*;
+
+ match x {
+ A { i, ref j } | B { i, ref j } => { //~ ERROR unused variable
+ println!("{}", i);
+ }
+ }
+}
+
+pub fn inner_no_ref(x: Option<MyEnum>) {
+ use MyEnum::*;
+
+ match x {
+ Some(A { i, j } | B { i, j }) => { //~ ERROR unused variable
+ println!("{}", i);
+ }
+
+ _ => {}
+ }
+}
+
+pub fn inner_with_ref(x: Option<MyEnum>) {
+ use MyEnum::*;
+
+ match x {
+ Some(A { i, ref j } | B { i, ref j }) => { //~ ERROR unused variable
+ println!("{}", i);
+ }
+
+ _ => {}
+ }
+}
+
+pub fn mixed_no_ref(x: MixedEnum) {
+ match x {
+ MixedEnum::A { i } | MixedEnum::B(i) => { //~ ERROR unused variable
+ println!("match");
+ }
+ }
+}
+
+pub fn mixed_with_ref(x: MixedEnum) {
+ match x {
+ MixedEnum::A { ref i } | MixedEnum::B(ref i) => { //~ ERROR unused variable
+ println!("match");
+ }
+ }
+}
+
+pub fn main() {
+ no_ref(MyEnum::A { i: 1, j: 2 });
+ with_ref(MyEnum::A { i: 1, j: 2 });
+
+ inner_no_ref(Some(MyEnum::A { i: 1, j: 2 }));
+ inner_with_ref(Some(MyEnum::A { i: 1, j: 2 }));
+
+ mixed_no_ref(MixedEnum::B(5));
+ mixed_with_ref(MixedEnum::B(5));
+}
diff --git a/tests/ui/lint/unused/issue-67691-unused-field-in-or-pattern.stderr b/tests/ui/lint/unused/issue-67691-unused-field-in-or-pattern.stderr
new file mode 100644
index 000000000..8fc2d1bc8
--- /dev/null
+++ b/tests/ui/lint/unused/issue-67691-unused-field-in-or-pattern.stderr
@@ -0,0 +1,74 @@
+error: unused variable: `j`
+ --> $DIR/issue-67691-unused-field-in-or-pattern.rs:20:16
+ |
+LL | A { i, j } | B { i, j } => {
+ | ^ ^
+ |
+note: the lint level is defined here
+ --> $DIR/issue-67691-unused-field-in-or-pattern.rs:4:9
+ |
+LL | #![deny(unused)]
+ | ^^^^^^
+ = note: `#[deny(unused_variables)]` implied by `#[deny(unused)]`
+help: try ignoring the field
+ |
+LL | A { i, j: _ } | B { i, j: _ } => {
+ | ~~~~ ~~~~
+
+error: unused variable: `j`
+ --> $DIR/issue-67691-unused-field-in-or-pattern.rs:30:16
+ |
+LL | A { i, ref j } | B { i, ref j } => {
+ | ^^^^^ ^^^^^
+ |
+help: try ignoring the field
+ |
+LL | A { i, j: _ } | B { i, j: _ } => {
+ | ~~~~ ~~~~
+
+error: unused variable: `j`
+ --> $DIR/issue-67691-unused-field-in-or-pattern.rs:40:21
+ |
+LL | Some(A { i, j } | B { i, j }) => {
+ | ^ ^
+ |
+help: try ignoring the field
+ |
+LL | Some(A { i, j: _ } | B { i, j: _ }) => {
+ | ~~~~ ~~~~
+
+error: unused variable: `j`
+ --> $DIR/issue-67691-unused-field-in-or-pattern.rs:52:21
+ |
+LL | Some(A { i, ref j } | B { i, ref j }) => {
+ | ^^^^^ ^^^^^
+ |
+help: try ignoring the field
+ |
+LL | Some(A { i, j: _ } | B { i, j: _ }) => {
+ | ~~~~ ~~~~
+
+error: unused variable: `i`
+ --> $DIR/issue-67691-unused-field-in-or-pattern.rs:62:24
+ |
+LL | MixedEnum::A { i } | MixedEnum::B(i) => {
+ | ^ ^
+ |
+help: try ignoring the field
+ |
+LL | MixedEnum::A { i: _ } | MixedEnum::B(_) => {
+ | ~~~~ ~
+
+error: unused variable: `i`
+ --> $DIR/issue-67691-unused-field-in-or-pattern.rs:70:24
+ |
+LL | MixedEnum::A { ref i } | MixedEnum::B(ref i) => {
+ | ^^^^^ ^^^^^
+ |
+help: try ignoring the field
+ |
+LL | MixedEnum::A { i: _ } | MixedEnum::B(_) => {
+ | ~~~~ ~
+
+error: aborting due to 6 previous errors
+
diff --git a/tests/ui/lint/unused/issue-70041.rs b/tests/ui/lint/unused/issue-70041.rs
new file mode 100644
index 000000000..22e42295e
--- /dev/null
+++ b/tests/ui/lint/unused/issue-70041.rs
@@ -0,0 +1,13 @@
+// compile-flags: --edition=2018
+// run-pass
+
+macro_rules! regex {
+ //~^ WARN unused macro definition
+ () => {};
+}
+
+#[allow(dead_code)]
+use regex;
+//~^ WARN unused import
+
+fn main() {}
diff --git a/tests/ui/lint/unused/issue-70041.stderr b/tests/ui/lint/unused/issue-70041.stderr
new file mode 100644
index 000000000..b2e6d1aeb
--- /dev/null
+++ b/tests/ui/lint/unused/issue-70041.stderr
@@ -0,0 +1,18 @@
+warning: unused macro definition: `regex`
+ --> $DIR/issue-70041.rs:4:14
+ |
+LL | macro_rules! regex {
+ | ^^^^^
+ |
+ = note: `#[warn(unused_macros)]` on by default
+
+warning: unused import: `regex`
+ --> $DIR/issue-70041.rs:10:5
+ |
+LL | use regex;
+ | ^^^^^
+ |
+ = note: `#[warn(unused_imports)]` on by default
+
+warning: 2 warnings emitted
+
diff --git a/tests/ui/lint/unused/issue-71290-unused-paren-binop.rs b/tests/ui/lint/unused/issue-71290-unused-paren-binop.rs
new file mode 100644
index 000000000..24d77e36d
--- /dev/null
+++ b/tests/ui/lint/unused/issue-71290-unused-paren-binop.rs
@@ -0,0 +1,23 @@
+// check-pass
+// Make sure unused parens lint doesn't emit a false positive.
+// See https://github.com/rust-lang/rust/issues/71290 for details.
+#![deny(unused_parens)]
+
+fn x() -> u8 {
+ ({ 0 }) + 1
+}
+
+fn y() -> u8 {
+ ({ 0 } + 1)
+}
+
+pub fn foo(a: bool, b: bool) -> u8 {
+ (if a { 1 } else { 0 } + if b { 1 } else { 0 })
+}
+
+pub fn bar() -> u8 {
+ // Make sure nested expressions are handled correctly as well
+ ({ 0 } + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9)
+}
+
+fn main() {}
diff --git a/tests/ui/lint/unused/issue-74883-unused-paren-baren-yield.rs b/tests/ui/lint/unused/issue-74883-unused-paren-baren-yield.rs
new file mode 100644
index 000000000..8064c3a88
--- /dev/null
+++ b/tests/ui/lint/unused/issue-74883-unused-paren-baren-yield.rs
@@ -0,0 +1,26 @@
+#![feature(generator_trait)]
+#![feature(generators)]
+#![deny(unused_braces, unused_parens)]
+
+use std::ops::Generator;
+use std::pin::Pin;
+
+fn main() {
+ let mut x = |_| {
+ while let Some(_) = (yield) {}
+ while let Some(_) = {yield} {}
+
+ // Only warn these cases
+ while let Some(_) = ({yield}) {} //~ ERROR: unnecessary parentheses
+ while let Some(_) = ((yield)) {} //~ ERROR: unnecessary parentheses
+ {{yield}}; //~ ERROR: unnecessary braces
+ {( yield )}; //~ ERROR: unnecessary parentheses
+ while let Some(_) = {(yield)} {} //~ ERROR: unnecessary parentheses
+ while let Some(_) = {{yield}} {} //~ ERROR: unnecessary braces
+
+ // FIXME: It'd be great if we could also warn them.
+ ((yield));
+ ({ yield });
+ };
+ let _ = Pin::new(&mut x).resume(Some(5));
+}
diff --git a/tests/ui/lint/unused/issue-74883-unused-paren-baren-yield.stderr b/tests/ui/lint/unused/issue-74883-unused-paren-baren-yield.stderr
new file mode 100644
index 000000000..3f1fee332
--- /dev/null
+++ b/tests/ui/lint/unused/issue-74883-unused-paren-baren-yield.stderr
@@ -0,0 +1,84 @@
+error: unnecessary parentheses around `let` scrutinee expression
+ --> $DIR/issue-74883-unused-paren-baren-yield.rs:14:29
+ |
+LL | while let Some(_) = ({yield}) {}
+ | ^ ^
+ |
+note: the lint level is defined here
+ --> $DIR/issue-74883-unused-paren-baren-yield.rs:3:24
+ |
+LL | #![deny(unused_braces, unused_parens)]
+ | ^^^^^^^^^^^^^
+help: remove these parentheses
+ |
+LL - while let Some(_) = ({yield}) {}
+LL + while let Some(_) = {yield} {}
+ |
+
+error: unnecessary parentheses around `let` scrutinee expression
+ --> $DIR/issue-74883-unused-paren-baren-yield.rs:15:29
+ |
+LL | while let Some(_) = ((yield)) {}
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - while let Some(_) = ((yield)) {}
+LL + while let Some(_) = (yield) {}
+ |
+
+error: unnecessary braces around block return value
+ --> $DIR/issue-74883-unused-paren-baren-yield.rs:16:10
+ |
+LL | {{yield}};
+ | ^ ^
+ |
+note: the lint level is defined here
+ --> $DIR/issue-74883-unused-paren-baren-yield.rs:3:9
+ |
+LL | #![deny(unused_braces, unused_parens)]
+ | ^^^^^^^^^^^^^
+help: remove these braces
+ |
+LL - {{yield}};
+LL + {yield};
+ |
+
+error: unnecessary parentheses around block return value
+ --> $DIR/issue-74883-unused-paren-baren-yield.rs:17:10
+ |
+LL | {( yield )};
+ | ^^ ^^
+ |
+help: remove these parentheses
+ |
+LL - {( yield )};
+LL + {yield};
+ |
+
+error: unnecessary parentheses around block return value
+ --> $DIR/issue-74883-unused-paren-baren-yield.rs:18:30
+ |
+LL | while let Some(_) = {(yield)} {}
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - while let Some(_) = {(yield)} {}
+LL + while let Some(_) = {yield} {}
+ |
+
+error: unnecessary braces around block return value
+ --> $DIR/issue-74883-unused-paren-baren-yield.rs:19:30
+ |
+LL | while let Some(_) = {{yield}} {}
+ | ^ ^
+ |
+help: remove these braces
+ |
+LL - while let Some(_) = {{yield}} {}
+LL + while let Some(_) = {yield} {}
+ |
+
+error: aborting due to 6 previous errors
+
diff --git a/tests/ui/lint/unused/issue-81314-unused-span-ident.fixed b/tests/ui/lint/unused/issue-81314-unused-span-ident.fixed
new file mode 100644
index 000000000..aac918f2b
--- /dev/null
+++ b/tests/ui/lint/unused/issue-81314-unused-span-ident.fixed
@@ -0,0 +1,12 @@
+// run-rustfix
+// Regression test for #81314: Unused variable lint should
+// span only the identifier and not the rest of the pattern
+
+#![deny(unused)]
+
+fn main() {
+ let [_rest @ ..] = [1, 2, 3]; //~ ERROR unused variable
+}
+
+pub fn foo([_rest @ ..]: &[i32]) { //~ ERROR unused variable
+}
diff --git a/tests/ui/lint/unused/issue-81314-unused-span-ident.rs b/tests/ui/lint/unused/issue-81314-unused-span-ident.rs
new file mode 100644
index 000000000..78296f425
--- /dev/null
+++ b/tests/ui/lint/unused/issue-81314-unused-span-ident.rs
@@ -0,0 +1,12 @@
+// run-rustfix
+// Regression test for #81314: Unused variable lint should
+// span only the identifier and not the rest of the pattern
+
+#![deny(unused)]
+
+fn main() {
+ let [rest @ ..] = [1, 2, 3]; //~ ERROR unused variable
+}
+
+pub fn foo([rest @ ..]: &[i32]) { //~ ERROR unused variable
+}
diff --git a/tests/ui/lint/unused/issue-81314-unused-span-ident.stderr b/tests/ui/lint/unused/issue-81314-unused-span-ident.stderr
new file mode 100644
index 000000000..519c71e94
--- /dev/null
+++ b/tests/ui/lint/unused/issue-81314-unused-span-ident.stderr
@@ -0,0 +1,21 @@
+error: unused variable: `rest`
+ --> $DIR/issue-81314-unused-span-ident.rs:8:10
+ |
+LL | let [rest @ ..] = [1, 2, 3];
+ | ^^^^ help: if this is intentional, prefix it with an underscore: `_rest`
+ |
+note: the lint level is defined here
+ --> $DIR/issue-81314-unused-span-ident.rs:5:9
+ |
+LL | #![deny(unused)]
+ | ^^^^^^
+ = note: `#[deny(unused_variables)]` implied by `#[deny(unused)]`
+
+error: unused variable: `rest`
+ --> $DIR/issue-81314-unused-span-ident.rs:11:13
+ |
+LL | pub fn foo([rest @ ..]: &[i32]) {
+ | ^^^^ help: if this is intentional, prefix it with an underscore: `_rest`
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/lint/unused/issue-85913.rs b/tests/ui/lint/unused/issue-85913.rs
new file mode 100644
index 000000000..7f3817b6e
--- /dev/null
+++ b/tests/ui/lint/unused/issue-85913.rs
@@ -0,0 +1,13 @@
+#![deny(unused_must_use)]
+
+pub fn fun() -> i32 {
+ function() && return 1;
+ //~^ ERROR: unused logical operation that must be used
+ return 0;
+}
+
+fn function() -> bool {
+ true
+}
+
+fn main() {}
diff --git a/tests/ui/lint/unused/issue-85913.stderr b/tests/ui/lint/unused/issue-85913.stderr
new file mode 100644
index 000000000..8234ed3b1
--- /dev/null
+++ b/tests/ui/lint/unused/issue-85913.stderr
@@ -0,0 +1,18 @@
+error: unused logical operation that must be used
+ --> $DIR/issue-85913.rs:4:5
+ |
+LL | function() && return 1;
+ | ^^^^^^^^^^^^^^^^^^^^^^ the logical operation produces a value
+ |
+note: the lint level is defined here
+ --> $DIR/issue-85913.rs:1:9
+ |
+LL | #![deny(unused_must_use)]
+ | ^^^^^^^^^^^^^^^
+help: use `let _ = ...` to ignore the resulting value
+ |
+LL | let _ = function() && return 1;
+ | +++++++
+
+error: aborting due to previous error
+
diff --git a/tests/ui/lint/unused/issue-88519-unused-paren.rs b/tests/ui/lint/unused/issue-88519-unused-paren.rs
new file mode 100644
index 000000000..ce3d15ac1
--- /dev/null
+++ b/tests/ui/lint/unused/issue-88519-unused-paren.rs
@@ -0,0 +1,85 @@
+// check-pass
+// Make sure unused parens lint doesn't emit a false positive.
+// See https://github.com/rust-lang/rust/issues/88519
+#![deny(unused_parens)]
+#![feature(type_ascription)]
+
+// binary ops are tested in issue-71290-unused-paren-binop.rs
+
+mod call {
+ fn noop() -> u8 { 0 }
+ fn outside() -> u8 {
+ ({ noop })()
+ }
+ fn inside() -> u8 {
+ ({ noop }())
+ }
+ fn outside_match() -> u8 {
+ (match noop { x => x })()
+ }
+ fn inside_match() -> u8 {
+ (match noop { x => x }())
+ }
+ fn outside_if() -> u8 {
+ (if false { noop } else { noop })()
+ }
+ fn inside_if() -> u8 {
+ (if false { noop } else { noop }())
+ }
+}
+
+mod casts {
+ fn outside() -> u8 {
+ ({ 0 }) as u8
+ }
+ fn inside() -> u8 {
+ ({ 0 } as u8)
+ }
+ fn outside_match() -> u8 {
+ (match 0 { x => x }) as u8
+ }
+ fn inside_match() -> u8 {
+ (match 0 { x => x } as u8)
+ }
+ fn outside_if() -> u8 {
+ (if false { 0 } else { 0 }) as u8
+ }
+ fn inside_if() -> u8 {
+ (if false { 0 } else { 0 } as u8)
+ }
+}
+
+mod typeascription {
+ fn outside() -> u8 {
+ type_ascribe!(({ 0 }), u8)
+ }
+ fn outside_match() -> u8 {
+ type_ascribe!((match 0 { x => x }), u8)
+ }
+ fn outside_if() -> u8 {
+ type_ascribe!((if false { 0 } else { 0 }), u8)
+ }
+}
+
+mod index {
+ fn outside(x: &[u8]) -> u8 {
+ ({ x })[0]
+ }
+ fn inside(x: &[u8]) -> u8 {
+ ({ x }[0])
+ }
+ fn outside_match(x: &[u8]) -> u8 {
+ (match x { x => x })[0]
+ }
+ fn inside_match(x: &[u8]) -> u8 {
+ (match x { x => x }[0])
+ }
+ fn outside_if(x: &[u8]) -> u8 {
+ (if false { x } else { x })[0]
+ }
+ fn inside_if(x: &[u8]) -> u8 {
+ (if false { x } else { x }[0])
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/lint/unused/issue-90807-unused-paren-error.rs b/tests/ui/lint/unused/issue-90807-unused-paren-error.rs
new file mode 100644
index 000000000..2fca2e262
--- /dev/null
+++ b/tests/ui/lint/unused/issue-90807-unused-paren-error.rs
@@ -0,0 +1,9 @@
+// Make sure unused parens lint emit is emitted for loop and match.
+// See https://github.com/rust-lang/rust/issues/90807
+// and https://github.com/rust-lang/rust/pull/91956#discussion_r771647953
+#![deny(unused_parens)]
+
+fn main() {
+ for _ in (1..loop { break 2 }) {} //~ERROR
+ for _ in (1..match () { () => 2 }) {} //~ERROR
+}
diff --git a/tests/ui/lint/unused/issue-90807-unused-paren-error.stderr b/tests/ui/lint/unused/issue-90807-unused-paren-error.stderr
new file mode 100644
index 000000000..b3b809d5f
--- /dev/null
+++ b/tests/ui/lint/unused/issue-90807-unused-paren-error.stderr
@@ -0,0 +1,31 @@
+error: unnecessary parentheses around `for` iterator expression
+ --> $DIR/issue-90807-unused-paren-error.rs:7:14
+ |
+LL | for _ in (1..loop { break 2 }) {}
+ | ^ ^
+ |
+note: the lint level is defined here
+ --> $DIR/issue-90807-unused-paren-error.rs:4:9
+ |
+LL | #![deny(unused_parens)]
+ | ^^^^^^^^^^^^^
+help: remove these parentheses
+ |
+LL - for _ in (1..loop { break 2 }) {}
+LL + for _ in 1..loop { break 2 } {}
+ |
+
+error: unnecessary parentheses around `for` iterator expression
+ --> $DIR/issue-90807-unused-paren-error.rs:8:14
+ |
+LL | for _ in (1..match () { () => 2 }) {}
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - for _ in (1..match () { () => 2 }) {}
+LL + for _ in 1..match () { () => 2 } {}
+ |
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/lint/unused/issue-90807-unused-paren.rs b/tests/ui/lint/unused/issue-90807-unused-paren.rs
new file mode 100644
index 000000000..4c0930f96
--- /dev/null
+++ b/tests/ui/lint/unused/issue-90807-unused-paren.rs
@@ -0,0 +1,8 @@
+// check-pass
+// Make sure unused parens lint doesn't emit a false positive.
+// See https://github.com/rust-lang/rust/issues/90807
+#![deny(unused_parens)]
+
+fn main() {
+ for _ in (1..{ 2 }) {}
+}
diff --git a/tests/ui/lint/unused/issue-92751.rs b/tests/ui/lint/unused/issue-92751.rs
new file mode 100644
index 000000000..2fb292736
--- /dev/null
+++ b/tests/ui/lint/unused/issue-92751.rs
@@ -0,0 +1,9 @@
+#[deny(unused)]
+pub fn broken(x: Option<()>) -> i32 {
+ match x {
+ Some(()) => (1), //~ ERROR unnecessary parentheses around match arm expression
+ None => (2), //~ ERROR unnecessary parentheses around match arm expression
+ }
+}
+
+fn main() { }
diff --git a/tests/ui/lint/unused/issue-92751.stderr b/tests/ui/lint/unused/issue-92751.stderr
new file mode 100644
index 000000000..0a8d8e672
--- /dev/null
+++ b/tests/ui/lint/unused/issue-92751.stderr
@@ -0,0 +1,32 @@
+error: unnecessary parentheses around match arm expression
+ --> $DIR/issue-92751.rs:4:21
+ |
+LL | Some(()) => (1),
+ | ^ ^
+ |
+note: the lint level is defined here
+ --> $DIR/issue-92751.rs:1:8
+ |
+LL | #[deny(unused)]
+ | ^^^^^^
+ = note: `#[deny(unused_parens)]` implied by `#[deny(unused)]`
+help: remove these parentheses
+ |
+LL - Some(()) => (1),
+LL + Some(()) => 1,
+ |
+
+error: unnecessary parentheses around match arm expression
+ --> $DIR/issue-92751.rs:5:17
+ |
+LL | None => (2),
+ | ^ ^
+ |
+help: remove these parentheses
+ |
+LL - None => (2),
+LL + None => 2,
+ |
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/lint/unused/lint-unused-extern-crate.rs b/tests/ui/lint/unused/lint-unused-extern-crate.rs
new file mode 100644
index 000000000..d5e4da526
--- /dev/null
+++ b/tests/ui/lint/unused/lint-unused-extern-crate.rs
@@ -0,0 +1,35 @@
+// aux-build:lint_unused_extern_crate.rs
+// aux-build:lint_unused_extern_crate2.rs
+// aux-build:lint_unused_extern_crate3.rs
+// aux-build:lint_unused_extern_crate4.rs
+// aux-build:lint_unused_extern_crate5.rs
+
+#![deny(unused_extern_crates)]
+#![allow(unused_variables)]
+#![allow(deprecated)]
+
+extern crate lint_unused_extern_crate5; //~ ERROR: unused extern crate
+
+pub extern crate lint_unused_extern_crate4; // no error, it is re-exported
+
+extern crate lint_unused_extern_crate3; // no error, it is used
+
+extern crate lint_unused_extern_crate2; // no error, the use marks it as used
+ // even if imported objects aren't used
+
+extern crate lint_unused_extern_crate as other; // no error, the use * marks it as used
+
+#[allow(unused_imports)]
+use lint_unused_extern_crate2::foo as bar;
+
+use other::*;
+
+mod foo {
+ // Test that this is unused even though an earlier `extern crate` is used.
+ extern crate lint_unused_extern_crate2; //~ ERROR unused extern crate
+}
+
+fn main() {
+ lint_unused_extern_crate3::foo();
+ let y = foo();
+}
diff --git a/tests/ui/lint/unused/lint-unused-extern-crate.stderr b/tests/ui/lint/unused/lint-unused-extern-crate.stderr
new file mode 100644
index 000000000..46d8f3bee
--- /dev/null
+++ b/tests/ui/lint/unused/lint-unused-extern-crate.stderr
@@ -0,0 +1,20 @@
+error: unused extern crate
+ --> $DIR/lint-unused-extern-crate.rs:11:1
+ |
+LL | extern crate lint_unused_extern_crate5;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
+ |
+note: the lint level is defined here
+ --> $DIR/lint-unused-extern-crate.rs:7:9
+ |
+LL | #![deny(unused_extern_crates)]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: unused extern crate
+ --> $DIR/lint-unused-extern-crate.rs:29:5
+ |
+LL | extern crate lint_unused_extern_crate2;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/lint/unused/lint-unused-imports.rs b/tests/ui/lint/unused/lint-unused-imports.rs
new file mode 100644
index 000000000..4754d8880
--- /dev/null
+++ b/tests/ui/lint/unused/lint-unused-imports.rs
@@ -0,0 +1,90 @@
+#![deny(unused_imports)]
+#![allow(dead_code)]
+
+use bar::c::cc as cal;
+
+use std::mem::*; // shouldn't get errors for not using
+ // everything imported
+use std::fmt::{};
+//~^ ERROR unused import: `std::fmt::{}`
+
+// Should get errors for both 'Some' and 'None'
+use std::option::Option::{Some, None};
+//~^ ERROR unused imports: `None`, `Some`
+
+use test::A; //~ ERROR unused import: `test::A`
+// Be sure that if we just bring some methods into scope that they're also
+// counted as being used.
+use test::B;
+// But only when actually used: do not get confused by the method with the same name.
+use test::B2; //~ ERROR unused import: `test::B2`
+
+// Make sure this import is warned about when at least one of its imported names
+// is unused
+use test2::{foo, bar}; //~ ERROR unused import: `bar`
+
+mod test2 {
+ pub fn foo() {}
+ pub fn bar() {}
+}
+
+mod test {
+ pub trait A { fn a(&self) {} }
+ pub trait B { fn b(&self) {} }
+ pub trait B2 { fn b(&self) {} }
+ pub struct C;
+ impl A for C {}
+ impl B for C {}
+}
+
+mod foo {
+ pub struct Point{pub x: isize, pub y: isize}
+ pub struct Square{pub p: Point, pub h: usize, pub w: usize}
+}
+
+mod bar {
+ // Don't ignore on 'pub use' because we're not sure if it's used or not
+ pub use std::cmp::PartialEq;
+ pub struct Square;
+
+ pub mod c {
+ use foo::Point;
+ use foo::Square; //~ ERROR unused import: `foo::Square`
+ pub fn cc(_p: Point) -> super::Square {
+ fn f() -> super::Square {
+ super::Square
+ }
+ f()
+ }
+ }
+
+ #[allow(unused_imports)]
+ mod foo {
+ use std::cmp::PartialEq;
+ }
+}
+
+fn g() {
+ use self::g; //~ ERROR unused import: `self::g`
+ //~^ ERROR the item `g` is imported redundantly
+ fn f() {
+ self::g();
+ }
+}
+
+// cf. issue #35135.
+#[allow(unused_variables)]
+fn h() {
+ use test2::foo; //~ ERROR unused import: `test2::foo`
+ //~^ ERROR the item `foo` is imported redundantly
+ let foo = 0;
+}
+
+fn main() {
+ cal(foo::Point{x:3, y:9});
+ let mut a = 3;
+ let mut b = 4;
+ swap(&mut a, &mut b);
+ test::C.b();
+ let _a = foo();
+}
diff --git a/tests/ui/lint/unused/lint-unused-imports.stderr b/tests/ui/lint/unused/lint-unused-imports.stderr
new file mode 100644
index 000000000..0574ca456
--- /dev/null
+++ b/tests/ui/lint/unused/lint-unused-imports.stderr
@@ -0,0 +1,78 @@
+error: unused import: `std::fmt::{}`
+ --> $DIR/lint-unused-imports.rs:8:5
+ |
+LL | use std::fmt::{};
+ | ^^^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/lint-unused-imports.rs:1:9
+ |
+LL | #![deny(unused_imports)]
+ | ^^^^^^^^^^^^^^
+
+error: unused imports: `None`, `Some`
+ --> $DIR/lint-unused-imports.rs:12:27
+ |
+LL | use std::option::Option::{Some, None};
+ | ^^^^ ^^^^
+
+error: unused import: `test::A`
+ --> $DIR/lint-unused-imports.rs:15:5
+ |
+LL | use test::A;
+ | ^^^^^^^
+
+error: unused import: `bar`
+ --> $DIR/lint-unused-imports.rs:24:18
+ |
+LL | use test2::{foo, bar};
+ | ^^^
+
+error: unused import: `foo::Square`
+ --> $DIR/lint-unused-imports.rs:52:13
+ |
+LL | use foo::Square;
+ | ^^^^^^^^^^^
+
+error: the item `g` is imported redundantly
+ --> $DIR/lint-unused-imports.rs:68:9
+ |
+LL | / fn g() {
+LL | | use self::g;
+ | | ^^^^^^^
+LL | |
+LL | | fn f() {
+LL | | self::g();
+LL | | }
+LL | | }
+ | |_- the item `g` is already defined here
+
+error: unused import: `self::g`
+ --> $DIR/lint-unused-imports.rs:68:9
+ |
+LL | use self::g;
+ | ^^^^^^^
+
+error: the item `foo` is imported redundantly
+ --> $DIR/lint-unused-imports.rs:78:9
+ |
+LL | use test2::{foo, bar};
+ | --- the item `foo` is already imported here
+...
+LL | use test2::foo;
+ | ^^^^^^^^^^
+
+error: unused import: `test2::foo`
+ --> $DIR/lint-unused-imports.rs:78:9
+ |
+LL | use test2::foo;
+ | ^^^^^^^^^^
+
+error: unused import: `test::B2`
+ --> $DIR/lint-unused-imports.rs:20:5
+ |
+LL | use test::B2;
+ | ^^^^^^^^
+
+error: aborting due to 10 previous errors
+
diff --git a/tests/ui/lint/unused/lint-unused-mut-self.fixed b/tests/ui/lint/unused/lint-unused-mut-self.fixed
new file mode 100644
index 000000000..92ce10358
--- /dev/null
+++ b/tests/ui/lint/unused/lint-unused-mut-self.fixed
@@ -0,0 +1,14 @@
+// run-rustfix
+
+#![allow(unused_assignments)]
+#![allow(unused_variables)]
+#![allow(dead_code)]
+#![deny(unused_mut)]
+
+struct Foo;
+impl Foo {
+ fn foo(self) {} //~ ERROR: variable does not need to be mutable
+ fn bar(self: Box<Foo>) {} //~ ERROR: variable does not need to be mutable
+}
+
+fn main() {}
diff --git a/tests/ui/lint/unused/lint-unused-mut-self.rs b/tests/ui/lint/unused/lint-unused-mut-self.rs
new file mode 100644
index 000000000..70736ce21
--- /dev/null
+++ b/tests/ui/lint/unused/lint-unused-mut-self.rs
@@ -0,0 +1,14 @@
+// run-rustfix
+
+#![allow(unused_assignments)]
+#![allow(unused_variables)]
+#![allow(dead_code)]
+#![deny(unused_mut)]
+
+struct Foo;
+impl Foo {
+ fn foo(mut self) {} //~ ERROR: variable does not need to be mutable
+ fn bar(mut self: Box<Foo>) {} //~ ERROR: variable does not need to be mutable
+}
+
+fn main() {}
diff --git a/tests/ui/lint/unused/lint-unused-mut-self.stderr b/tests/ui/lint/unused/lint-unused-mut-self.stderr
new file mode 100644
index 000000000..01a524bd3
--- /dev/null
+++ b/tests/ui/lint/unused/lint-unused-mut-self.stderr
@@ -0,0 +1,24 @@
+error: variable does not need to be mutable
+ --> $DIR/lint-unused-mut-self.rs:10:12
+ |
+LL | fn foo(mut self) {}
+ | ----^^^^
+ | |
+ | help: remove this `mut`
+ |
+note: the lint level is defined here
+ --> $DIR/lint-unused-mut-self.rs:6:9
+ |
+LL | #![deny(unused_mut)]
+ | ^^^^^^^^^^
+
+error: variable does not need to be mutable
+ --> $DIR/lint-unused-mut-self.rs:11:12
+ |
+LL | fn bar(mut self: Box<Foo>) {}
+ | ----^^^^
+ | |
+ | help: remove this `mut`
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/lint/unused/lint-unused-mut-variables.rs b/tests/ui/lint/unused/lint-unused-mut-variables.rs
new file mode 100644
index 000000000..67ec7facf
--- /dev/null
+++ b/tests/ui/lint/unused/lint-unused-mut-variables.rs
@@ -0,0 +1,207 @@
+// edition:2018
+
+// Exercise the unused_mut attribute in some positive and negative cases
+
+#![warn(unused_mut)]
+#![feature(async_closure, raw_ref_op)]
+
+async fn baz_async(
+ mut a: i32,
+ //~^ WARN: variable does not need to be mutable
+ #[allow(unused_mut)] mut b: i32,
+) {}
+fn baz(
+ mut a: i32,
+ //~^ WARN: variable does not need to be mutable
+ #[allow(unused_mut)] mut b: i32,
+ #[allow(unused_mut)] (mut c, d): (i32, i32)
+) {}
+
+struct RefStruct {}
+impl RefStruct {
+ async fn baz_async(
+ mut a: i32,
+ //~^ WARN: variable does not need to be mutable
+ #[allow(unused_mut)] mut b: i32,
+ ) {}
+ fn baz(
+ &self,
+ mut a: i32,
+ //~^ WARN: variable does not need to be mutable
+ #[allow(unused_mut)] mut b: i32,
+ #[allow(unused_mut)] (mut c, d): (i32, i32)
+ ) {}
+}
+
+trait RefTrait {
+ fn baz(
+ &self,
+ mut a: i32,
+ //~^ WARN: variable does not need to be mutable
+ #[allow(unused_mut)] mut b: i32,
+ #[allow(unused_mut)] (mut c, d): (i32, i32)
+ ) {}
+}
+impl RefTrait for () {
+ fn baz(
+ &self,
+ mut a: i32,
+ //~^ WARN: variable does not need to be mutable
+ #[allow(unused_mut)] mut b: i32,
+ #[allow(unused_mut)] (mut c, d): (i32, i32)
+ ) {}
+}
+
+fn main() {
+ let _ = async move |
+ mut a: i32,
+ //~^ WARN: variable does not need to be mutable
+ #[allow(unused_mut)] mut b: i32,
+ | {};
+ let _ = |
+ mut a: i32,
+ //~^ WARN: variable does not need to be mutable
+ #[allow(unused_mut)] mut b: i32,
+ #[allow(unused_mut)] (mut c, d): (i32, i32)
+ | {};
+
+ // negative cases
+ let mut a = 3; //~ WARN: variable does not need to be mutable
+
+ let mut a = 2; //~ WARN: variable does not need to be mutable
+
+ let mut b = 3; //~ WARN: variable does not need to be mutable
+
+ let mut a = vec![3]; //~ WARN: variable does not need to be mutable
+
+ let (mut a, b) = (1, 2); //~ WARN: variable does not need to be mutable
+
+ let mut a; //~ WARN: variable does not need to be mutable
+
+ a = 3;
+
+ let mut b; //~ WARN: variable does not need to be mutable
+
+ if true {
+ b = 3;
+ } else {
+ b = 4;
+ }
+
+ match 30 {
+ mut x => {} //~ WARN: variable does not need to be mutable
+
+ }
+
+ match (30, 2) {
+ // FIXME: Here's a false positive,
+ // shouldn't be removed `mut` not to be bound with a different way.
+ (mut x, 1) | //~ WARN: variable does not need to be mutable
+
+ (mut x, 2) |
+ (mut x, 3) => {
+ }
+ _ => {}
+ }
+
+ let x = |mut y: isize| 10; //~ WARN: variable does not need to be mutable
+
+ fn what(mut foo: isize) {} //~ WARN: variable does not need to be mutable
+
+
+ let mut a = &mut 5; //~ WARN: variable does not need to be mutable
+
+ *a = 4;
+
+ let mut a = 5;
+ let mut b = (&mut a,); //~ WARN: variable does not need to be mutable
+ *b.0 = 4;
+
+ let mut x = &mut 1; //~ WARN: variable does not need to be mutable
+
+ let mut f = || {
+ *x += 1;
+ };
+ f();
+
+ fn mut_ref_arg(mut arg : &mut [u8]) -> &mut [u8] {
+ &mut arg[..] //~^ WARN: variable does not need to be mutable
+
+ }
+
+ let mut v : &mut Vec<()> = &mut vec![]; //~ WARN: variable does not need to be mutable
+
+ v.push(());
+
+ // positive cases
+ let mut a = 2;
+ a = 3;
+ let mut a = Vec::new();
+ a.push(3);
+ let mut a = Vec::new();
+ callback(|| {
+ a.push(3);
+ });
+ let mut a = Vec::new();
+ callback(|| {
+ callback(|| {
+ a.push(3);
+ });
+ });
+ let (mut a, b) = (1, 2);
+ a = 34;
+
+ match 30 {
+ mut x => {
+ x = 21;
+ }
+ }
+
+ match (30, 2) {
+ (mut x, 1) |
+ (mut x, 2) |
+ (mut x, 3) => {
+ x = 21
+ }
+ _ => {}
+ }
+
+ // Attribute should be respected on match arms
+ match 0 {
+ #[allow(unused_mut)]
+ mut x => {
+ let mut y = 1;
+ },
+ }
+
+ let x = |mut y: isize| y = 32;
+ fn nothing(mut foo: isize) { foo = 37; }
+
+ // leading underscore should avoid the warning, just like the
+ // unused variable lint.
+ let mut _allowed = 1;
+
+ let mut raw_address_of_mut = 1; // OK
+ let mut_ptr = &raw mut raw_address_of_mut;
+
+ let mut raw_address_of_const = 1; //~ WARN: variable does not need to be mutable
+ let const_ptr = &raw const raw_address_of_const;
+}
+
+fn callback<F>(f: F) where F: FnOnce() {}
+
+// make sure the lint attribute can be turned off
+#[allow(unused_mut)]
+fn foo(mut a: isize) {
+ let mut a = 3;
+ let mut b = vec![2];
+}
+
+// make sure the lint attribute can be turned off on let statements
+#[deny(unused_mut)]
+fn bar() {
+ #[allow(unused_mut)]
+ let mut a = 3;
+ let mut b = vec![2]; //~ ERROR: variable does not need to be mutable
+
+}
diff --git a/tests/ui/lint/unused/lint-unused-mut-variables.stderr b/tests/ui/lint/unused/lint-unused-mut-variables.stderr
new file mode 100644
index 000000000..805ed2b40
--- /dev/null
+++ b/tests/ui/lint/unused/lint-unused-mut-variables.stderr
@@ -0,0 +1,222 @@
+warning: variable does not need to be mutable
+ --> $DIR/lint-unused-mut-variables.rs:9:5
+ |
+LL | mut a: i32,
+ | ----^
+ | |
+ | help: remove this `mut`
+ |
+note: the lint level is defined here
+ --> $DIR/lint-unused-mut-variables.rs:5:9
+ |
+LL | #![warn(unused_mut)]
+ | ^^^^^^^^^^
+
+warning: variable does not need to be mutable
+ --> $DIR/lint-unused-mut-variables.rs:23:9
+ |
+LL | mut a: i32,
+ | ----^
+ | |
+ | help: remove this `mut`
+
+warning: variable does not need to be mutable
+ --> $DIR/lint-unused-mut-variables.rs:14:5
+ |
+LL | mut a: i32,
+ | ----^
+ | |
+ | help: remove this `mut`
+
+warning: variable does not need to be mutable
+ --> $DIR/lint-unused-mut-variables.rs:29:9
+ |
+LL | mut a: i32,
+ | ----^
+ | |
+ | help: remove this `mut`
+
+warning: variable does not need to be mutable
+ --> $DIR/lint-unused-mut-variables.rs:39:9
+ |
+LL | mut a: i32,
+ | ----^
+ | |
+ | help: remove this `mut`
+
+warning: variable does not need to be mutable
+ --> $DIR/lint-unused-mut-variables.rs:48:9
+ |
+LL | mut a: i32,
+ | ----^
+ | |
+ | help: remove this `mut`
+
+warning: variable does not need to be mutable
+ --> $DIR/lint-unused-mut-variables.rs:57:9
+ |
+LL | mut a: i32,
+ | ----^
+ | |
+ | help: remove this `mut`
+
+warning: variable does not need to be mutable
+ --> $DIR/lint-unused-mut-variables.rs:62:9
+ |
+LL | mut a: i32,
+ | ----^
+ | |
+ | help: remove this `mut`
+
+warning: variable does not need to be mutable
+ --> $DIR/lint-unused-mut-variables.rs:107:14
+ |
+LL | let x = |mut y: isize| 10;
+ | ----^
+ | |
+ | help: remove this `mut`
+
+warning: variable does not need to be mutable
+ --> $DIR/lint-unused-mut-variables.rs:69:9
+ |
+LL | let mut a = 3;
+ | ----^
+ | |
+ | help: remove this `mut`
+
+warning: variable does not need to be mutable
+ --> $DIR/lint-unused-mut-variables.rs:71:9
+ |
+LL | let mut a = 2;
+ | ----^
+ | |
+ | help: remove this `mut`
+
+warning: variable does not need to be mutable
+ --> $DIR/lint-unused-mut-variables.rs:73:9
+ |
+LL | let mut b = 3;
+ | ----^
+ | |
+ | help: remove this `mut`
+
+warning: variable does not need to be mutable
+ --> $DIR/lint-unused-mut-variables.rs:75:9
+ |
+LL | let mut a = vec![3];
+ | ----^
+ | |
+ | help: remove this `mut`
+
+warning: variable does not need to be mutable
+ --> $DIR/lint-unused-mut-variables.rs:77:10
+ |
+LL | let (mut a, b) = (1, 2);
+ | ----^
+ | |
+ | help: remove this `mut`
+
+warning: variable does not need to be mutable
+ --> $DIR/lint-unused-mut-variables.rs:79:9
+ |
+LL | let mut a;
+ | ----^
+ | |
+ | help: remove this `mut`
+
+warning: variable does not need to be mutable
+ --> $DIR/lint-unused-mut-variables.rs:83:9
+ |
+LL | let mut b;
+ | ----^
+ | |
+ | help: remove this `mut`
+
+warning: variable does not need to be mutable
+ --> $DIR/lint-unused-mut-variables.rs:92:9
+ |
+LL | mut x => {}
+ | ----^
+ | |
+ | help: remove this `mut`
+
+warning: variable does not need to be mutable
+ --> $DIR/lint-unused-mut-variables.rs:99:10
+ |
+LL | (mut x, 1) |
+ | ----^
+ | |
+ | help: remove this `mut`
+
+warning: variable does not need to be mutable
+ --> $DIR/lint-unused-mut-variables.rs:112:9
+ |
+LL | let mut a = &mut 5;
+ | ----^
+ | |
+ | help: remove this `mut`
+
+warning: variable does not need to be mutable
+ --> $DIR/lint-unused-mut-variables.rs:117:9
+ |
+LL | let mut b = (&mut a,);
+ | ----^
+ | |
+ | help: remove this `mut`
+
+warning: variable does not need to be mutable
+ --> $DIR/lint-unused-mut-variables.rs:120:9
+ |
+LL | let mut x = &mut 1;
+ | ----^
+ | |
+ | help: remove this `mut`
+
+warning: variable does not need to be mutable
+ --> $DIR/lint-unused-mut-variables.rs:132:9
+ |
+LL | let mut v : &mut Vec<()> = &mut vec![];
+ | ----^
+ | |
+ | help: remove this `mut`
+
+warning: variable does not need to be mutable
+ --> $DIR/lint-unused-mut-variables.rs:187:9
+ |
+LL | let mut raw_address_of_const = 1;
+ | ----^^^^^^^^^^^^^^^^^^^^
+ | |
+ | help: remove this `mut`
+
+warning: variable does not need to be mutable
+ --> $DIR/lint-unused-mut-variables.rs:109:13
+ |
+LL | fn what(mut foo: isize) {}
+ | ----^^^
+ | |
+ | help: remove this `mut`
+
+warning: variable does not need to be mutable
+ --> $DIR/lint-unused-mut-variables.rs:127:20
+ |
+LL | fn mut_ref_arg(mut arg : &mut [u8]) -> &mut [u8] {
+ | ----^^^
+ | |
+ | help: remove this `mut`
+
+error: variable does not need to be mutable
+ --> $DIR/lint-unused-mut-variables.rs:205:9
+ |
+LL | let mut b = vec![2];
+ | ----^
+ | |
+ | help: remove this `mut`
+ |
+note: the lint level is defined here
+ --> $DIR/lint-unused-mut-variables.rs:201:8
+ |
+LL | #[deny(unused_mut)]
+ | ^^^^^^^^^^
+
+error: aborting due to previous error; 25 warnings emitted
+
diff --git a/tests/ui/lint/unused/lint-unused-variables.rs b/tests/ui/lint/unused/lint-unused-variables.rs
new file mode 100644
index 000000000..6850e9992
--- /dev/null
+++ b/tests/ui/lint/unused/lint-unused-variables.rs
@@ -0,0 +1,79 @@
+// compile-flags: --cfg something
+// edition:2018
+
+#![feature(async_closure)]
+#![deny(unused_variables)]
+
+async fn foo_async(
+ a: i32,
+ //~^ ERROR unused variable: `a`
+ #[allow(unused_variables)] b: i32,
+) {}
+fn foo(
+ #[allow(unused_variables)] a: i32,
+ b: i32,
+ //~^ ERROR unused variable: `b`
+) {}
+
+struct RefStruct {}
+impl RefStruct {
+ async fn bar_async(
+ &self,
+ a: i32,
+ //~^ ERROR unused variable: `a`
+ #[allow(unused_variables)] b: i32,
+ ) {}
+ fn bar(
+ &self,
+ #[allow(unused_variables)] a: i32,
+ b: i32,
+ //~^ ERROR unused variable: `b`
+ ) {}
+ fn issue_64682_associated_fn(
+ #[allow(unused_variables)] a: i32,
+ b: i32,
+ //~^ ERROR unused variable: `b`
+ ) {}
+}
+trait RefTrait {
+ fn bar(
+ &self,
+ #[allow(unused_variables)] a: i32,
+ b: i32,
+ //~^ ERROR unused variable: `b`
+ ) {}
+ fn issue_64682_associated_fn(
+ #[allow(unused_variables)] a: i32,
+ b: i32,
+ //~^ ERROR unused variable: `b`
+ ) {}
+}
+impl RefTrait for RefStruct {
+ fn bar(
+ &self,
+ #[allow(unused_variables)] a: i32,
+ b: i32,
+ //~^ ERROR unused variable: `b`
+ ) {}
+ fn issue_64682_associated_fn(
+ #[allow(unused_variables)] a: i32,
+ b: i32,
+ //~^ ERROR unused variable: `b`
+ ) {}
+}
+
+fn main() {
+ let _: fn(_, _) = foo;
+ let a = async move |
+ a: i32,
+ //~^ ERROR unused variable: `a`
+ #[allow(unused_variables)] b: i32,
+ | {};
+ let b = |
+ #[allow(unused_variables)] a: i32,
+ b: i32,
+ //~^ ERROR unused variable: `b`
+ | {};
+ let _ = a(1, 2);
+ let _ = b(1, 2);
+}
diff --git a/tests/ui/lint/unused/lint-unused-variables.stderr b/tests/ui/lint/unused/lint-unused-variables.stderr
new file mode 100644
index 000000000..fd9a5bcbf
--- /dev/null
+++ b/tests/ui/lint/unused/lint-unused-variables.stderr
@@ -0,0 +1,74 @@
+error: unused variable: `a`
+ --> $DIR/lint-unused-variables.rs:8:5
+ |
+LL | a: i32,
+ | ^ help: if this is intentional, prefix it with an underscore: `_a`
+ |
+note: the lint level is defined here
+ --> $DIR/lint-unused-variables.rs:5:9
+ |
+LL | #![deny(unused_variables)]
+ | ^^^^^^^^^^^^^^^^
+
+error: unused variable: `b`
+ --> $DIR/lint-unused-variables.rs:14:5
+ |
+LL | b: i32,
+ | ^ help: if this is intentional, prefix it with an underscore: `_b`
+
+error: unused variable: `a`
+ --> $DIR/lint-unused-variables.rs:22:9
+ |
+LL | a: i32,
+ | ^ help: if this is intentional, prefix it with an underscore: `_a`
+
+error: unused variable: `b`
+ --> $DIR/lint-unused-variables.rs:29:9
+ |
+LL | b: i32,
+ | ^ help: if this is intentional, prefix it with an underscore: `_b`
+
+error: unused variable: `b`
+ --> $DIR/lint-unused-variables.rs:34:9
+ |
+LL | b: i32,
+ | ^ help: if this is intentional, prefix it with an underscore: `_b`
+
+error: unused variable: `b`
+ --> $DIR/lint-unused-variables.rs:42:9
+ |
+LL | b: i32,
+ | ^ help: if this is intentional, prefix it with an underscore: `_b`
+
+error: unused variable: `b`
+ --> $DIR/lint-unused-variables.rs:47:9
+ |
+LL | b: i32,
+ | ^ help: if this is intentional, prefix it with an underscore: `_b`
+
+error: unused variable: `b`
+ --> $DIR/lint-unused-variables.rs:55:9
+ |
+LL | b: i32,
+ | ^ help: if this is intentional, prefix it with an underscore: `_b`
+
+error: unused variable: `b`
+ --> $DIR/lint-unused-variables.rs:60:9
+ |
+LL | b: i32,
+ | ^ help: if this is intentional, prefix it with an underscore: `_b`
+
+error: unused variable: `a`
+ --> $DIR/lint-unused-variables.rs:68:9
+ |
+LL | a: i32,
+ | ^ help: if this is intentional, prefix it with an underscore: `_a`
+
+error: unused variable: `b`
+ --> $DIR/lint-unused-variables.rs:74:9
+ |
+LL | b: i32,
+ | ^ help: if this is intentional, prefix it with an underscore: `_b`
+
+error: aborting due to 11 previous errors
+
diff --git a/tests/ui/lint/unused/must-use-box-from-raw.rs b/tests/ui/lint/unused/must-use-box-from-raw.rs
new file mode 100644
index 000000000..9ea772689
--- /dev/null
+++ b/tests/ui/lint/unused/must-use-box-from-raw.rs
@@ -0,0 +1,11 @@
+// #99269
+
+// check-pass
+
+#![warn(unused_must_use)]
+
+unsafe fn free<T>(ptr: *mut T) {
+ Box::from_raw(ptr); //~ WARNING unused return value
+}
+
+fn main() {}
diff --git a/tests/ui/lint/unused/must-use-box-from-raw.stderr b/tests/ui/lint/unused/must-use-box-from-raw.stderr
new file mode 100644
index 000000000..47ab613be
--- /dev/null
+++ b/tests/ui/lint/unused/must-use-box-from-raw.stderr
@@ -0,0 +1,15 @@
+warning: unused return value of `Box::<T>::from_raw` that must be used
+ --> $DIR/must-use-box-from-raw.rs:8:5
+ |
+LL | Box::from_raw(ptr);
+ | ^^^^^^^^^^^^^^^^^^
+ |
+ = note: call `drop(Box::from_raw(ptr))` if you intend to drop the `Box`
+note: the lint level is defined here
+ --> $DIR/must-use-box-from-raw.rs:5:9
+ |
+LL | #![warn(unused_must_use)]
+ | ^^^^^^^^^^^^^^^
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/lint/unused/must-use-ops.rs b/tests/ui/lint/unused/must-use-ops.rs
new file mode 100644
index 000000000..60f877aa8
--- /dev/null
+++ b/tests/ui/lint/unused/must-use-ops.rs
@@ -0,0 +1,51 @@
+// Issue #50124 - Test warning for unused operator expressions
+
+// check-pass
+
+#![warn(unused_must_use)]
+#![feature(never_type)]
+
+fn deref_never(x: &!) {
+ // Don't lint for uninhabited typess
+ *x;
+}
+
+fn main() {
+ let val = 1;
+ let val_pointer = &val;
+
+ // Comparison Operators
+ val == 1; //~ WARNING unused comparison
+ val < 1; //~ WARNING unused comparison
+ val <= 1; //~ WARNING unused comparison
+ val != 1; //~ WARNING unused comparison
+ val >= 1; //~ WARNING unused comparison
+ val > 1; //~ WARNING unused comparison
+
+ // Arithmetic Operators
+ val + 2; //~ WARNING unused arithmetic operation
+ val - 2; //~ WARNING unused arithmetic operation
+ val / 2; //~ WARNING unused arithmetic operation
+ val * 2; //~ WARNING unused arithmetic operation
+ val % 2; //~ WARNING unused arithmetic operation
+
+ // Logical Operators
+ true && true; //~ WARNING unused logical operation
+ false || true; //~ WARNING unused logical operation
+
+ // Bitwise Operators
+ 5 ^ val; //~ WARNING unused bitwise operation
+ 5 & val; //~ WARNING unused bitwise operation
+ 5 | val; //~ WARNING unused bitwise operation
+ 5 << val; //~ WARNING unused bitwise operation
+ 5 >> val; //~ WARNING unused bitwise operation
+
+ // Unary Operators
+ !val; //~ WARNING unused unary operation
+ -val; //~ WARNING unused unary operation
+ *val_pointer; //~ WARNING unused unary operation
+
+ if false {
+ deref_never(&panic!());
+ }
+}
diff --git a/tests/ui/lint/unused/must-use-ops.stderr b/tests/ui/lint/unused/must-use-ops.stderr
new file mode 100644
index 000000000..79a53d39c
--- /dev/null
+++ b/tests/ui/lint/unused/must-use-ops.stderr
@@ -0,0 +1,238 @@
+warning: unused comparison that must be used
+ --> $DIR/must-use-ops.rs:18:5
+ |
+LL | val == 1;
+ | ^^^^^^^^ the comparison produces a value
+ |
+note: the lint level is defined here
+ --> $DIR/must-use-ops.rs:5:9
+ |
+LL | #![warn(unused_must_use)]
+ | ^^^^^^^^^^^^^^^
+help: use `let _ = ...` to ignore the resulting value
+ |
+LL | let _ = val == 1;
+ | +++++++
+
+warning: unused comparison that must be used
+ --> $DIR/must-use-ops.rs:19:5
+ |
+LL | val < 1;
+ | ^^^^^^^ the comparison produces a value
+ |
+help: use `let _ = ...` to ignore the resulting value
+ |
+LL | let _ = val < 1;
+ | +++++++
+
+warning: unused comparison that must be used
+ --> $DIR/must-use-ops.rs:20:5
+ |
+LL | val <= 1;
+ | ^^^^^^^^ the comparison produces a value
+ |
+help: use `let _ = ...` to ignore the resulting value
+ |
+LL | let _ = val <= 1;
+ | +++++++
+
+warning: unused comparison that must be used
+ --> $DIR/must-use-ops.rs:21:5
+ |
+LL | val != 1;
+ | ^^^^^^^^ the comparison produces a value
+ |
+help: use `let _ = ...` to ignore the resulting value
+ |
+LL | let _ = val != 1;
+ | +++++++
+
+warning: unused comparison that must be used
+ --> $DIR/must-use-ops.rs:22:5
+ |
+LL | val >= 1;
+ | ^^^^^^^^ the comparison produces a value
+ |
+help: use `let _ = ...` to ignore the resulting value
+ |
+LL | let _ = val >= 1;
+ | +++++++
+
+warning: unused comparison that must be used
+ --> $DIR/must-use-ops.rs:23:5
+ |
+LL | val > 1;
+ | ^^^^^^^ the comparison produces a value
+ |
+help: use `let _ = ...` to ignore the resulting value
+ |
+LL | let _ = val > 1;
+ | +++++++
+
+warning: unused arithmetic operation that must be used
+ --> $DIR/must-use-ops.rs:26:5
+ |
+LL | val + 2;
+ | ^^^^^^^ the arithmetic operation produces a value
+ |
+help: use `let _ = ...` to ignore the resulting value
+ |
+LL | let _ = val + 2;
+ | +++++++
+
+warning: unused arithmetic operation that must be used
+ --> $DIR/must-use-ops.rs:27:5
+ |
+LL | val - 2;
+ | ^^^^^^^ the arithmetic operation produces a value
+ |
+help: use `let _ = ...` to ignore the resulting value
+ |
+LL | let _ = val - 2;
+ | +++++++
+
+warning: unused arithmetic operation that must be used
+ --> $DIR/must-use-ops.rs:28:5
+ |
+LL | val / 2;
+ | ^^^^^^^ the arithmetic operation produces a value
+ |
+help: use `let _ = ...` to ignore the resulting value
+ |
+LL | let _ = val / 2;
+ | +++++++
+
+warning: unused arithmetic operation that must be used
+ --> $DIR/must-use-ops.rs:29:5
+ |
+LL | val * 2;
+ | ^^^^^^^ the arithmetic operation produces a value
+ |
+help: use `let _ = ...` to ignore the resulting value
+ |
+LL | let _ = val * 2;
+ | +++++++
+
+warning: unused arithmetic operation that must be used
+ --> $DIR/must-use-ops.rs:30:5
+ |
+LL | val % 2;
+ | ^^^^^^^ the arithmetic operation produces a value
+ |
+help: use `let _ = ...` to ignore the resulting value
+ |
+LL | let _ = val % 2;
+ | +++++++
+
+warning: unused logical operation that must be used
+ --> $DIR/must-use-ops.rs:33:5
+ |
+LL | true && true;
+ | ^^^^^^^^^^^^ the logical operation produces a value
+ |
+help: use `let _ = ...` to ignore the resulting value
+ |
+LL | let _ = true && true;
+ | +++++++
+
+warning: unused logical operation that must be used
+ --> $DIR/must-use-ops.rs:34:5
+ |
+LL | false || true;
+ | ^^^^^^^^^^^^^ the logical operation produces a value
+ |
+help: use `let _ = ...` to ignore the resulting value
+ |
+LL | let _ = false || true;
+ | +++++++
+
+warning: unused bitwise operation that must be used
+ --> $DIR/must-use-ops.rs:37:5
+ |
+LL | 5 ^ val;
+ | ^^^^^^^ the bitwise operation produces a value
+ |
+help: use `let _ = ...` to ignore the resulting value
+ |
+LL | let _ = 5 ^ val;
+ | +++++++
+
+warning: unused bitwise operation that must be used
+ --> $DIR/must-use-ops.rs:38:5
+ |
+LL | 5 & val;
+ | ^^^^^^^ the bitwise operation produces a value
+ |
+help: use `let _ = ...` to ignore the resulting value
+ |
+LL | let _ = 5 & val;
+ | +++++++
+
+warning: unused bitwise operation that must be used
+ --> $DIR/must-use-ops.rs:39:5
+ |
+LL | 5 | val;
+ | ^^^^^^^ the bitwise operation produces a value
+ |
+help: use `let _ = ...` to ignore the resulting value
+ |
+LL | let _ = 5 | val;
+ | +++++++
+
+warning: unused bitwise operation that must be used
+ --> $DIR/must-use-ops.rs:40:5
+ |
+LL | 5 << val;
+ | ^^^^^^^^ the bitwise operation produces a value
+ |
+help: use `let _ = ...` to ignore the resulting value
+ |
+LL | let _ = 5 << val;
+ | +++++++
+
+warning: unused bitwise operation that must be used
+ --> $DIR/must-use-ops.rs:41:5
+ |
+LL | 5 >> val;
+ | ^^^^^^^^ the bitwise operation produces a value
+ |
+help: use `let _ = ...` to ignore the resulting value
+ |
+LL | let _ = 5 >> val;
+ | +++++++
+
+warning: unused unary operation that must be used
+ --> $DIR/must-use-ops.rs:44:5
+ |
+LL | !val;
+ | ^^^^ the unary operation produces a value
+ |
+help: use `let _ = ...` to ignore the resulting value
+ |
+LL | let _ = !val;
+ | +++++++
+
+warning: unused unary operation that must be used
+ --> $DIR/must-use-ops.rs:45:5
+ |
+LL | -val;
+ | ^^^^ the unary operation produces a value
+ |
+help: use `let _ = ...` to ignore the resulting value
+ |
+LL | let _ = -val;
+ | +++++++
+
+warning: unused unary operation that must be used
+ --> $DIR/must-use-ops.rs:46:5
+ |
+LL | *val_pointer;
+ | ^^^^^^^^^^^^ the unary operation produces a value
+ |
+help: use `let _ = ...` to ignore the resulting value
+ |
+LL | let _ = *val_pointer;
+ | +++++++
+
+warning: 21 warnings emitted
+
diff --git a/tests/ui/lint/unused/must_use-array.rs b/tests/ui/lint/unused/must_use-array.rs
new file mode 100644
index 000000000..b7bae4b0a
--- /dev/null
+++ b/tests/ui/lint/unused/must_use-array.rs
@@ -0,0 +1,54 @@
+#![deny(unused_must_use)]
+
+#[must_use]
+#[derive(Clone, Copy)]
+struct S;
+
+struct A;
+
+#[must_use]
+trait T {}
+
+impl T for A {}
+
+fn empty() -> [S; 0] {
+ []
+}
+
+fn singleton() -> [S; 1] {
+ [S]
+}
+
+fn many() -> [S; 4] {
+ [S, S, S, S]
+}
+
+fn array_of_impl_trait() -> [impl T; 2] {
+ [A, A]
+}
+
+fn impl_array() -> [(u8, Box<dyn T>); 2] {
+ [(0, Box::new(A)), (0, Box::new(A))]
+}
+
+fn array_of_arrays_of_arrays() -> [[[S; 1]; 2]; 1] {
+ [[[S], [S]]]
+}
+
+fn usize_max() -> [S; usize::MAX] {
+ [S; usize::MAX]
+}
+
+fn main() {
+ empty(); // ok
+ singleton(); //~ ERROR unused array of `S` that must be used
+ many(); //~ ERROR unused array of `S` that must be used
+ ([S], 0, ()); //~ ERROR unused array of `S` in tuple element 0 that must be used
+ array_of_impl_trait(); //~ ERROR unused array of implementers of `T` that must be used
+ impl_array();
+ //~^ ERROR unused array of boxed `T` trait objects in tuple element 1 that must be used
+ array_of_arrays_of_arrays();
+ //~^ ERROR unused array of arrays of arrays of `S` that must be used
+ usize_max();
+ //~^ ERROR unused array of `S` that must be used
+}
diff --git a/tests/ui/lint/unused/must_use-array.stderr b/tests/ui/lint/unused/must_use-array.stderr
new file mode 100644
index 000000000..61ef2088d
--- /dev/null
+++ b/tests/ui/lint/unused/must_use-array.stderr
@@ -0,0 +1,50 @@
+error: unused array of `S` that must be used
+ --> $DIR/must_use-array.rs:44:5
+ |
+LL | singleton();
+ | ^^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/must_use-array.rs:1:9
+ |
+LL | #![deny(unused_must_use)]
+ | ^^^^^^^^^^^^^^^
+
+error: unused array of `S` that must be used
+ --> $DIR/must_use-array.rs:45:5
+ |
+LL | many();
+ | ^^^^^^
+
+error: unused array of `S` in tuple element 0 that must be used
+ --> $DIR/must_use-array.rs:46:6
+ |
+LL | ([S], 0, ());
+ | ^^^
+
+error: unused array of implementers of `T` that must be used
+ --> $DIR/must_use-array.rs:47:5
+ |
+LL | array_of_impl_trait();
+ | ^^^^^^^^^^^^^^^^^^^^^
+
+error: unused array of boxed `T` trait objects in tuple element 1 that must be used
+ --> $DIR/must_use-array.rs:48:5
+ |
+LL | impl_array();
+ | ^^^^^^^^^^^^
+
+error: unused array of arrays of arrays of `S` that must be used
+ --> $DIR/must_use-array.rs:50:5
+ |
+LL | array_of_arrays_of_arrays();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: unused array of `S` that must be used
+ --> $DIR/must_use-array.rs:52:5
+ |
+LL | usize_max();
+ | ^^^^^^^^^^^
+
+error: aborting due to 7 previous errors
+
diff --git a/tests/ui/lint/unused/must_use-in-stdlib-traits.rs b/tests/ui/lint/unused/must_use-in-stdlib-traits.rs
new file mode 100644
index 000000000..70dddf61f
--- /dev/null
+++ b/tests/ui/lint/unused/must_use-in-stdlib-traits.rs
@@ -0,0 +1,47 @@
+#![deny(unused_must_use)]
+#![feature(arbitrary_self_types)]
+
+use std::iter::Iterator;
+use std::future::Future;
+
+use std::task::{Context, Poll};
+use std::pin::Pin;
+use std::unimplemented;
+
+struct MyFuture;
+
+impl Future for MyFuture {
+ type Output = u32;
+
+ fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<u32> {
+ Poll::Pending
+ }
+}
+
+fn iterator() -> impl Iterator {
+ std::iter::empty::<u32>()
+}
+
+fn future() -> impl Future {
+ MyFuture
+}
+
+fn square_fn_once() -> impl FnOnce(u32) -> u32 {
+ |x| x * x
+}
+
+fn square_fn_mut() -> impl FnMut(u32) -> u32 {
+ |x| x * x
+}
+
+fn square_fn() -> impl Fn(u32) -> u32 {
+ |x| x * x
+}
+
+fn main() {
+ iterator(); //~ ERROR unused implementer of `Iterator` that must be used
+ future(); //~ ERROR unused implementer of `Future` that must be used
+ square_fn_once(); //~ ERROR unused implementer of `FnOnce` that must be used
+ square_fn_mut(); //~ ERROR unused implementer of `FnMut` that must be used
+ square_fn(); //~ ERROR unused implementer of `Fn` that must be used
+}
diff --git a/tests/ui/lint/unused/must_use-in-stdlib-traits.stderr b/tests/ui/lint/unused/must_use-in-stdlib-traits.stderr
new file mode 100644
index 000000000..ef738708d
--- /dev/null
+++ b/tests/ui/lint/unused/must_use-in-stdlib-traits.stderr
@@ -0,0 +1,47 @@
+error: unused implementer of `Iterator` that must be used
+ --> $DIR/must_use-in-stdlib-traits.rs:42:4
+ |
+LL | iterator();
+ | ^^^^^^^^^^
+ |
+ = note: iterators are lazy and do nothing unless consumed
+note: the lint level is defined here
+ --> $DIR/must_use-in-stdlib-traits.rs:1:9
+ |
+LL | #![deny(unused_must_use)]
+ | ^^^^^^^^^^^^^^^
+
+error: unused implementer of `Future` that must be used
+ --> $DIR/must_use-in-stdlib-traits.rs:43:4
+ |
+LL | future();
+ | ^^^^^^^^
+ |
+ = note: futures do nothing unless you `.await` or poll them
+
+error: unused implementer of `FnOnce` that must be used
+ --> $DIR/must_use-in-stdlib-traits.rs:44:4
+ |
+LL | square_fn_once();
+ | ^^^^^^^^^^^^^^^^
+ |
+ = note: closures are lazy and do nothing unless called
+
+error: unused implementer of `FnMut` that must be used
+ --> $DIR/must_use-in-stdlib-traits.rs:45:4
+ |
+LL | square_fn_mut();
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: closures are lazy and do nothing unless called
+
+error: unused implementer of `Fn` that must be used
+ --> $DIR/must_use-in-stdlib-traits.rs:46:4
+ |
+LL | square_fn();
+ | ^^^^^^^^^^^
+ |
+ = note: closures are lazy and do nothing unless called
+
+error: aborting due to 5 previous errors
+
diff --git a/tests/ui/lint/unused/must_use-trait.rs b/tests/ui/lint/unused/must_use-trait.rs
new file mode 100644
index 000000000..0aa751443
--- /dev/null
+++ b/tests/ui/lint/unused/must_use-trait.rs
@@ -0,0 +1,39 @@
+#![deny(unused_must_use)]
+
+#[must_use]
+trait Critical {}
+
+trait NotSoCritical {}
+
+trait DecidedlyUnimportant {}
+
+struct Anon;
+
+impl Critical for Anon {}
+impl NotSoCritical for Anon {}
+impl DecidedlyUnimportant for Anon {}
+
+fn get_critical() -> impl NotSoCritical + Critical + DecidedlyUnimportant {
+ Anon {}
+}
+
+fn get_boxed_critical() -> Box<dyn Critical> {
+ Box::new(Anon {})
+}
+
+fn get_nested_boxed_critical() -> Box<Box<dyn Critical>> {
+ Box::new(Box::new(Anon {}))
+}
+
+fn get_critical_tuple() -> (u32, Box<dyn Critical>, impl Critical, ()) {
+ (0, get_boxed_critical(), get_critical(), ())
+}
+
+fn main() {
+ get_critical(); //~ ERROR unused implementer of `Critical` that must be used
+ get_boxed_critical(); //~ ERROR unused boxed `Critical` trait object that must be used
+ get_nested_boxed_critical();
+ //~^ ERROR unused boxed boxed `Critical` trait object that must be used
+ get_critical_tuple(); //~ ERROR unused boxed `Critical` trait object in tuple element 1
+ //~^ ERROR unused implementer of `Critical` in tuple element 2
+}
diff --git a/tests/ui/lint/unused/must_use-trait.stderr b/tests/ui/lint/unused/must_use-trait.stderr
new file mode 100644
index 000000000..2f5496484
--- /dev/null
+++ b/tests/ui/lint/unused/must_use-trait.stderr
@@ -0,0 +1,38 @@
+error: unused implementer of `Critical` that must be used
+ --> $DIR/must_use-trait.rs:33:5
+ |
+LL | get_critical();
+ | ^^^^^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/must_use-trait.rs:1:9
+ |
+LL | #![deny(unused_must_use)]
+ | ^^^^^^^^^^^^^^^
+
+error: unused boxed `Critical` trait object that must be used
+ --> $DIR/must_use-trait.rs:34:5
+ |
+LL | get_boxed_critical();
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: unused boxed boxed `Critical` trait object that must be used
+ --> $DIR/must_use-trait.rs:35:5
+ |
+LL | get_nested_boxed_critical();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: unused boxed `Critical` trait object in tuple element 1 that must be used
+ --> $DIR/must_use-trait.rs:37:5
+ |
+LL | get_critical_tuple();
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: unused implementer of `Critical` in tuple element 2 that must be used
+ --> $DIR/must_use-trait.rs:37:5
+ |
+LL | get_critical_tuple();
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
+
diff --git a/tests/ui/lint/unused/must_use-tuple.rs b/tests/ui/lint/unused/must_use-tuple.rs
new file mode 100644
index 000000000..0f0aa2025
--- /dev/null
+++ b/tests/ui/lint/unused/must_use-tuple.rs
@@ -0,0 +1,17 @@
+#![deny(unused_must_use)]
+
+fn foo() -> (Result<(), ()>, ()) {
+ (Ok::<(), ()>(()), ())
+}
+
+fn main() {
+ (Ok::<(), ()>(()),); //~ ERROR unused `Result`
+
+ (Ok::<(), ()>(()), 0, Ok::<(), ()>(()), 5);
+ //~^ ERROR unused `Result`
+ //~^^ ERROR unused `Result`
+
+ foo(); //~ ERROR unused `Result`
+
+ ((Err::<(), ()>(()), ()), ()); //~ ERROR unused `Result`
+}
diff --git a/tests/ui/lint/unused/must_use-tuple.stderr b/tests/ui/lint/unused/must_use-tuple.stderr
new file mode 100644
index 000000000..63e0318fb
--- /dev/null
+++ b/tests/ui/lint/unused/must_use-tuple.stderr
@@ -0,0 +1,47 @@
+error: unused `Result` in tuple element 0 that must be used
+ --> $DIR/must_use-tuple.rs:8:6
+ |
+LL | (Ok::<(), ()>(()),);
+ | ^^^^^^^^^^^^^^^^
+ |
+ = note: this `Result` may be an `Err` variant, which should be handled
+note: the lint level is defined here
+ --> $DIR/must_use-tuple.rs:1:9
+ |
+LL | #![deny(unused_must_use)]
+ | ^^^^^^^^^^^^^^^
+
+error: unused `Result` in tuple element 0 that must be used
+ --> $DIR/must_use-tuple.rs:10:6
+ |
+LL | (Ok::<(), ()>(()), 0, Ok::<(), ()>(()), 5);
+ | ^^^^^^^^^^^^^^^^
+ |
+ = note: this `Result` may be an `Err` variant, which should be handled
+
+error: unused `Result` in tuple element 2 that must be used
+ --> $DIR/must_use-tuple.rs:10:27
+ |
+LL | (Ok::<(), ()>(()), 0, Ok::<(), ()>(()), 5);
+ | ^^^^^^^^^^^^^^^^
+ |
+ = note: this `Result` may be an `Err` variant, which should be handled
+
+error: unused `Result` in tuple element 0 that must be used
+ --> $DIR/must_use-tuple.rs:14:5
+ |
+LL | foo();
+ | ^^^^^
+ |
+ = note: this `Result` may be an `Err` variant, which should be handled
+
+error: unused `Result` in tuple element 0 that must be used
+ --> $DIR/must_use-tuple.rs:16:7
+ |
+LL | ((Err::<(), ()>(()), ()), ());
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: this `Result` may be an `Err` variant, which should be handled
+
+error: aborting due to 5 previous errors
+
diff --git a/tests/ui/lint/unused/must_use-unit.rs b/tests/ui/lint/unused/must_use-unit.rs
new file mode 100644
index 000000000..4dd4798ab
--- /dev/null
+++ b/tests/ui/lint/unused/must_use-unit.rs
@@ -0,0 +1,16 @@
+#![feature(never_type)]
+#![deny(unused_must_use)]
+
+#[must_use]
+fn foo() {}
+
+#[must_use]
+fn bar() -> ! {
+ unimplemented!()
+}
+
+fn main() {
+ foo(); //~ unused return value of `foo`
+
+ bar(); //~ unused return value of `bar`
+}
diff --git a/tests/ui/lint/unused/must_use-unit.stderr b/tests/ui/lint/unused/must_use-unit.stderr
new file mode 100644
index 000000000..9fcbc5074
--- /dev/null
+++ b/tests/ui/lint/unused/must_use-unit.stderr
@@ -0,0 +1,20 @@
+error: unused return value of `foo` that must be used
+ --> $DIR/must_use-unit.rs:13:5
+ |
+LL | foo();
+ | ^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/must_use-unit.rs:2:9
+ |
+LL | #![deny(unused_must_use)]
+ | ^^^^^^^^^^^^^^^
+
+error: unused return value of `bar` that must be used
+ --> $DIR/must_use-unit.rs:15:5
+ |
+LL | bar();
+ | ^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/lint/unused/no-unused-parens-return-block.rs b/tests/ui/lint/unused/no-unused-parens-return-block.rs
new file mode 100644
index 000000000..37dc519a2
--- /dev/null
+++ b/tests/ui/lint/unused/no-unused-parens-return-block.rs
@@ -0,0 +1,9 @@
+// run-pass
+
+#![deny(unused_parens)]
+#![allow(unreachable_code)]
+
+fn main() {
+ match (return) {} // ok
+ if (return) {} // ok
+}
diff --git a/tests/ui/lint/unused/unused-async.rs b/tests/ui/lint/unused/unused-async.rs
new file mode 100644
index 000000000..4be93aa15
--- /dev/null
+++ b/tests/ui/lint/unused/unused-async.rs
@@ -0,0 +1,62 @@
+// edition:2018
+#![deny(unused_must_use)]
+
+
+#[must_use]
+async fn foo() -> i32 {
+ 1
+}
+
+#[must_use]
+fn bar() -> impl std::future::Future<Output=i32> {
+ async {
+ 42
+ }
+}
+
+async fn baz() -> i32 {
+ 0
+}
+
+struct Wowee {}
+
+impl Wowee {
+ #[must_use]
+ async fn test_method() -> i32 {
+ 1
+ }
+}
+
+async fn test() {
+ foo(); //~ ERROR unused return value of `foo` that must be used
+ //~^ ERROR unused implementer of `Future` that must be used
+ foo().await; //~ ERROR unused output of future returned by `foo` that must be used
+ bar(); //~ ERROR unused return value of `bar` that must be used
+ //~^ ERROR unused implementer of `Future` that must be used
+ bar().await; //~ ERROR unused output of future returned by `bar` that must be used
+ baz(); //~ ERROR unused implementer of `Future` that must be used
+ baz().await; // ok
+}
+
+/* FIXME(guswynn) update this test when async-fn-in-traits works
+trait Doer {
+ #[must_use]
+ async fn test_trait_method() -> i32;
+ WARNING must_use
+ async fn test_other_trait() -> i32;
+}
+
+impl Doer for Wowee {
+ async fn test_trait_method() -> i32 {
+ 1
+ }
+ #[must_use]
+ async fn test_other_trait() -> i32 {
+ WARNING must_use
+ 1
+ }
+}
+*/
+
+fn main() {
+}
diff --git a/tests/ui/lint/unused/unused-async.stderr b/tests/ui/lint/unused/unused-async.stderr
new file mode 100644
index 000000000..4bcb26dc1
--- /dev/null
+++ b/tests/ui/lint/unused/unused-async.stderr
@@ -0,0 +1,55 @@
+error: unused implementer of `Future` that must be used
+ --> $DIR/unused-async.rs:31:5
+ |
+LL | foo();
+ | ^^^^^
+ |
+ = note: futures do nothing unless you `.await` or poll them
+note: the lint level is defined here
+ --> $DIR/unused-async.rs:2:9
+ |
+LL | #![deny(unused_must_use)]
+ | ^^^^^^^^^^^^^^^
+
+error: unused return value of `foo` that must be used
+ --> $DIR/unused-async.rs:31:5
+ |
+LL | foo();
+ | ^^^^^
+
+error: unused output of future returned by `foo` that must be used
+ --> $DIR/unused-async.rs:33:5
+ |
+LL | foo().await;
+ | ^^^^^^^^^^^
+
+error: unused implementer of `Future` that must be used
+ --> $DIR/unused-async.rs:34:5
+ |
+LL | bar();
+ | ^^^^^
+ |
+ = note: futures do nothing unless you `.await` or poll them
+
+error: unused return value of `bar` that must be used
+ --> $DIR/unused-async.rs:34:5
+ |
+LL | bar();
+ | ^^^^^
+
+error: unused output of future returned by `bar` that must be used
+ --> $DIR/unused-async.rs:36:5
+ |
+LL | bar().await;
+ | ^^^^^^^^^^^
+
+error: unused implementer of `Future` that must be used
+ --> $DIR/unused-async.rs:37:5
+ |
+LL | baz();
+ | ^^^^^
+ |
+ = note: futures do nothing unless you `.await` or poll them
+
+error: aborting due to 7 previous errors
+
diff --git a/tests/ui/lint/unused/unused-attr-duplicate.rs b/tests/ui/lint/unused/unused-attr-duplicate.rs
new file mode 100644
index 000000000..692617eac
--- /dev/null
+++ b/tests/ui/lint/unused/unused-attr-duplicate.rs
@@ -0,0 +1,105 @@
+// Tests for repeating attribute warnings.
+// aux-build:lint_unused_extern_crate.rs
+// compile-flags:--test
+// Not tested due to extra requirements:
+// - panic_handler: needs extra setup
+// - target_feature: platform-specific
+// - link_section: platform-specific
+// - proc_macro, proc_macro_derive, proc_macro_attribute: needs to be a
+// proc-macro, and have special handling for mixing.
+// - unstable attributes (not going to bother)
+// - no_main: extra setup
+#![deny(unused_attributes)]
+#![crate_name = "unused_attr_duplicate"]
+#![crate_name = "unused_attr_duplicate2"] //~ ERROR unused attribute
+//~^ WARN this was previously accepted
+#![recursion_limit = "128"]
+#![recursion_limit = "256"] //~ ERROR unused attribute
+//~^ WARN this was previously accepted
+#![type_length_limit = "1048576"]
+#![type_length_limit = "1"] //~ ERROR unused attribute
+//~^ WARN this was previously accepted
+#![no_std]
+#![no_std] //~ ERROR unused attribute
+#![no_implicit_prelude]
+#![no_implicit_prelude] //~ ERROR unused attribute
+#![windows_subsystem = "console"]
+#![windows_subsystem = "windows"] //~ ERROR unused attribute
+//~^ WARN this was previously accepted
+#![no_builtins]
+#![no_builtins] //~ ERROR unused attribute
+
+#[no_link]
+#[no_link] //~ ERROR unused attribute
+extern crate lint_unused_extern_crate;
+
+#[macro_use]
+#[macro_use] //~ ERROR unused attribute
+pub mod m {
+ #[macro_export]
+ #[macro_export] //~ ERROR unused attribute
+ macro_rules! foo {
+ () => {};
+ }
+}
+
+#[path = "auxiliary/lint_unused_extern_crate.rs"]
+#[path = "bar.rs"] //~ ERROR unused attribute
+//~^ WARN this was previously accepted
+pub mod from_path;
+
+#[test]
+#[ignore]
+#[ignore = "some text"] //~ ERROR unused attribute
+#[should_panic]
+#[should_panic(expected = "values don't match")] //~ ERROR unused attribute
+//~^ WARN this was previously accepted
+fn t1() {}
+
+#[must_use]
+#[must_use = "some message"] //~ ERROR unused attribute
+//~^ WARN this was previously accepted
+// No warnings for #[repr], would require more logic.
+#[repr(C)]
+#[repr(C)]
+#[non_exhaustive]
+#[non_exhaustive] //~ ERROR unused attribute
+pub struct X;
+
+#[automatically_derived]
+#[automatically_derived] //~ ERROR unused attribute
+impl X {}
+
+#[inline(always)]
+#[inline(never)] //~ ERROR unused attribute
+//~^ WARN this was previously accepted
+#[cold]
+#[cold] //~ ERROR unused attribute
+#[track_caller]
+#[track_caller] //~ ERROR unused attribute
+pub fn xyz() {}
+
+// No warnings for #[link], would require more logic.
+#[link(name = "rust_test_helpers", kind = "static")]
+#[link(name = "rust_test_helpers", kind = "static")]
+extern "C" {
+ #[link_name = "this_does_not_exist"] //~ ERROR unused attribute
+ //~^ WARN this was previously accepted
+ #[link_name = "rust_dbg_extern_identity_u32"]
+ pub fn name_in_rust(v: u32) -> u32;
+}
+
+#[export_name = "exported_symbol_name"] //~ ERROR unused attribute
+//~^ WARN this was previously accepted
+#[export_name = "exported_symbol_name2"]
+pub fn export_test() {}
+
+#[no_mangle]
+#[no_mangle] //~ ERROR unused attribute
+pub fn no_mangle_test() {}
+
+#[used]
+#[used] //~ ERROR unused attribute
+static FOO: u32 = 0;
+
+fn main() {}
diff --git a/tests/ui/lint/unused/unused-attr-duplicate.stderr b/tests/ui/lint/unused/unused-attr-duplicate.stderr
new file mode 100644
index 000000000..769b17487
--- /dev/null
+++ b/tests/ui/lint/unused/unused-attr-duplicate.stderr
@@ -0,0 +1,293 @@
+error: unused attribute
+ --> $DIR/unused-attr-duplicate.rs:33:1
+ |
+LL | #[no_link]
+ | ^^^^^^^^^^ help: remove this attribute
+ |
+note: attribute also specified here
+ --> $DIR/unused-attr-duplicate.rs:32:1
+ |
+LL | #[no_link]
+ | ^^^^^^^^^^
+note: the lint level is defined here
+ --> $DIR/unused-attr-duplicate.rs:12:9
+ |
+LL | #![deny(unused_attributes)]
+ | ^^^^^^^^^^^^^^^^^
+
+error: unused attribute
+ --> $DIR/unused-attr-duplicate.rs:37:1
+ |
+LL | #[macro_use]
+ | ^^^^^^^^^^^^ help: remove this attribute
+ |
+note: attribute also specified here
+ --> $DIR/unused-attr-duplicate.rs:36:1
+ |
+LL | #[macro_use]
+ | ^^^^^^^^^^^^
+
+error: unused attribute
+ --> $DIR/unused-attr-duplicate.rs:47:1
+ |
+LL | #[path = "bar.rs"]
+ | ^^^^^^^^^^^^^^^^^^ help: remove this attribute
+ |
+note: attribute also specified here
+ --> $DIR/unused-attr-duplicate.rs:46:1
+ |
+LL | #[path = "auxiliary/lint_unused_extern_crate.rs"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+
+error: unused attribute
+ --> $DIR/unused-attr-duplicate.rs:53:1
+ |
+LL | #[ignore = "some text"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
+ |
+note: attribute also specified here
+ --> $DIR/unused-attr-duplicate.rs:52:1
+ |
+LL | #[ignore]
+ | ^^^^^^^^^
+
+error: unused attribute
+ --> $DIR/unused-attr-duplicate.rs:55:1
+ |
+LL | #[should_panic(expected = "values don't match")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
+ |
+note: attribute also specified here
+ --> $DIR/unused-attr-duplicate.rs:54:1
+ |
+LL | #[should_panic]
+ | ^^^^^^^^^^^^^^^
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+
+error: unused attribute
+ --> $DIR/unused-attr-duplicate.rs:60:1
+ |
+LL | #[must_use = "some message"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
+ |
+note: attribute also specified here
+ --> $DIR/unused-attr-duplicate.rs:59:1
+ |
+LL | #[must_use]
+ | ^^^^^^^^^^^
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+
+error: unused attribute
+ --> $DIR/unused-attr-duplicate.rs:66:1
+ |
+LL | #[non_exhaustive]
+ | ^^^^^^^^^^^^^^^^^ help: remove this attribute
+ |
+note: attribute also specified here
+ --> $DIR/unused-attr-duplicate.rs:65:1
+ |
+LL | #[non_exhaustive]
+ | ^^^^^^^^^^^^^^^^^
+
+error: unused attribute
+ --> $DIR/unused-attr-duplicate.rs:70:1
+ |
+LL | #[automatically_derived]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
+ |
+note: attribute also specified here
+ --> $DIR/unused-attr-duplicate.rs:69:1
+ |
+LL | #[automatically_derived]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: unused attribute
+ --> $DIR/unused-attr-duplicate.rs:74:1
+ |
+LL | #[inline(never)]
+ | ^^^^^^^^^^^^^^^^ help: remove this attribute
+ |
+note: attribute also specified here
+ --> $DIR/unused-attr-duplicate.rs:73:1
+ |
+LL | #[inline(always)]
+ | ^^^^^^^^^^^^^^^^^
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+
+error: unused attribute
+ --> $DIR/unused-attr-duplicate.rs:77:1
+ |
+LL | #[cold]
+ | ^^^^^^^ help: remove this attribute
+ |
+note: attribute also specified here
+ --> $DIR/unused-attr-duplicate.rs:76:1
+ |
+LL | #[cold]
+ | ^^^^^^^
+
+error: unused attribute
+ --> $DIR/unused-attr-duplicate.rs:79:1
+ |
+LL | #[track_caller]
+ | ^^^^^^^^^^^^^^^ help: remove this attribute
+ |
+note: attribute also specified here
+ --> $DIR/unused-attr-duplicate.rs:78:1
+ |
+LL | #[track_caller]
+ | ^^^^^^^^^^^^^^^
+
+error: unused attribute
+ --> $DIR/unused-attr-duplicate.rs:92:1
+ |
+LL | #[export_name = "exported_symbol_name"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
+ |
+note: attribute also specified here
+ --> $DIR/unused-attr-duplicate.rs:94:1
+ |
+LL | #[export_name = "exported_symbol_name2"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+
+error: unused attribute
+ --> $DIR/unused-attr-duplicate.rs:98:1
+ |
+LL | #[no_mangle]
+ | ^^^^^^^^^^^^ help: remove this attribute
+ |
+note: attribute also specified here
+ --> $DIR/unused-attr-duplicate.rs:97:1
+ |
+LL | #[no_mangle]
+ | ^^^^^^^^^^^^
+
+error: unused attribute
+ --> $DIR/unused-attr-duplicate.rs:102:1
+ |
+LL | #[used]
+ | ^^^^^^^ help: remove this attribute
+ |
+note: attribute also specified here
+ --> $DIR/unused-attr-duplicate.rs:101:1
+ |
+LL | #[used]
+ | ^^^^^^^
+
+error: unused attribute
+ --> $DIR/unused-attr-duplicate.rs:86:5
+ |
+LL | #[link_name = "this_does_not_exist"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
+ |
+note: attribute also specified here
+ --> $DIR/unused-attr-duplicate.rs:88:5
+ |
+LL | #[link_name = "rust_dbg_extern_identity_u32"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+
+error: unused attribute
+ --> $DIR/unused-attr-duplicate.rs:14:1
+ |
+LL | #![crate_name = "unused_attr_duplicate2"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
+ |
+note: attribute also specified here
+ --> $DIR/unused-attr-duplicate.rs:13:1
+ |
+LL | #![crate_name = "unused_attr_duplicate"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+
+error: unused attribute
+ --> $DIR/unused-attr-duplicate.rs:17:1
+ |
+LL | #![recursion_limit = "256"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
+ |
+note: attribute also specified here
+ --> $DIR/unused-attr-duplicate.rs:16:1
+ |
+LL | #![recursion_limit = "128"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+
+error: unused attribute
+ --> $DIR/unused-attr-duplicate.rs:20:1
+ |
+LL | #![type_length_limit = "1"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
+ |
+note: attribute also specified here
+ --> $DIR/unused-attr-duplicate.rs:19:1
+ |
+LL | #![type_length_limit = "1048576"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+
+error: unused attribute
+ --> $DIR/unused-attr-duplicate.rs:23:1
+ |
+LL | #![no_std]
+ | ^^^^^^^^^^ help: remove this attribute
+ |
+note: attribute also specified here
+ --> $DIR/unused-attr-duplicate.rs:22:1
+ |
+LL | #![no_std]
+ | ^^^^^^^^^^
+
+error: unused attribute
+ --> $DIR/unused-attr-duplicate.rs:25:1
+ |
+LL | #![no_implicit_prelude]
+ | ^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
+ |
+note: attribute also specified here
+ --> $DIR/unused-attr-duplicate.rs:24:1
+ |
+LL | #![no_implicit_prelude]
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: unused attribute
+ --> $DIR/unused-attr-duplicate.rs:27:1
+ |
+LL | #![windows_subsystem = "windows"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
+ |
+note: attribute also specified here
+ --> $DIR/unused-attr-duplicate.rs:26:1
+ |
+LL | #![windows_subsystem = "console"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+
+error: unused attribute
+ --> $DIR/unused-attr-duplicate.rs:30:1
+ |
+LL | #![no_builtins]
+ | ^^^^^^^^^^^^^^^ help: remove this attribute
+ |
+note: attribute also specified here
+ --> $DIR/unused-attr-duplicate.rs:29:1
+ |
+LL | #![no_builtins]
+ | ^^^^^^^^^^^^^^^
+
+error: unused attribute
+ --> $DIR/unused-attr-duplicate.rs:40:5
+ |
+LL | #[macro_export]
+ | ^^^^^^^^^^^^^^^ help: remove this attribute
+ |
+note: attribute also specified here
+ --> $DIR/unused-attr-duplicate.rs:39:5
+ |
+LL | #[macro_export]
+ | ^^^^^^^^^^^^^^^
+
+error: aborting due to 23 previous errors
+
diff --git a/tests/ui/lint/unused/unused-attr-macro-rules.rs b/tests/ui/lint/unused/unused-attr-macro-rules.rs
new file mode 100644
index 000000000..c0fc280ab
--- /dev/null
+++ b/tests/ui/lint/unused/unused-attr-macro-rules.rs
@@ -0,0 +1,33 @@
+#![deny(unused_attributes)]
+// Unused attributes on macro_rules requires special handling since the
+// macro_rules definition does not survive towards HIR.
+
+// A sample of various built-in attributes.
+#[macro_export]
+#[macro_use] //~ ERROR `#[macro_use]` only has an effect
+#[path="foo"] //~ ERROR #[path]` only has an effect
+#[recursion_limit="1"] //~ ERROR crate-level attribute should be an inner attribute
+macro_rules! foo {
+ () => {};
+}
+
+// The following should not warn about unused attributes.
+#[allow(unused)]
+macro_rules! foo2 {
+ () => {};
+}
+
+#[cfg(FALSE)]
+macro_rules! foo {
+ () => {};
+}
+
+/// Some docs
+#[deprecated]
+#[doc = "more docs"]
+#[macro_export]
+macro_rules! bar {
+ () => {};
+}
+
+fn main() {}
diff --git a/tests/ui/lint/unused/unused-attr-macro-rules.stderr b/tests/ui/lint/unused/unused-attr-macro-rules.stderr
new file mode 100644
index 000000000..e3ca90d9a
--- /dev/null
+++ b/tests/ui/lint/unused/unused-attr-macro-rules.stderr
@@ -0,0 +1,26 @@
+error: `#[macro_use]` only has an effect on `extern crate` and modules
+ --> $DIR/unused-attr-macro-rules.rs:7:1
+ |
+LL | #[macro_use]
+ | ^^^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/unused-attr-macro-rules.rs:1:9
+ |
+LL | #![deny(unused_attributes)]
+ | ^^^^^^^^^^^^^^^^^
+
+error: `#[path]` only has an effect on modules
+ --> $DIR/unused-attr-macro-rules.rs:8:1
+ |
+LL | #[path="foo"]
+ | ^^^^^^^^^^^^^
+
+error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
+ --> $DIR/unused-attr-macro-rules.rs:9:1
+ |
+LL | #[recursion_limit="1"]
+ | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/lint/unused/unused-closure.rs b/tests/ui/lint/unused/unused-closure.rs
new file mode 100644
index 000000000..c96c90731
--- /dev/null
+++ b/tests/ui/lint/unused/unused-closure.rs
@@ -0,0 +1,35 @@
+// Test that closures and generators are "must use" types.
+// edition:2018
+
+#![feature(async_closure)]
+#![feature(generators)]
+#![deny(unused_must_use)]
+
+fn unused() {
+ || { //~ ERROR unused closure that must be used
+ println!("Hello!");
+ };
+
+ async {}; //~ ERROR unused implementer of `Future` that must be used
+ || async {}; //~ ERROR unused closure that must be used
+ async || {}; //~ ERROR unused closure that must be used
+
+
+ [Box::new([|| {}; 10]); 1]; //~ ERROR unused array of boxed arrays of closures that must be used
+
+ vec![|| "a"].pop().unwrap(); //~ ERROR unused closure that must be used
+
+ let b = false;
+ || true; //~ ERROR unused closure that must be used
+ println!("{}", b);
+}
+
+fn ignored() {
+ let _ = || {};
+ let _ = || yield 42;
+}
+
+fn main() {
+ unused();
+ ignored();
+}
diff --git a/tests/ui/lint/unused/unused-closure.stderr b/tests/ui/lint/unused/unused-closure.stderr
new file mode 100644
index 000000000..c3a82402e
--- /dev/null
+++ b/tests/ui/lint/unused/unused-closure.stderr
@@ -0,0 +1,65 @@
+error: unused closure that must be used
+ --> $DIR/unused-closure.rs:9:5
+ |
+LL | / || {
+LL | | println!("Hello!");
+LL | | };
+ | |_____^
+ |
+ = note: closures are lazy and do nothing unless called
+note: the lint level is defined here
+ --> $DIR/unused-closure.rs:6:9
+ |
+LL | #![deny(unused_must_use)]
+ | ^^^^^^^^^^^^^^^
+
+error: unused implementer of `Future` that must be used
+ --> $DIR/unused-closure.rs:13:5
+ |
+LL | async {};
+ | ^^^^^^^^
+ |
+ = note: futures do nothing unless you `.await` or poll them
+
+error: unused closure that must be used
+ --> $DIR/unused-closure.rs:14:5
+ |
+LL | || async {};
+ | ^^^^^^^^^^^
+ |
+ = note: closures are lazy and do nothing unless called
+
+error: unused closure that must be used
+ --> $DIR/unused-closure.rs:15:5
+ |
+LL | async || {};
+ | ^^^^^^^^^^^
+ |
+ = note: closures are lazy and do nothing unless called
+
+error: unused array of boxed arrays of closures that must be used
+ --> $DIR/unused-closure.rs:18:5
+ |
+LL | [Box::new([|| {}; 10]); 1];
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: closures are lazy and do nothing unless called
+
+error: unused closure that must be used
+ --> $DIR/unused-closure.rs:20:5
+ |
+LL | vec![|| "a"].pop().unwrap();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: closures are lazy and do nothing unless called
+
+error: unused closure that must be used
+ --> $DIR/unused-closure.rs:23:9
+ |
+LL | || true;
+ | ^^^^^^^
+ |
+ = note: closures are lazy and do nothing unless called
+
+error: aborting due to 7 previous errors
+
diff --git a/tests/ui/lint/unused/unused-doc-comments-edge-cases.rs b/tests/ui/lint/unused/unused-doc-comments-edge-cases.rs
new file mode 100644
index 000000000..54d86c31f
--- /dev/null
+++ b/tests/ui/lint/unused/unused-doc-comments-edge-cases.rs
@@ -0,0 +1,46 @@
+#![deny(unused_doc_comments)]
+
+fn doc_comment_on_match_arms(num: u8) -> bool {
+ match num {
+ 3 => true,
+ /// useless doc comment
+ //~^ ERROR: unused doc comment
+ _ => false,
+ }
+}
+
+fn doc_comment_between_if_else(num: u8) -> bool {
+ if num == 3 {
+ true //~ ERROR: mismatched types
+ }
+ /// useless doc comment
+ else { //~ ERROR: expected expression, found keyword `else`
+ false
+ }
+}
+
+fn doc_comment_on_expr(num: u8) -> bool {
+ /// useless doc comment
+ //~^ ERROR: attributes on expressions are experimental
+ //~| ERROR: unused doc comment
+ num == 3
+}
+
+fn doc_comment_on_generic<#[doc = "x"] T>(val: T) {}
+//~^ ERROR: unused doc comment
+
+fn doc_comment_on_block() {
+ /// unused doc comment
+ //~^ ERROR: unused doc comment
+ {
+ let x = 12;
+ }
+}
+
+/// unused doc comment
+//~^ ERROR: unused doc comment
+extern "C" {
+ fn foo();
+}
+
+fn main() {}
diff --git a/tests/ui/lint/unused/unused-doc-comments-edge-cases.stderr b/tests/ui/lint/unused/unused-doc-comments-edge-cases.stderr
new file mode 100644
index 000000000..078b780d8
--- /dev/null
+++ b/tests/ui/lint/unused/unused-doc-comments-edge-cases.stderr
@@ -0,0 +1,95 @@
+error: expected expression, found keyword `else`
+ --> $DIR/unused-doc-comments-edge-cases.rs:17:5
+ |
+LL | else {
+ | ^^^^ expected expression
+
+error[E0658]: attributes on expressions are experimental
+ --> $DIR/unused-doc-comments-edge-cases.rs:23:5
+ |
+LL | /// useless doc comment
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
+ = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
+ = help: `///` is for documentation comments. For a plain comment, use `//`.
+
+error: unused doc comment
+ --> $DIR/unused-doc-comments-edge-cases.rs:6:9
+ |
+LL | /// useless doc comment
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+LL |
+LL | _ => false,
+ | ---------- rustdoc does not generate documentation for match arms
+ |
+ = help: use `//` for a plain comment
+note: the lint level is defined here
+ --> $DIR/unused-doc-comments-edge-cases.rs:1:9
+ |
+LL | #![deny(unused_doc_comments)]
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: unused doc comment
+ --> $DIR/unused-doc-comments-edge-cases.rs:23:5
+ |
+LL | /// useless doc comment
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | num == 3
+ | --- rustdoc does not generate documentation for expressions
+ |
+ = help: use `//` for a plain comment
+
+error: unused doc comment
+ --> $DIR/unused-doc-comments-edge-cases.rs:29:27
+ |
+LL | fn doc_comment_on_generic<#[doc = "x"] T>(val: T) {}
+ | ^^^^^^^^^^^^ - rustdoc does not generate documentation for generic parameters
+ |
+ = help: use `//` for a plain comment
+
+error: unused doc comment
+ --> $DIR/unused-doc-comments-edge-cases.rs:33:5
+ |
+LL | /// unused doc comment
+ | ^^^^^^^^^^^^^^^^^^^^^^
+LL |
+LL | / {
+LL | | let x = 12;
+LL | | }
+ | |_____- rustdoc does not generate documentation for expressions
+ |
+ = help: use `//` for a plain comment
+
+error: unused doc comment
+ --> $DIR/unused-doc-comments-edge-cases.rs:40:1
+ |
+LL | /// unused doc comment
+ | ^^^^^^^^^^^^^^^^^^^^^^
+LL |
+LL | / extern "C" {
+LL | | fn foo();
+LL | | }
+ | |_- rustdoc does not generate documentation for extern blocks
+ |
+ = help: use `//` for a plain comment
+
+error[E0308]: mismatched types
+ --> $DIR/unused-doc-comments-edge-cases.rs:14:9
+ |
+LL | / if num == 3 {
+LL | | true
+ | | ^^^^ expected `()`, found `bool`
+LL | | }
+ | |_____- expected this to be `()`
+ |
+help: you might have meant to return this value
+ |
+LL | return true;
+ | ++++++ +
+
+error: aborting due to 8 previous errors
+
+Some errors have detailed explanations: E0308, E0658.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/lint/unused/unused-doc-comments-for-macros.rs b/tests/ui/lint/unused/unused-doc-comments-for-macros.rs
new file mode 100644
index 000000000..05828ebb2
--- /dev/null
+++ b/tests/ui/lint/unused/unused-doc-comments-for-macros.rs
@@ -0,0 +1,17 @@
+#![deny(unused_doc_comments)]
+#![feature(rustc_attrs)]
+
+macro_rules! foo { () => {}; }
+
+fn main() {
+ /// line1 //~ ERROR: unused doc comment
+ /// line2
+ /// line3
+ foo!();
+
+ // Ensure we still detect another doc-comment block.
+ /// line1 //~ ERROR: unused doc comment
+ /// line2
+ /// line3
+ foo!();
+}
diff --git a/tests/ui/lint/unused/unused-doc-comments-for-macros.stderr b/tests/ui/lint/unused/unused-doc-comments-for-macros.stderr
new file mode 100644
index 000000000..26b1c2b05
--- /dev/null
+++ b/tests/ui/lint/unused/unused-doc-comments-for-macros.stderr
@@ -0,0 +1,31 @@
+error: unused doc comment
+ --> $DIR/unused-doc-comments-for-macros.rs:7:5
+ |
+LL | / /// line1
+LL | | /// line2
+LL | | /// line3
+ | |_____--------^
+ | |
+ | rustdoc does not generate documentation for macro invocations
+ |
+ = help: to document an item produced by a macro, the macro must produce the documentation as part of its expansion
+note: the lint level is defined here
+ --> $DIR/unused-doc-comments-for-macros.rs:1:9
+ |
+LL | #![deny(unused_doc_comments)]
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: unused doc comment
+ --> $DIR/unused-doc-comments-for-macros.rs:13:5
+ |
+LL | / /// line1
+LL | | /// line2
+LL | | /// line3
+ | |_____--------^
+ | |
+ | rustdoc does not generate documentation for macro invocations
+ |
+ = help: to document an item produced by a macro, the macro must produce the documentation as part of its expansion
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/lint/unused/unused-macro-rules-compile-error.rs b/tests/ui/lint/unused/unused-macro-rules-compile-error.rs
new file mode 100644
index 000000000..4d51db89b
--- /dev/null
+++ b/tests/ui/lint/unused/unused-macro-rules-compile-error.rs
@@ -0,0 +1,27 @@
+#![deny(unused_macro_rules)]
+// To make sure we are not hitting this
+#![deny(unused_macros)]
+
+macro_rules! num {
+ (one) => { 1 };
+ // Most simple (and common) case
+ (two) => { compile_error!("foo"); };
+ // Some nested use
+ (two_) => { foo(compile_error!("foo")); };
+ (three) => { 3 };
+ (four) => { 4 }; //~ ERROR: rule of macro
+}
+const _NUM: u8 = num!(one) + num!(three);
+
+// compile_error not used as a macro invocation
+macro_rules! num2 {
+ (one) => { 1 };
+ // Only identifier present
+ (two) => { fn compile_error() {} }; //~ ERROR: rule of macro
+ // Only identifier and bang present
+ (two_) => { compile_error! }; //~ ERROR: rule of macro
+ (three) => { 3 };
+}
+const _NUM2: u8 = num2!(one) + num2!(three);
+
+fn main() {}
diff --git a/tests/ui/lint/unused/unused-macro-rules-compile-error.stderr b/tests/ui/lint/unused/unused-macro-rules-compile-error.stderr
new file mode 100644
index 000000000..76af8c967
--- /dev/null
+++ b/tests/ui/lint/unused/unused-macro-rules-compile-error.stderr
@@ -0,0 +1,26 @@
+error: 5th rule of macro `num` is never used
+ --> $DIR/unused-macro-rules-compile-error.rs:12:5
+ |
+LL | (four) => { 4 };
+ | ^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/unused-macro-rules-compile-error.rs:1:9
+ |
+LL | #![deny(unused_macro_rules)]
+ | ^^^^^^^^^^^^^^^^^^
+
+error: 3rd rule of macro `num2` is never used
+ --> $DIR/unused-macro-rules-compile-error.rs:22:5
+ |
+LL | (two_) => { compile_error! };
+ | ^^^^^^
+
+error: 2nd rule of macro `num2` is never used
+ --> $DIR/unused-macro-rules-compile-error.rs:20:5
+ |
+LL | (two) => { fn compile_error() {} };
+ | ^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/lint/unused/unused-macro-rules-decl.rs b/tests/ui/lint/unused/unused-macro-rules-decl.rs
new file mode 100644
index 000000000..537c84940
--- /dev/null
+++ b/tests/ui/lint/unused/unused-macro-rules-decl.rs
@@ -0,0 +1,49 @@
+#![feature(decl_macro)]
+#![deny(unused_macro_rules)]
+// To make sure we are not hitting this
+#![deny(unused_macros)]
+
+// Most simple case
+macro num {
+ (one) => { 1 },
+ (two) => { 2 }, //~ ERROR: 2nd rule of macro
+ (three) => { 3 },
+ (four) => { 4 }, //~ ERROR: 4th rule of macro
+}
+const _NUM: u8 = num!(one) + num!(three);
+
+// Check that allowing the lint works
+#[allow(unused_macro_rules)]
+macro num_allowed {
+ (one) => { 1 },
+ (two) => { 2 },
+ (three) => { 3 },
+ (four) => { 4 },
+}
+const _NUM_ALLOWED: u8 = num_allowed!(one) + num_allowed!(three);
+
+// Check that macro calls inside the macro trigger as usage
+macro num_rec {
+ (one) => { 1 },
+ (two) => {
+ num_rec!(one) + num_rec!(one)
+ },
+ (three) => { //~ ERROR: 3rd rule of macro
+ num_rec!(one) + num_rec!(two)
+ },
+ (four) => {
+ num_rec!(two) + num_rec!(two)
+ },
+}
+const _NUM_RECURSIVE: u8 = num_rec!(four);
+
+// No error if the macro is public
+pub macro num_public {
+ (one) => { 1 },
+ (two) => { 2 },
+ (three) => { 3 },
+ (four) => { 4 },
+}
+const _NUM_PUBLIC: u8 = num_public!(one) + num_public!(three);
+
+fn main() {}
diff --git a/tests/ui/lint/unused/unused-macro-rules-decl.stderr b/tests/ui/lint/unused/unused-macro-rules-decl.stderr
new file mode 100644
index 000000000..4d9b22fed
--- /dev/null
+++ b/tests/ui/lint/unused/unused-macro-rules-decl.stderr
@@ -0,0 +1,26 @@
+error: 4th rule of macro `num` is never used
+ --> $DIR/unused-macro-rules-decl.rs:11:5
+ |
+LL | (four) => { 4 },
+ | ^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/unused-macro-rules-decl.rs:2:9
+ |
+LL | #![deny(unused_macro_rules)]
+ | ^^^^^^^^^^^^^^^^^^
+
+error: 2nd rule of macro `num` is never used
+ --> $DIR/unused-macro-rules-decl.rs:9:5
+ |
+LL | (two) => { 2 },
+ | ^^^^^
+
+error: 3rd rule of macro `num_rec` is never used
+ --> $DIR/unused-macro-rules-decl.rs:31:5
+ |
+LL | (three) => {
+ | ^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/lint/unused/unused-macro-rules-malformed-rule.rs b/tests/ui/lint/unused/unused-macro-rules-malformed-rule.rs
new file mode 100644
index 000000000..a826026ec
--- /dev/null
+++ b/tests/ui/lint/unused/unused-macro-rules-malformed-rule.rs
@@ -0,0 +1,11 @@
+#![deny(unused_macro_rules)]
+
+macro_rules! foo {
+ (v) => {};
+ (w) => {};
+ () => 0; //~ ERROR: macro rhs must be delimited
+}
+
+fn main() {
+ foo!(v);
+}
diff --git a/tests/ui/lint/unused/unused-macro-rules-malformed-rule.stderr b/tests/ui/lint/unused/unused-macro-rules-malformed-rule.stderr
new file mode 100644
index 000000000..797c86710
--- /dev/null
+++ b/tests/ui/lint/unused/unused-macro-rules-malformed-rule.stderr
@@ -0,0 +1,8 @@
+error: macro rhs must be delimited
+ --> $DIR/unused-macro-rules-malformed-rule.rs:6:11
+ |
+LL | () => 0;
+ | ^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/lint/unused/unused-macro-rules.rs b/tests/ui/lint/unused/unused-macro-rules.rs
new file mode 100644
index 000000000..eeaf4d1b0
--- /dev/null
+++ b/tests/ui/lint/unused/unused-macro-rules.rs
@@ -0,0 +1,47 @@
+#![deny(unused_macro_rules)]
+// To make sure we are not hitting this
+#![deny(unused_macros)]
+
+// Most simple case
+macro_rules! num {
+ (one) => { 1 };
+ (two) => { 2 }; //~ ERROR: 2nd rule of macro
+ (three) => { 3 };
+ (four) => { 4 }; //~ ERROR: 4th rule of macro
+}
+const _NUM: u8 = num!(one) + num!(three);
+
+// Check that allowing the lint works
+#[allow(unused_macro_rules)]
+macro_rules! num_allowed {
+ (one) => { 1 };
+ (two) => { 2 };
+ (three) => { 3 };
+ (four) => { 4 };
+}
+const _NUM_ALLOWED: u8 = num_allowed!(one) + num_allowed!(three);
+
+// Check that macro calls inside the macro trigger as usage
+macro_rules! num_rec {
+ (one) => { 1 };
+ (two) => {
+ num_rec!(one) + num_rec!(one)
+ };
+ (three) => { //~ ERROR: 3rd rule of macro
+ num_rec!(one) + num_rec!(two)
+ };
+ (four) => { num_rec!(two) + num_rec!(two) };
+}
+const _NUM_RECURSIVE: u8 = num_rec!(four);
+
+// No error if the macro is being exported
+#[macro_export]
+macro_rules! num_exported {
+ (one) => { 1 };
+ (two) => { 2 };
+ (three) => { 3 };
+ (four) => { 4 };
+}
+const _NUM_EXPORTED: u8 = num_exported!(one) + num_exported!(three);
+
+fn main() {}
diff --git a/tests/ui/lint/unused/unused-macro-rules.stderr b/tests/ui/lint/unused/unused-macro-rules.stderr
new file mode 100644
index 000000000..2b3098a51
--- /dev/null
+++ b/tests/ui/lint/unused/unused-macro-rules.stderr
@@ -0,0 +1,26 @@
+error: 4th rule of macro `num` is never used
+ --> $DIR/unused-macro-rules.rs:10:5
+ |
+LL | (four) => { 4 };
+ | ^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/unused-macro-rules.rs:1:9
+ |
+LL | #![deny(unused_macro_rules)]
+ | ^^^^^^^^^^^^^^^^^^
+
+error: 2nd rule of macro `num` is never used
+ --> $DIR/unused-macro-rules.rs:8:5
+ |
+LL | (two) => { 2 };
+ | ^^^^^
+
+error: 3rd rule of macro `num_rec` is never used
+ --> $DIR/unused-macro-rules.rs:30:5
+ |
+LL | (three) => {
+ | ^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/lint/unused/unused-macro-with-bad-frag-spec.rs b/tests/ui/lint/unused/unused-macro-with-bad-frag-spec.rs
new file mode 100644
index 000000000..ce187047b
--- /dev/null
+++ b/tests/ui/lint/unused/unused-macro-with-bad-frag-spec.rs
@@ -0,0 +1,9 @@
+#![allow(unused_macros)]
+
+// Issue #21370
+
+macro_rules! test {
+ ($wrong:t_ty) => () //~ ERROR invalid fragment specifier `t_ty`
+}
+
+fn main() { }
diff --git a/tests/ui/lint/unused/unused-macro-with-bad-frag-spec.stderr b/tests/ui/lint/unused/unused-macro-with-bad-frag-spec.stderr
new file mode 100644
index 000000000..6edf0a2cf
--- /dev/null
+++ b/tests/ui/lint/unused/unused-macro-with-bad-frag-spec.stderr
@@ -0,0 +1,10 @@
+error: invalid fragment specifier `t_ty`
+ --> $DIR/unused-macro-with-bad-frag-spec.rs:6:6
+ |
+LL | ($wrong:t_ty) => ()
+ | ^^^^^^^^^^^
+ |
+ = help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/lint/unused/unused-macro-with-follow-violation.rs b/tests/ui/lint/unused/unused-macro-with-follow-violation.rs
new file mode 100644
index 000000000..1666dae69
--- /dev/null
+++ b/tests/ui/lint/unused/unused-macro-with-follow-violation.rs
@@ -0,0 +1,7 @@
+#![allow(unused_macros)]
+
+macro_rules! test {
+ ($e:expr +) => () //~ ERROR not allowed for `expr` fragments
+}
+
+fn main() { }
diff --git a/tests/ui/lint/unused/unused-macro-with-follow-violation.stderr b/tests/ui/lint/unused/unused-macro-with-follow-violation.stderr
new file mode 100644
index 000000000..5eced4f06
--- /dev/null
+++ b/tests/ui/lint/unused/unused-macro-with-follow-violation.stderr
@@ -0,0 +1,10 @@
+error: `$e:expr` is followed by `+`, which is not allowed for `expr` fragments
+ --> $DIR/unused-macro-with-follow-violation.rs:4:14
+ |
+LL | ($e:expr +) => ()
+ | ^ not allowed after `expr` fragments
+ |
+ = note: allowed there are: `=>`, `,` or `;`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/lint/unused/unused-macros-decl.rs b/tests/ui/lint/unused/unused-macros-decl.rs
new file mode 100644
index 000000000..21f6108b1
--- /dev/null
+++ b/tests/ui/lint/unused/unused-macros-decl.rs
@@ -0,0 +1,28 @@
+#![feature(decl_macro)]
+#![deny(unused_macros)]
+// To make sure we are not hitting this
+#![deny(unused_macro_rules)]
+
+// Most simple case
+macro unused { //~ ERROR: unused macro definition
+ () => {}
+}
+
+#[allow(unused_macros)]
+mod bar {
+ // Test that putting the #[deny] close to the macro's definition
+ // works.
+
+ #[deny(unused_macros)]
+ macro unused { //~ ERROR: unused macro definition
+ () => {}
+ }
+}
+
+mod boo {
+ pub(crate) macro unused { //~ ERROR: unused macro definition
+ () => {}
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/lint/unused/unused-macros-decl.stderr b/tests/ui/lint/unused/unused-macros-decl.stderr
new file mode 100644
index 000000000..1f426b9d9
--- /dev/null
+++ b/tests/ui/lint/unused/unused-macros-decl.stderr
@@ -0,0 +1,32 @@
+error: unused macro definition: `unused`
+ --> $DIR/unused-macros-decl.rs:7:7
+ |
+LL | macro unused {
+ | ^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/unused-macros-decl.rs:2:9
+ |
+LL | #![deny(unused_macros)]
+ | ^^^^^^^^^^^^^
+
+error: unused macro definition: `unused`
+ --> $DIR/unused-macros-decl.rs:17:11
+ |
+LL | macro unused {
+ | ^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/unused-macros-decl.rs:16:12
+ |
+LL | #[deny(unused_macros)]
+ | ^^^^^^^^^^^^^
+
+error: unused macro definition: `unused`
+ --> $DIR/unused-macros-decl.rs:23:22
+ |
+LL | pub(crate) macro unused {
+ | ^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/lint/unused/unused-macros-malformed-rule.rs b/tests/ui/lint/unused/unused-macros-malformed-rule.rs
new file mode 100644
index 000000000..d4c35fad9
--- /dev/null
+++ b/tests/ui/lint/unused/unused-macros-malformed-rule.rs
@@ -0,0 +1,15 @@
+#![deny(unused_macros)]
+
+macro_rules! foo { //~ ERROR: unused macro definition
+ (v) => {};
+ () => 0; //~ ERROR: macro rhs must be delimited
+}
+
+macro_rules! bar {
+ (v) => {};
+ () => 0; //~ ERROR: macro rhs must be delimited
+}
+
+fn main() {
+ bar!(v);
+}
diff --git a/tests/ui/lint/unused/unused-macros-malformed-rule.stderr b/tests/ui/lint/unused/unused-macros-malformed-rule.stderr
new file mode 100644
index 000000000..9a880dccf
--- /dev/null
+++ b/tests/ui/lint/unused/unused-macros-malformed-rule.stderr
@@ -0,0 +1,26 @@
+error: macro rhs must be delimited
+ --> $DIR/unused-macros-malformed-rule.rs:5:11
+ |
+LL | () => 0;
+ | ^
+
+error: macro rhs must be delimited
+ --> $DIR/unused-macros-malformed-rule.rs:10:11
+ |
+LL | () => 0;
+ | ^
+
+error: unused macro definition: `foo`
+ --> $DIR/unused-macros-malformed-rule.rs:3:14
+ |
+LL | macro_rules! foo {
+ | ^^^
+ |
+note: the lint level is defined here
+ --> $DIR/unused-macros-malformed-rule.rs:1:9
+ |
+LL | #![deny(unused_macros)]
+ | ^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/lint/unused/unused-macros.rs b/tests/ui/lint/unused/unused-macros.rs
new file mode 100644
index 000000000..70b50b208
--- /dev/null
+++ b/tests/ui/lint/unused/unused-macros.rs
@@ -0,0 +1,31 @@
+#![deny(unused_macros)]
+// To make sure we are not hitting this
+#![deny(unused_macro_rules)]
+
+// Most simple case
+macro_rules! unused { //~ ERROR: unused macro definition
+ () => {};
+}
+
+// Test macros created by macros
+macro_rules! create_macro {
+ () => {
+ macro_rules! m { //~ ERROR: unused macro definition
+ () => {};
+ }
+ };
+}
+create_macro!();
+
+#[allow(unused_macros)]
+mod bar {
+ // Test that putting the #[deny] close to the macro's definition
+ // works.
+
+ #[deny(unused_macros)]
+ macro_rules! unused { //~ ERROR: unused macro definition
+ () => {};
+ }
+}
+
+fn main() {}
diff --git a/tests/ui/lint/unused/unused-macros.stderr b/tests/ui/lint/unused/unused-macros.stderr
new file mode 100644
index 000000000..d0baf5bec
--- /dev/null
+++ b/tests/ui/lint/unused/unused-macros.stderr
@@ -0,0 +1,32 @@
+error: unused macro definition: `unused`
+ --> $DIR/unused-macros.rs:6:14
+ |
+LL | macro_rules! unused {
+ | ^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/unused-macros.rs:1:9
+ |
+LL | #![deny(unused_macros)]
+ | ^^^^^^^^^^^^^
+
+error: unused macro definition: `m`
+ --> $DIR/unused-macros.rs:13:22
+ |
+LL | macro_rules! m {
+ | ^
+
+error: unused macro definition: `unused`
+ --> $DIR/unused-macros.rs:26:18
+ |
+LL | macro_rules! unused {
+ | ^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/unused-macros.rs:25:12
+ |
+LL | #[deny(unused_macros)]
+ | ^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/lint/unused/unused-mut-warning-captured-var.fixed b/tests/ui/lint/unused/unused-mut-warning-captured-var.fixed
new file mode 100644
index 000000000..c21f18015
--- /dev/null
+++ b/tests/ui/lint/unused/unused-mut-warning-captured-var.fixed
@@ -0,0 +1,9 @@
+// run-rustfix
+
+#![forbid(unused_mut)]
+
+fn main() {
+ let x = 1;
+ //~^ ERROR: variable does not need to be mutable
+ (move|| { println!("{}", x); })();
+}
diff --git a/tests/ui/lint/unused/unused-mut-warning-captured-var.rs b/tests/ui/lint/unused/unused-mut-warning-captured-var.rs
new file mode 100644
index 000000000..3119d83a0
--- /dev/null
+++ b/tests/ui/lint/unused/unused-mut-warning-captured-var.rs
@@ -0,0 +1,9 @@
+// run-rustfix
+
+#![forbid(unused_mut)]
+
+fn main() {
+ let mut x = 1;
+ //~^ ERROR: variable does not need to be mutable
+ (move|| { println!("{}", x); })();
+}
diff --git a/tests/ui/lint/unused/unused-mut-warning-captured-var.stderr b/tests/ui/lint/unused/unused-mut-warning-captured-var.stderr
new file mode 100644
index 000000000..20aeedcc2
--- /dev/null
+++ b/tests/ui/lint/unused/unused-mut-warning-captured-var.stderr
@@ -0,0 +1,16 @@
+error: variable does not need to be mutable
+ --> $DIR/unused-mut-warning-captured-var.rs:6:9
+ |
+LL | let mut x = 1;
+ | ----^
+ | |
+ | help: remove this `mut`
+ |
+note: the lint level is defined here
+ --> $DIR/unused-mut-warning-captured-var.rs:3:11
+ |
+LL | #![forbid(unused_mut)]
+ | ^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/lint/unused/unused-result.rs b/tests/ui/lint/unused/unused-result.rs
new file mode 100644
index 000000000..e283eaa88
--- /dev/null
+++ b/tests/ui/lint/unused/unused-result.rs
@@ -0,0 +1,42 @@
+#![allow(dead_code)]
+#![deny(unused_results, unused_must_use)]
+//~^ NOTE: the lint level is defined here
+//~| NOTE: the lint level is defined here
+
+#[must_use]
+enum MustUse { Test }
+
+#[must_use = "some message"]
+enum MustUseMsg { Test2 }
+
+fn foo<T>() -> T { panic!() }
+
+fn bar() -> isize { return foo::<isize>(); }
+fn baz() -> MustUse { return foo::<MustUse>(); }
+fn qux() -> MustUseMsg { return foo::<MustUseMsg>(); }
+
+#[allow(unused_results)]
+fn test() {
+ foo::<isize>();
+ foo::<MustUse>(); //~ ERROR: unused `MustUse` that must be used
+ foo::<MustUseMsg>(); //~ ERROR: unused `MustUseMsg` that must be used
+ //~^ NOTE: some message
+}
+
+#[allow(unused_results, unused_must_use)]
+fn test2() {
+ foo::<isize>();
+ foo::<MustUse>();
+ foo::<MustUseMsg>();
+}
+
+fn main() {
+ foo::<isize>(); //~ ERROR: unused result of type `isize`
+ foo::<MustUse>(); //~ ERROR: unused `MustUse` that must be used
+ foo::<MustUseMsg>(); //~ ERROR: unused `MustUseMsg` that must be used
+ //~^ NOTE: some message
+
+ let _ = foo::<isize>();
+ let _ = foo::<MustUse>();
+ let _ = foo::<MustUseMsg>();
+}
diff --git a/tests/ui/lint/unused/unused-result.stderr b/tests/ui/lint/unused/unused-result.stderr
new file mode 100644
index 000000000..4e1ba1fd9
--- /dev/null
+++ b/tests/ui/lint/unused/unused-result.stderr
@@ -0,0 +1,48 @@
+error: unused `MustUse` that must be used
+ --> $DIR/unused-result.rs:21:5
+ |
+LL | foo::<MustUse>();
+ | ^^^^^^^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/unused-result.rs:2:25
+ |
+LL | #![deny(unused_results, unused_must_use)]
+ | ^^^^^^^^^^^^^^^
+
+error: unused `MustUseMsg` that must be used
+ --> $DIR/unused-result.rs:22:5
+ |
+LL | foo::<MustUseMsg>();
+ | ^^^^^^^^^^^^^^^^^^^
+ |
+ = note: some message
+
+error: unused result of type `isize`
+ --> $DIR/unused-result.rs:34:5
+ |
+LL | foo::<isize>();
+ | ^^^^^^^^^^^^^^^
+ |
+note: the lint level is defined here
+ --> $DIR/unused-result.rs:2:9
+ |
+LL | #![deny(unused_results, unused_must_use)]
+ | ^^^^^^^^^^^^^^
+
+error: unused `MustUse` that must be used
+ --> $DIR/unused-result.rs:35:5
+ |
+LL | foo::<MustUse>();
+ | ^^^^^^^^^^^^^^^^
+
+error: unused `MustUseMsg` that must be used
+ --> $DIR/unused-result.rs:36:5
+ |
+LL | foo::<MustUseMsg>();
+ | ^^^^^^^^^^^^^^^^^^^
+ |
+ = note: some message
+
+error: aborting due to 5 previous errors
+
diff --git a/tests/ui/lint/unused/unused-supertrait.rs b/tests/ui/lint/unused/unused-supertrait.rs
new file mode 100644
index 000000000..64a8e5204
--- /dev/null
+++ b/tests/ui/lint/unused/unused-supertrait.rs
@@ -0,0 +1,11 @@
+#![deny(unused_must_use)]
+
+fn it() -> impl ExactSizeIterator<Item = ()> {
+ let x: Box<dyn ExactSizeIterator<Item = ()>> = todo!();
+ x
+}
+
+fn main() {
+ it();
+ //~^ ERROR unused implementer of `Iterator` that must be used
+}
diff --git a/tests/ui/lint/unused/unused-supertrait.stderr b/tests/ui/lint/unused/unused-supertrait.stderr
new file mode 100644
index 000000000..cb45add9c
--- /dev/null
+++ b/tests/ui/lint/unused/unused-supertrait.stderr
@@ -0,0 +1,15 @@
+error: unused implementer of `Iterator` that must be used
+ --> $DIR/unused-supertrait.rs:9:5
+ |
+LL | it();
+ | ^^^^
+ |
+ = note: iterators are lazy and do nothing unless consumed
+note: the lint level is defined here
+ --> $DIR/unused-supertrait.rs:1:9
+ |
+LL | #![deny(unused_must_use)]
+ | ^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/lint/unused/unused_attributes-must_use.rs b/tests/ui/lint/unused/unused_attributes-must_use.rs
new file mode 100644
index 000000000..51f868706
--- /dev/null
+++ b/tests/ui/lint/unused/unused_attributes-must_use.rs
@@ -0,0 +1,131 @@
+#![allow(dead_code, path_statements)]
+#![deny(unused_attributes, unused_must_use)]
+#![feature(asm_experimental_arch, stmt_expr_attributes, trait_alias)]
+
+#[must_use] //~ ERROR `#[must_use]` has no effect
+extern crate std as std2;
+
+#[must_use] //~ ERROR `#[must_use]` has no effect
+mod test_mod {}
+
+#[must_use] //~ ERROR `#[must_use]` has no effect
+use std::arch::global_asm;
+
+#[must_use] //~ ERROR `#[must_use]` has no effect
+const CONST: usize = 4;
+#[must_use] //~ ERROR `#[must_use]` has no effect
+#[no_mangle]
+static STATIC: usize = 4;
+
+#[must_use]
+struct X;
+
+#[must_use]
+enum Y {
+ Z,
+}
+
+#[must_use]
+union U {
+ unit: (),
+}
+
+#[must_use] //~ ERROR `#[must_use]` has no effect
+impl U {
+ #[must_use]
+ fn method() -> i32 {
+ 4
+ }
+}
+
+#[must_use]
+#[no_mangle]
+fn foo() -> i64 {
+ 4
+}
+
+#[must_use] //~ ERROR `#[must_use]` has no effect
+extern "Rust" {
+ #[link_name = "STATIC"]
+ #[must_use] //~ ERROR `#[must_use]` has no effect
+ static FOREIGN_STATIC: usize;
+
+ #[link_name = "foo"]
+ #[must_use]
+ fn foreign_foo() -> i64;
+}
+
+#[must_use] //~ ERROR unused attribute
+global_asm!("");
+
+#[must_use] //~ ERROR `#[must_use]` has no effect
+type UseMe = ();
+
+fn qux<#[must_use] T>(_: T) {} //~ ERROR `#[must_use]` has no effect
+
+#[must_use]
+trait Use {
+ #[must_use] //~ ERROR `#[must_use]` has no effect
+ const ASSOC_CONST: usize = 4;
+ #[must_use] //~ ERROR `#[must_use]` has no effect
+ type AssocTy;
+
+ #[must_use]
+ fn get_four(&self) -> usize {
+ 4
+ }
+}
+
+#[must_use] //~ ERROR `#[must_use]` has no effect
+impl Use for () {
+ type AssocTy = ();
+}
+
+#[must_use] //~ ERROR `#[must_use]` has no effect
+trait Alias = Use;
+
+#[must_use] //~ ERROR `#[must_use]` has no effect
+macro_rules! cool_macro {
+ () => {
+ 4
+ };
+}
+
+fn main() {
+ #[must_use] //~ ERROR `#[must_use]` has no effect
+ let x = || {};
+ x();
+
+ let x = #[must_use] //~ ERROR `#[must_use]` has no effect
+ || {};
+ x();
+
+ X; //~ ERROR that must be used
+ Y::Z; //~ ERROR that must be used
+ U { unit: () }; //~ ERROR that must be used
+ U::method(); //~ ERROR that must be used
+ foo(); //~ ERROR that must be used
+
+ unsafe {
+ foreign_foo(); //~ ERROR that must be used
+ };
+
+ CONST;
+ STATIC;
+ unsafe { FOREIGN_STATIC };
+ cool_macro!();
+ qux(4);
+ ().get_four(); //~ ERROR that must be used
+
+ match Some(4) {
+ #[must_use] //~ ERROR `#[must_use]` has no effect
+ Some(res) => res,
+ None => 0,
+ };
+
+ struct PatternField {
+ foo: i32,
+ }
+ let s = PatternField { #[must_use] foo: 123 }; //~ ERROR `#[must_use]` has no effect
+ let PatternField { #[must_use] foo } = s; //~ ERROR `#[must_use]` has no effect
+}
diff --git a/tests/ui/lint/unused/unused_attributes-must_use.stderr b/tests/ui/lint/unused/unused_attributes-must_use.stderr
new file mode 100644
index 000000000..0f699429e
--- /dev/null
+++ b/tests/ui/lint/unused/unused_attributes-must_use.stderr
@@ -0,0 +1,187 @@
+error: unused attribute `must_use`
+ --> $DIR/unused_attributes-must_use.rs:58:1
+ |
+LL | #[must_use]
+ | ^^^^^^^^^^^
+ |
+note: the built-in attribute `must_use` will be ignored, since it's applied to the macro invocation `global_asm`
+ --> $DIR/unused_attributes-must_use.rs:59:1
+ |
+LL | global_asm!("");
+ | ^^^^^^^^^^
+note: the lint level is defined here
+ --> $DIR/unused_attributes-must_use.rs:2:9
+ |
+LL | #![deny(unused_attributes, unused_must_use)]
+ | ^^^^^^^^^^^^^^^^^
+
+error: `#[must_use]` has no effect when applied to an extern crate
+ --> $DIR/unused_attributes-must_use.rs:5:1
+ |
+LL | #[must_use]
+ | ^^^^^^^^^^^
+
+error: `#[must_use]` has no effect when applied to a module
+ --> $DIR/unused_attributes-must_use.rs:8:1
+ |
+LL | #[must_use]
+ | ^^^^^^^^^^^
+
+error: `#[must_use]` has no effect when applied to a use
+ --> $DIR/unused_attributes-must_use.rs:11:1
+ |
+LL | #[must_use]
+ | ^^^^^^^^^^^
+
+error: `#[must_use]` has no effect when applied to a constant item
+ --> $DIR/unused_attributes-must_use.rs:14:1
+ |
+LL | #[must_use]
+ | ^^^^^^^^^^^
+
+error: `#[must_use]` has no effect when applied to a static item
+ --> $DIR/unused_attributes-must_use.rs:16:1
+ |
+LL | #[must_use]
+ | ^^^^^^^^^^^
+
+error: `#[must_use]` has no effect when applied to an implementation block
+ --> $DIR/unused_attributes-must_use.rs:33:1
+ |
+LL | #[must_use]
+ | ^^^^^^^^^^^
+
+error: `#[must_use]` has no effect when applied to a foreign module
+ --> $DIR/unused_attributes-must_use.rs:47:1
+ |
+LL | #[must_use]
+ | ^^^^^^^^^^^
+
+error: `#[must_use]` has no effect when applied to a type alias
+ --> $DIR/unused_attributes-must_use.rs:61:1
+ |
+LL | #[must_use]
+ | ^^^^^^^^^^^
+
+error: `#[must_use]` has no effect when applied to a type parameter
+ --> $DIR/unused_attributes-must_use.rs:64:8
+ |
+LL | fn qux<#[must_use] T>(_: T) {}
+ | ^^^^^^^^^^^
+
+error: `#[must_use]` has no effect when applied to an implementation block
+ --> $DIR/unused_attributes-must_use.rs:79:1
+ |
+LL | #[must_use]
+ | ^^^^^^^^^^^
+
+error: `#[must_use]` has no effect when applied to a trait alias
+ --> $DIR/unused_attributes-must_use.rs:84:1
+ |
+LL | #[must_use]
+ | ^^^^^^^^^^^
+
+error: `#[must_use]` has no effect when applied to a macro def
+ --> $DIR/unused_attributes-must_use.rs:87:1
+ |
+LL | #[must_use]
+ | ^^^^^^^^^^^
+
+error: `#[must_use]` has no effect when applied to a statement
+ --> $DIR/unused_attributes-must_use.rs:95:5
+ |
+LL | #[must_use]
+ | ^^^^^^^^^^^
+
+error: `#[must_use]` has no effect when applied to a closure
+ --> $DIR/unused_attributes-must_use.rs:99:13
+ |
+LL | let x = #[must_use]
+ | ^^^^^^^^^^^
+
+error: `#[must_use]` has no effect when applied to an match arm
+ --> $DIR/unused_attributes-must_use.rs:121:9
+ |
+LL | #[must_use]
+ | ^^^^^^^^^^^
+
+error: `#[must_use]` has no effect when applied to a struct field
+ --> $DIR/unused_attributes-must_use.rs:129:28
+ |
+LL | let s = PatternField { #[must_use] foo: 123 };
+ | ^^^^^^^^^^^
+
+error: `#[must_use]` has no effect when applied to a pattern field
+ --> $DIR/unused_attributes-must_use.rs:130:24
+ |
+LL | let PatternField { #[must_use] foo } = s;
+ | ^^^^^^^^^^^
+
+error: `#[must_use]` has no effect when applied to an associated const
+ --> $DIR/unused_attributes-must_use.rs:68:5
+ |
+LL | #[must_use]
+ | ^^^^^^^^^^^
+
+error: `#[must_use]` has no effect when applied to an associated type
+ --> $DIR/unused_attributes-must_use.rs:70:5
+ |
+LL | #[must_use]
+ | ^^^^^^^^^^^
+
+error: `#[must_use]` has no effect when applied to a foreign static item
+ --> $DIR/unused_attributes-must_use.rs:50:5
+ |
+LL | #[must_use]
+ | ^^^^^^^^^^^
+
+error: unused `X` that must be used
+ --> $DIR/unused_attributes-must_use.rs:103:5
+ |
+LL | X;
+ | ^
+ |
+note: the lint level is defined here
+ --> $DIR/unused_attributes-must_use.rs:2:28
+ |
+LL | #![deny(unused_attributes, unused_must_use)]
+ | ^^^^^^^^^^^^^^^
+
+error: unused `Y` that must be used
+ --> $DIR/unused_attributes-must_use.rs:104:5
+ |
+LL | Y::Z;
+ | ^^^^
+
+error: unused `U` that must be used
+ --> $DIR/unused_attributes-must_use.rs:105:5
+ |
+LL | U { unit: () };
+ | ^^^^^^^^^^^^^^
+
+error: unused return value of `U::method` that must be used
+ --> $DIR/unused_attributes-must_use.rs:106:5
+ |
+LL | U::method();
+ | ^^^^^^^^^^^
+
+error: unused return value of `foo` that must be used
+ --> $DIR/unused_attributes-must_use.rs:107:5
+ |
+LL | foo();
+ | ^^^^^
+
+error: unused return value of `foreign_foo` that must be used
+ --> $DIR/unused_attributes-must_use.rs:110:9
+ |
+LL | foreign_foo();
+ | ^^^^^^^^^^^^^
+
+error: unused return value of `Use::get_four` that must be used
+ --> $DIR/unused_attributes-must_use.rs:118:5
+ |
+LL | ().get_four();
+ | ^^^^^^^^^^^^^
+
+error: aborting due to 28 previous errors
+
diff --git a/tests/ui/lint/unused/useless-comment.rs b/tests/ui/lint/unused/useless-comment.rs
new file mode 100644
index 000000000..7d2e5ab6f
--- /dev/null
+++ b/tests/ui/lint/unused/useless-comment.rs
@@ -0,0 +1,45 @@
+#![feature(stmt_expr_attributes)]
+
+#![deny(unused_doc_comments)]
+
+macro_rules! mac {
+ () => {}
+}
+
+/// foo //~ ERROR unused doc comment
+mac!();
+
+fn foo() {
+ /// a //~ ERROR unused doc comment
+ let x = 12;
+
+ /// multi-line //~ unused doc comment
+ /// doc comment
+ /// that is unused
+ match x {
+ /// c //~ ERROR unused doc comment
+ 1 => {},
+ _ => {}
+ }
+
+ /// foo //~ ERROR unused doc comment
+ unsafe {}
+
+ #[doc = "foo"] //~ ERROR unused doc comment
+ #[doc = "bar"] //~ ERROR unused doc comment
+ 3;
+
+ /// bar //~ ERROR unused doc comment
+ mac!();
+
+ let x = /** comment */ 47; //~ ERROR unused doc comment
+
+ /// dox //~ ERROR unused doc comment
+ {
+
+ }
+}
+
+fn main() {
+ foo();
+}
diff --git a/tests/ui/lint/unused/useless-comment.stderr b/tests/ui/lint/unused/useless-comment.stderr
new file mode 100644
index 000000000..8bb5bdaeb
--- /dev/null
+++ b/tests/ui/lint/unused/useless-comment.stderr
@@ -0,0 +1,110 @@
+error: unused doc comment
+ --> $DIR/useless-comment.rs:9:1
+ |
+LL | /// foo
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ rustdoc does not generate documentation for macro invocations
+ |
+ = help: to document an item produced by a macro, the macro must produce the documentation as part of its expansion
+note: the lint level is defined here
+ --> $DIR/useless-comment.rs:3:9
+ |
+LL | #![deny(unused_doc_comments)]
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: unused doc comment
+ --> $DIR/useless-comment.rs:32:5
+ |
+LL | /// bar
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ rustdoc does not generate documentation for macro invocations
+ |
+ = help: to document an item produced by a macro, the macro must produce the documentation as part of its expansion
+
+error: unused doc comment
+ --> $DIR/useless-comment.rs:13:5
+ |
+LL | /// a
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | let x = 12;
+ | ----------- rustdoc does not generate documentation for statements
+ |
+ = help: use `//` for a plain comment
+
+error: unused doc comment
+ --> $DIR/useless-comment.rs:16:5
+ |
+LL | / /// multi-line
+LL | | /// doc comment
+LL | | /// that is unused
+ | |______________________^
+LL | / match x {
+LL | | /// c
+LL | | 1 => {},
+LL | | _ => {}
+LL | | }
+ | |_____- rustdoc does not generate documentation for expressions
+ |
+ = help: use `//` for a plain comment
+
+error: unused doc comment
+ --> $DIR/useless-comment.rs:20:9
+ |
+LL | /// c
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | 1 => {},
+ | ------- rustdoc does not generate documentation for match arms
+ |
+ = help: use `//` for a plain comment
+
+error: unused doc comment
+ --> $DIR/useless-comment.rs:25:5
+ |
+LL | /// foo
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | unsafe {}
+ | --------- rustdoc does not generate documentation for expressions
+ |
+ = help: use `//` for a plain comment
+
+error: unused doc comment
+ --> $DIR/useless-comment.rs:28:5
+ |
+LL | #[doc = "foo"]
+ | ^^^^^^^^^^^^^^
+LL | #[doc = "bar"]
+LL | 3;
+ | - rustdoc does not generate documentation for expressions
+ |
+ = help: use `//` for a plain comment
+
+error: unused doc comment
+ --> $DIR/useless-comment.rs:29:5
+ |
+LL | #[doc = "bar"]
+ | ^^^^^^^^^^^^^^
+LL | 3;
+ | - rustdoc does not generate documentation for expressions
+ |
+ = help: use `//` for a plain comment
+
+error: unused doc comment
+ --> $DIR/useless-comment.rs:35:13
+ |
+LL | let x = /** comment */ 47;
+ | ^^^^^^^^^^^^^^ -- rustdoc does not generate documentation for expressions
+ |
+ = help: use `/* */` for a plain comment
+
+error: unused doc comment
+ --> $DIR/useless-comment.rs:37:5
+ |
+LL | /// dox
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | / {
+LL | |
+LL | | }
+ | |_____- rustdoc does not generate documentation for expressions
+ |
+ = help: use `//` for a plain comment
+
+error: aborting due to 10 previous errors
+