about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-08-05 09:32:26 +0000
committerbors <bors@rust-lang.org>2022-08-05 09:32:26 +0000
commit9bbbf60b0442f1d56fc39f30274be77acc79164c (patch)
tree1ce993d5a0b8f327611f5d4ab57c11ec3bd3c9e6
parentcdfd675a63090182fd1c5f2ff58d8eaa115da156 (diff)
parente3c7e04a4430942205872a8ed3c67531f22985bc (diff)
downloadrust-9bbbf60b0442f1d56fc39f30274be77acc79164c.tar.gz
rust-9bbbf60b0442f1d56fc39f30274be77acc79164c.zip
Auto merge of #95977 - FabianWolff:issue-92790-dead-tuple, r=estebank
Warn about dead tuple struct fields

Continuation of #92972. Fixes #92790.

The language team has already commented on this in https://github.com/rust-lang/rust/pull/92972#issuecomment-1021511970; I have incorporated their requests here. Specifically, there is now a new allow-by-default `unused_tuple_struct_fields` lint (name bikesheddable), and fields of unit type are ignored (https://github.com/rust-lang/rust/pull/92972#issuecomment-1021815408), so error messages look like this:
```
error: field is never read: `1`
  --> $DIR/tuple-struct-field.rs:6:21
   |
LL | struct Wrapper(i32, [u8; LEN], String);
   |                     ^^^^^^^^^
   |
help: change the field to unit type to suppress this warning while preserving the field numbering
   |
LL | struct Wrapper(i32, (), String);
   |                     ~~
```
r? `@joshtriplett`
-rw-r--r--compiler/rustc_apfloat/src/ppc.rs4
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs27
-rw-r--r--compiler/rustc_passes/src/check_attr.rs9
-rw-r--r--compiler/rustc_passes/src/dead.rs129
-rw-r--r--src/test/codegen-units/item-collection/generic-drop-glue.rs4
-rw-r--r--src/test/codegen-units/item-collection/transitive-drop-glue.rs10
-rw-r--r--src/test/codegen-units/item-collection/unsizing.rs2
-rw-r--r--src/test/run-make-fulldeps/issues-41478-43796/a.rs2
-rw-r--r--src/test/ui/align-with-extern-c-fn.rs2
-rw-r--r--src/test/ui/allocator/no_std-alloc-error-handler-custom.rs2
-rw-r--r--src/test/ui/allocator/no_std-alloc-error-handler-default.rs2
-rw-r--r--src/test/ui/array-slice-vec/show-boxed-slice.rs2
-rw-r--r--src/test/ui/associated-consts/associated-const-type-parameters.rs2
-rw-r--r--src/test/ui/associated-type-bounds/enum-bounds.rs1
-rw-r--r--src/test/ui/associated-types/associated-types-method.rs1
-rw-r--r--src/test/ui/associated-types/associated-types-struct-field-numbered.rs2
-rw-r--r--src/test/ui/async-await/async-fn-size-moved-locals.rs2
-rw-r--r--src/test/ui/async-await/async-fn-size-uninit-locals.rs2
-rw-r--r--src/test/ui/auto-traits/auto-traits.rs2
-rw-r--r--src/test/ui/bench/issue-32062.rs4
-rw-r--r--src/test/ui/binding/match-tag.rs2
-rw-r--r--src/test/ui/binding/or-pattern.rs2
-rw-r--r--src/test/ui/binding/simple-generic-match.rs2
-rw-r--r--src/test/ui/builtin-superkinds/builtin-superkinds-in-metadata2.rs2
-rw-r--r--src/test/ui/chalkify/builtin-copy-clone.rs2
-rw-r--r--src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.fixed4
-rw-r--r--src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.rs4
-rw-r--r--src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.fixed2
-rw-r--r--src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.rs2
-rw-r--r--src/test/ui/codegen/issue-16602-3.rs1
-rw-r--r--src/test/ui/coercion/issue-14589.rs2
-rw-r--r--src/test/ui/const-generics/conservative_is_privately_uninhabited_uses_correct_param_env-1.rs1
-rw-r--r--src/test/ui/const-generics/conservative_is_privately_uninhabited_uses_correct_param_env-2.rs1
-rw-r--r--src/test/ui/const-generics/const-argument-cross-crate.rs2
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/associated-consts.rs2
-rw-r--r--src/test/ui/consts/assoc-const.rs2
-rw-r--r--src/test/ui/consts/const-needs_drop.rs2
-rw-r--r--src/test/ui/consts/const-size_of_val-align_of_val.rs2
-rw-r--r--src/test/ui/consts/const_in_pattern/warn_corner_cases.rs2
-rw-r--r--src/test/ui/consts/issue-70773-mir-typeck-lt-norm.rs2
-rw-r--r--src/test/ui/consts/rvalue-static-promotion.rs2
-rw-r--r--src/test/ui/consts/transmute-const.rs2
-rw-r--r--src/test/ui/deriving/deriving-clone-generic-tuple-struct.rs1
-rw-r--r--src/test/ui/deriving/deriving-copyclone.rs2
-rw-r--r--src/test/ui/deriving/issue-58319.rs1
-rw-r--r--src/test/ui/drop/dropck-eyepatch-reorder.rs8
-rw-r--r--src/test/ui/drop/dropck-eyepatch.rs8
-rw-r--r--src/test/ui/drop/dynamic-drop.rs2
-rw-r--r--src/test/ui/dropck/issue-28498-ugeh-with-passed-to-fn.rs2
-rw-r--r--src/test/ui/enum-discriminant/discriminant_value-wrapper.rs1
-rw-r--r--src/test/ui/enum-discriminant/discriminant_value.rs3
-rw-r--r--src/test/ui/generator/size-moved-locals.rs2
-rw-r--r--src/test/ui/generics/generic-default-type-params-cross-crate.rs2
-rw-r--r--src/test/ui/generics/generic-ivec-leak.rs2
-rw-r--r--src/test/ui/generics/generic-newtype-struct.rs2
-rw-r--r--src/test/ui/generics/generic-no-mangle.fixed4
-rw-r--r--src/test/ui/generics/generic-no-mangle.rs4
-rw-r--r--src/test/ui/generics/generic-recursive-tag.rs2
-rw-r--r--src/test/ui/generics/generic-tag-corruption.rs2
-rw-r--r--src/test/ui/generics/generic-tag-local.rs2
-rw-r--r--src/test/ui/generics/generic-tag.rs2
-rw-r--r--src/test/ui/impl-trait/bounds_regression.rs2
-rw-r--r--src/test/ui/issues/issue-13027.rs2
-rw-r--r--src/test/ui/issues/issue-14382.rs2
-rw-r--r--src/test/ui/issues/issue-15858.rs2
-rw-r--r--src/test/ui/issues/issue-17905.rs1
-rw-r--r--src/test/ui/issues/issue-2063.rs2
-rw-r--r--src/test/ui/issues/issue-23491.rs2
-rw-r--r--src/test/ui/issues/issue-24308.rs2
-rw-r--r--src/test/ui/issues/issue-24805-dropck-itemless.rs2
-rw-r--r--src/test/ui/issues/issue-25089.rs2
-rw-r--r--src/test/ui/issues/issue-25679.rs1
-rw-r--r--src/test/ui/issues/issue-25700-1.rs2
-rw-r--r--src/test/ui/issues/issue-25700-2.rs3
-rw-r--r--src/test/ui/issues/issue-25700.rs2
-rw-r--r--src/test/ui/issues/issue-26127.rs2
-rw-r--r--src/test/ui/issues/issue-26641.rs2
-rw-r--r--src/test/ui/issues/issue-26709.rs2
-rw-r--r--src/test/ui/issues/issue-27240.rs5
-rw-r--r--src/test/ui/issues/issue-28498-must-work-ex1.rs2
-rw-r--r--src/test/ui/issues/issue-28498-must-work-ex2.rs2
-rw-r--r--src/test/ui/issues/issue-28498-ugeh-ex1.rs2
-rw-r--r--src/test/ui/issues/issue-29147-rpass.rs1
-rw-r--r--src/test/ui/issues/issue-29147.rs1
-rw-r--r--src/test/ui/issues/issue-29147.stderr4
-rw-r--r--src/test/ui/issues/issue-31267-additional.rs2
-rw-r--r--src/test/ui/issues/issue-31299.rs4
-rw-r--r--src/test/ui/issues/issue-34571.rs2
-rw-r--r--src/test/ui/issues/issue-36053.rs2
-rw-r--r--src/test/ui/issues/issue-36278-prefix-nesting.rs1
-rw-r--r--src/test/ui/issues/issue-40003.rs2
-rw-r--r--src/test/ui/issues/issue-4252.rs2
-rw-r--r--src/test/ui/issues/issue-46069.rs2
-rw-r--r--src/test/ui/issues/issue-5315.rs2
-rw-r--r--src/test/ui/issues/issue-61894.rs2
-rw-r--r--src/test/ui/issues/issue-7911.rs2
-rw-r--r--src/test/ui/layout/unsafe-cell-hides-niche.rs4
-rw-r--r--src/test/ui/lint/dead-code/tuple-struct-field.rs35
-rw-r--r--src/test/ui/lint/dead-code/tuple-struct-field.stderr33
-rw-r--r--src/test/ui/lint/dead-code/with-impl.rs2
-rw-r--r--src/test/ui/list.rs2
-rw-r--r--src/test/ui/macros/html-literals.rs1
-rw-r--r--src/test/ui/macros/macro-tt-followed-by-seq.rs1
-rw-r--r--src/test/ui/methods/method-argument-inference-associated-type.rs2
-rw-r--r--src/test/ui/methods/method-probe-no-guessing-dyn-trait.rs4
-rw-r--r--src/test/ui/mir/mir_codegen_switch.rs4
-rw-r--r--src/test/ui/mir/mir_fat_ptr.rs2
-rw-r--r--src/test/ui/mir/mir_raw_fat_ptr.rs1
-rw-r--r--src/test/ui/mir/mir_refs_correct.rs4
-rw-r--r--src/test/ui/nullable-pointer-iotareduction.rs2
-rw-r--r--src/test/ui/optimization-fuel-0.rs2
-rw-r--r--src/test/ui/optimization-fuel-1.rs2
-rw-r--r--src/test/ui/packed/packed-struct-drop-aligned.rs2
-rw-r--r--src/test/ui/packed/packed-struct-optimized-enum.rs2
-rw-r--r--src/test/ui/packed/packed-tuple-struct-layout.rs2
-rw-r--r--src/test/ui/parser/issues/issue-70388-without-witness.fixed2
-rw-r--r--src/test/ui/parser/issues/issue-70388-without-witness.rs2
-rw-r--r--src/test/ui/range_inclusive.rs2
-rw-r--r--src/test/ui/recursion/issue-26548-recursion-via-normalize.rs10
-rw-r--r--src/test/ui/recursion/issue-26548-recursion-via-normalize.stderr12
-rw-r--r--src/test/ui/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-direct-unsafe-ptr-embedded.rs2
-rw-r--r--src/test/ui/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-direct-unsafe-ptr-param.rs2
-rw-r--r--src/test/ui/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-indirect-unsafe-ptr-embedded.rs2
-rw-r--r--src/test/ui/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-indirect-unsafe-ptr-param.rs2
-rw-r--r--src/test/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.rs2
-rw-r--r--src/test/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.rs2
-rw-r--r--src/test/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.rs2
-rw-r--r--src/test/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.rs2
-rw-r--r--src/test/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.rs2
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/const-drop.rs2
-rw-r--r--src/test/ui/rfcs/rfc-2151-raw-identifiers/attr.rs2
-rw-r--r--src/test/ui/specialization/specialization-cross-crate.rs2
-rw-r--r--src/test/ui/specialization/specialization-translate-projections-with-lifetimes.rs2
-rw-r--r--src/test/ui/stdlib-unit-tests/raw-fat-ptr.rs1
-rw-r--r--src/test/ui/struct-ctor-mangling.rs2
-rw-r--r--src/test/ui/structs-enums/enum-null-pointer-opt.rs6
-rw-r--r--src/test/ui/structs-enums/enum-nullable-simplifycfg-misopt.rs2
-rw-r--r--src/test/ui/structs-enums/resource-in-struct.rs2
-rw-r--r--src/test/ui/structs-enums/tuple-struct-construct.rs1
-rw-r--r--src/test/ui/structs-enums/uninstantiable-struct.rs2
-rw-r--r--src/test/ui/trailing-comma.rs4
-rw-r--r--src/test/ui/traits/augmented-assignments-trait.rs2
-rw-r--r--src/test/ui/traits/negative-impls/negated-auto-traits-rpass.rs2
-rw-r--r--src/test/ui/traits/object/exclusion.rs2
-rw-r--r--src/test/ui/traits/object/generics.rs2
-rw-r--r--src/test/ui/traits/pointee-deduction.rs4
-rw-r--r--src/test/ui/traits/principal-less-objects.rs2
-rw-r--r--src/test/ui/type-alias-enum-variants/enum-variant-generic-args-pass.rs2
-rw-r--r--src/test/ui/unboxed-closures/type-id-higher-rank.rs2
-rw-r--r--src/test/ui/unsized-locals/unsized-exprs-rpass.rs2
-rw-r--r--src/test/ui/unsized/unchanged-param.rs4
-rw-r--r--src/tools/clippy/tests/ui/borrow_interior_mutable_const/auxiliary/helper.rs1
-rw-r--r--src/tools/clippy/tests/ui/format.fixed1
-rw-r--r--src/tools/clippy/tests/ui/format.rs1
-rw-r--r--src/tools/clippy/tests/ui/format.stderr38
-rw-r--r--src/tools/clippy/tests/ui/from_iter_instead_of_collect.fixed2
-rw-r--r--src/tools/clippy/tests/ui/from_iter_instead_of_collect.rs2
-rw-r--r--src/tools/clippy/tests/ui/must_use_candidates.fixed2
-rw-r--r--src/tools/clippy/tests/ui/must_use_candidates.rs2
-rw-r--r--src/tools/clippy/tests/ui/numbered_fields.fixed1
-rw-r--r--src/tools/clippy/tests/ui/numbered_fields.rs1
-rw-r--r--src/tools/clippy/tests/ui/numbered_fields.stderr4
-rw-r--r--src/tools/clippy/tests/ui/option_if_let_else.fixed1
-rw-r--r--src/tools/clippy/tests/ui/option_if_let_else.rs1
-rw-r--r--src/tools/clippy/tests/ui/option_if_let_else.stderr30
-rw-r--r--src/tools/clippy/tests/ui/unreadable_literal.fixed1
-rw-r--r--src/tools/clippy/tests/ui/unreadable_literal.rs1
-rw-r--r--src/tools/clippy/tests/ui/unreadable_literal.stderr22
168 files changed, 451 insertions, 246 deletions
diff --git a/compiler/rustc_apfloat/src/ppc.rs b/compiler/rustc_apfloat/src/ppc.rs
index 4ae8edf3157..65a0f66645b 100644
--- a/compiler/rustc_apfloat/src/ppc.rs
+++ b/compiler/rustc_apfloat/src/ppc.rs
@@ -30,7 +30,7 @@ pub type DoubleDouble = DoubleFloat<ieee::Double>;
 // FIXME: Implement all operations in DoubleDouble, and delete these
 // semantics.
 // FIXME(eddyb) This shouldn't need to be `pub`, it's only used in bounds.
-pub struct FallbackS<F>(F);
+pub struct FallbackS<F>(#[allow(unused)] F);
 type Fallback<F> = ieee::IeeeFloat<FallbackS<F>>;
 impl<F: Float> ieee::Semantics for FallbackS<F> {
     // Forbid any conversion to/from bits.
@@ -45,7 +45,7 @@ impl<F: Float> ieee::Semantics for FallbackS<F> {
 // truncate the mantissa. The result of that second conversion
 // may be inexact, but should never underflow.
 // FIXME(eddyb) This shouldn't need to be `pub`, it's only used in bounds.
-pub struct FallbackExtendedS<F>(F);
+pub struct FallbackExtendedS<F>(#[allow(unused)] F);
 type FallbackExtended<F> = ieee::IeeeFloat<FallbackExtendedS<F>>;
 impl<F: Float> ieee::Semantics for FallbackExtendedS<F> {
     // Forbid any conversion to/from bits.
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index 39690851d1e..f00165cd3b3 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -631,6 +631,32 @@ declare_lint! {
 }
 
 declare_lint! {
+    /// The `unused_tuple_struct_fields` lint detects fields of tuple structs
+    /// that are never read.
+    ///
+    /// ### Example
+    ///
+    /// ```
+    /// #[warn(unused_tuple_struct_fields)]
+    /// struct S(i32, i32, i32);
+    /// let s = S(1, 2, 3);
+    /// let _ = (s.0, s.2);
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// Tuple struct fields that are never read anywhere may indicate a
+    /// mistake or unfinished code. To silence this warning, consider
+    /// removing the unused field(s) or, to preserve the numbering of the
+    /// remaining fields, change the unused field(s) to have unit type.
+    pub UNUSED_TUPLE_STRUCT_FIELDS,
+    Allow,
+    "detects tuple struct fields that are never read"
+}
+
+declare_lint! {
     /// The `unreachable_code` lint detects unreachable code paths.
     ///
     /// ### Example
@@ -3281,6 +3307,7 @@ declare_lint_pass! {
         UNSUPPORTED_CALLING_CONVENTIONS,
         BREAK_WITH_LABEL_AND_LOOP,
         UNUSED_ATTRIBUTES,
+        UNUSED_TUPLE_STRUCT_FIELDS,
         NON_EXHAUSTIVE_OMITTED_PATTERNS,
         TEXT_DIRECTION_CODEPOINT_IN_COMMENT,
         DEREF_INTO_DYN_SUPERTRAIT,
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 5b7d44e41cf..a2ac329f28f 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -53,7 +53,7 @@ pub(crate) fn target_from_impl_item<'tcx>(
 #[derive(Clone, Copy)]
 enum ItemLike<'tcx> {
     Item(&'tcx Item<'tcx>),
-    ForeignItem(&'tcx ForeignItem<'tcx>),
+    ForeignItem,
 }
 
 struct CheckAttrVisitor<'tcx> {
@@ -2020,12 +2020,7 @@ impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> {
 
     fn visit_foreign_item(&mut self, f_item: &'tcx ForeignItem<'tcx>) {
         let target = Target::from_foreign_item(f_item);
-        self.check_attributes(
-            f_item.hir_id(),
-            f_item.span,
-            target,
-            Some(ItemLike::ForeignItem(f_item)),
-        );
+        self.check_attributes(f_item.hir_id(), f_item.span, target, Some(ItemLike::ForeignItem));
         intravisit::walk_foreign_item(self, f_item)
     }
 
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index 58c5e5b4dfe..1e2fbeb384c 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -4,7 +4,7 @@
 
 use itertools::Itertools;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_errors::{pluralize, MultiSpan};
+use rustc_errors::{pluralize, Applicability, MultiSpan};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind, Res};
 use rustc_hir::def_id::{DefId, LocalDefId};
@@ -42,6 +42,7 @@ struct MarkSymbolVisitor<'tcx> {
     maybe_typeck_results: Option<&'tcx ty::TypeckResults<'tcx>>,
     live_symbols: FxHashSet<LocalDefId>,
     repr_has_repr_c: bool,
+    repr_has_repr_simd: bool,
     in_pat: bool,
     ignore_variant_stack: Vec<DefId>,
     // maps from tuple struct constructors to tuple struct items
@@ -220,6 +221,32 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
         }
     }
 
+    fn handle_tuple_field_pattern_match(
+        &mut self,
+        lhs: &hir::Pat<'_>,
+        res: Res,
+        pats: &[hir::Pat<'_>],
+        dotdot: Option<usize>,
+    ) {
+        let variant = match self.typeck_results().node_type(lhs.hir_id).kind() {
+            ty::Adt(adt, _) => adt.variant_of_res(res),
+            _ => span_bug!(lhs.span, "non-ADT in tuple struct pattern"),
+        };
+        let first_n = pats.iter().enumerate().take(dotdot.unwrap_or(pats.len()));
+        let missing = variant.fields.len() - pats.len();
+        let last_n = pats
+            .iter()
+            .enumerate()
+            .skip(dotdot.unwrap_or(pats.len()))
+            .map(|(idx, pat)| (idx + missing, pat));
+        for (idx, pat) in first_n.chain(last_n) {
+            if let PatKind::Wild = pat.kind {
+                continue;
+            }
+            self.insert_def_id(variant.fields[idx].did);
+        }
+    }
+
     fn mark_live_symbols(&mut self) {
         let mut scanned = FxHashSet::default();
         while let Some(id) = self.worklist.pop() {
@@ -274,12 +301,15 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
         }
 
         let had_repr_c = self.repr_has_repr_c;
+        let had_repr_simd = self.repr_has_repr_simd;
         self.repr_has_repr_c = false;
+        self.repr_has_repr_simd = false;
         match node {
             Node::Item(item) => match item.kind {
                 hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => {
                     let def = self.tcx.adt_def(item.def_id);
                     self.repr_has_repr_c = def.repr().c();
+                    self.repr_has_repr_simd = def.repr().simd();
 
                     intravisit::walk_item(self, &item)
                 }
@@ -315,6 +345,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
             }
             _ => {}
         }
+        self.repr_has_repr_simd = had_repr_simd;
         self.repr_has_repr_c = had_repr_c;
     }
 
@@ -347,9 +378,10 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
     ) {
         let tcx = self.tcx;
         let has_repr_c = self.repr_has_repr_c;
+        let has_repr_simd = self.repr_has_repr_simd;
         let live_fields = def.fields().iter().filter_map(|f| {
             let def_id = tcx.hir().local_def_id(f.hir_id);
-            if has_repr_c {
+            if has_repr_c || (f.is_positional() && has_repr_simd) {
                 return Some(def_id);
             }
             if !tcx.visibility(f.hir_id.owner).is_public() {
@@ -408,6 +440,10 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
                 let res = self.typeck_results().qpath_res(qpath, pat.hir_id);
                 self.handle_res(res);
             }
+            PatKind::TupleStruct(ref qpath, ref fields, dotdot) => {
+                let res = self.typeck_results().qpath_res(qpath, pat.hir_id);
+                self.handle_tuple_field_pattern_match(pat, res, fields, dotdot);
+            }
             _ => (),
         }
 
@@ -440,7 +476,11 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
     }
 }
 
-fn has_allow_dead_code_or_lang_attr(tcx: TyCtxt<'_>, id: hir::HirId) -> bool {
+fn has_allow_dead_code_or_lang_attr_helper(
+    tcx: TyCtxt<'_>,
+    id: hir::HirId,
+    lint: &'static lint::Lint,
+) -> bool {
     let attrs = tcx.hir().attrs(id);
     if tcx.sess.contains_name(attrs, sym::lang) {
         return true;
@@ -470,7 +510,11 @@ fn has_allow_dead_code_or_lang_attr(tcx: TyCtxt<'_>, id: hir::HirId) -> bool {
         }
     }
 
-    tcx.lint_level_at_node(lint::builtin::DEAD_CODE, id).0 == lint::Allow
+    tcx.lint_level_at_node(lint, id).0 == lint::Allow
+}
+
+fn has_allow_dead_code_or_lang_attr(tcx: TyCtxt<'_>, id: hir::HirId) -> bool {
+    has_allow_dead_code_or_lang_attr_helper(tcx, id, lint::builtin::DEAD_CODE)
 }
 
 // These check_* functions seeds items that
@@ -623,6 +667,7 @@ fn live_symbols_and_ignored_derived_traits<'tcx>(
         maybe_typeck_results: None,
         live_symbols: Default::default(),
         repr_has_repr_c: false,
+        repr_has_repr_simd: false,
         in_pat: false,
         ignore_variant_stack: vec![],
         struct_constructors,
@@ -644,17 +689,30 @@ struct DeadVisitor<'tcx> {
     ignored_derived_traits: &'tcx FxHashMap<LocalDefId, Vec<(DefId, DefId)>>,
 }
 
+enum ShouldWarnAboutField {
+    Yes(bool), // positional?
+    No,
+}
+
 impl<'tcx> DeadVisitor<'tcx> {
-    fn should_warn_about_field(&mut self, field: &ty::FieldDef) -> bool {
+    fn should_warn_about_field(&mut self, field: &ty::FieldDef) -> ShouldWarnAboutField {
         if self.live_symbols.contains(&field.did.expect_local()) {
-            return false;
+            return ShouldWarnAboutField::No;
+        }
+        let field_type = self.tcx.type_of(field.did);
+        if field_type.is_phantom_data() {
+            return ShouldWarnAboutField::No;
         }
         let is_positional = field.name.as_str().starts_with(|c: char| c.is_ascii_digit());
-        if is_positional {
-            return false;
+        if is_positional
+            && self
+                .tcx
+                .layout_of(self.tcx.param_env(field.did).and(field_type))
+                .map_or(true, |layout| layout.is_zst())
+        {
+            return ShouldWarnAboutField::No;
         }
-        let field_type = self.tcx.type_of(field.did);
-        !field_type.is_phantom_data()
+        ShouldWarnAboutField::Yes(is_positional)
     }
 
     fn warn_multiple_dead_codes(
@@ -662,6 +720,7 @@ impl<'tcx> DeadVisitor<'tcx> {
         dead_codes: &[LocalDefId],
         participle: &str,
         parent_item: Option<LocalDefId>,
+        is_positional: bool,
     ) {
         if let Some(&first_id) = dead_codes.first() {
             let tcx = self.tcx;
@@ -669,7 +728,7 @@ impl<'tcx> DeadVisitor<'tcx> {
                 .iter()
                 .map(|&def_id| tcx.item_name(def_id.to_def_id()).to_string())
                 .collect();
-            let spans = dead_codes
+            let spans: Vec<_> = dead_codes
                 .iter()
                 .map(|&def_id| match tcx.def_ident_span(def_id) {
                     Some(s) => s.with_ctxt(tcx.def_span(def_id).ctxt()),
@@ -678,9 +737,13 @@ impl<'tcx> DeadVisitor<'tcx> {
                 .collect();
 
             tcx.struct_span_lint_hir(
-                lint::builtin::DEAD_CODE,
+                if is_positional {
+                    lint::builtin::UNUSED_TUPLE_STRUCT_FIELDS
+                } else {
+                    lint::builtin::DEAD_CODE
+                },
                 tcx.hir().local_def_id_to_hir_id(first_id),
-                MultiSpan::from_spans(spans),
+                MultiSpan::from_spans(spans.clone()),
                 |lint| {
                     let descr = tcx.def_kind(first_id).descr(first_id.to_def_id());
                     let span_len = dead_codes.len();
@@ -702,6 +765,21 @@ impl<'tcx> DeadVisitor<'tcx> {
                         are = pluralize!("is", span_len),
                     ));
 
+                    if is_positional {
+                        err.multipart_suggestion(
+                            &format!(
+                                "consider changing the field{s} to be of unit type to \
+                                      suppress this warning while preserving the field \
+                                      numbering, or remove the field{s}",
+                                s = pluralize!(span_len)
+                            ),
+                            spans.iter().map(|sp| (*sp, "()".to_string())).collect(),
+                            // "HasPlaceholders" because applying this fix by itself isn't
+                            // enough: All constructor calls have to be adjusted as well
+                            Applicability::HasPlaceholders,
+                        );
+                    }
+
                     if let Some(parent_item) = parent_item {
                         let parent_descr = tcx.def_kind(parent_item).descr(parent_item.to_def_id());
                         err.span_label(
@@ -743,6 +821,7 @@ impl<'tcx> DeadVisitor<'tcx> {
         def_id: LocalDefId,
         participle: &str,
         dead_codes: Vec<DeadVariant>,
+        is_positional: bool,
     ) {
         let mut dead_codes = dead_codes
             .iter()
@@ -758,12 +837,13 @@ impl<'tcx> DeadVisitor<'tcx> {
                 &group.map(|v| v.def_id).collect::<Vec<_>>(),
                 participle,
                 Some(def_id),
+                is_positional,
             );
         }
     }
 
     fn warn_dead_code(&mut self, id: LocalDefId, participle: &str) {
-        self.warn_multiple_dead_codes(&[id], participle, None);
+        self.warn_multiple_dead_codes(&[id], participle, None, false);
     }
 
     fn check_definition(&mut self, def_id: LocalDefId) {
@@ -829,24 +909,37 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalDefId) {
                     continue;
                 }
 
+                let mut is_positional = false;
                 let dead_fields = variant
                     .fields
                     .iter()
                     .filter_map(|field| {
                         let def_id = field.did.expect_local();
                         let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
-                        if visitor.should_warn_about_field(&field) {
-                            let level = tcx.lint_level_at_node(lint::builtin::DEAD_CODE, hir_id).0;
+                        if let ShouldWarnAboutField::Yes(is_pos) =
+                            visitor.should_warn_about_field(&field)
+                        {
+                            let level = tcx
+                                .lint_level_at_node(
+                                    if is_pos {
+                                        is_positional = true;
+                                        lint::builtin::UNUSED_TUPLE_STRUCT_FIELDS
+                                    } else {
+                                        lint::builtin::DEAD_CODE
+                                    },
+                                    hir_id,
+                                )
+                                .0;
                             Some(DeadVariant { def_id, name: field.name, level })
                         } else {
                             None
                         }
                     })
                     .collect();
-                visitor.warn_dead_fields_and_variants(def_id, "read", dead_fields)
+                visitor.warn_dead_fields_and_variants(def_id, "read", dead_fields, is_positional)
             }
 
-            visitor.warn_dead_fields_and_variants(item.def_id, "constructed", dead_variants);
+            visitor.warn_dead_fields_and_variants(item.def_id, "constructed", dead_variants, false);
         }
     }
 
diff --git a/src/test/codegen-units/item-collection/generic-drop-glue.rs b/src/test/codegen-units/item-collection/generic-drop-glue.rs
index 25cf5dad614..6df4ff7e58b 100644
--- a/src/test/codegen-units/item-collection/generic-drop-glue.rs
+++ b/src/test/codegen-units/item-collection/generic-drop-glue.rs
@@ -34,9 +34,9 @@ enum EnumNoDrop<T1, T2> {
 }
 
 
-struct NonGenericNoDrop(i32);
+struct NonGenericNoDrop(#[allow(unused_tuple_struct_fields)] i32);
 
-struct NonGenericWithDrop(i32);
+struct NonGenericWithDrop(#[allow(unused_tuple_struct_fields)] i32);
 //~ MONO_ITEM fn std::ptr::drop_in_place::<NonGenericWithDrop> - shim(Some(NonGenericWithDrop)) @@ generic_drop_glue-cgu.0[Internal]
 
 impl Drop for NonGenericWithDrop {
diff --git a/src/test/codegen-units/item-collection/transitive-drop-glue.rs b/src/test/codegen-units/item-collection/transitive-drop-glue.rs
index 8249e7cba94..e286c800b7c 100644
--- a/src/test/codegen-units/item-collection/transitive-drop-glue.rs
+++ b/src/test/codegen-units/item-collection/transitive-drop-glue.rs
@@ -6,9 +6,9 @@
 #![feature(start)]
 
 //~ MONO_ITEM fn std::ptr::drop_in_place::<Root> - shim(Some(Root)) @@ transitive_drop_glue-cgu.0[Internal]
-struct Root(Intermediate);
+struct Root(#[allow(unused_tuple_struct_fields)] Intermediate);
 //~ MONO_ITEM fn std::ptr::drop_in_place::<Intermediate> - shim(Some(Intermediate)) @@ transitive_drop_glue-cgu.0[Internal]
-struct Intermediate(Leaf);
+struct Intermediate(#[allow(unused_tuple_struct_fields)] Leaf);
 //~ MONO_ITEM fn std::ptr::drop_in_place::<Leaf> - shim(Some(Leaf)) @@ transitive_drop_glue-cgu.0[Internal]
 struct Leaf;
 
@@ -17,9 +17,9 @@ impl Drop for Leaf {
     fn drop(&mut self) {}
 }
 
-struct RootGen<T>(IntermediateGen<T>);
-struct IntermediateGen<T>(LeafGen<T>);
-struct LeafGen<T>(T);
+struct RootGen<T>(#[allow(unused_tuple_struct_fields)] IntermediateGen<T>);
+struct IntermediateGen<T>(#[allow(unused_tuple_struct_fields)] LeafGen<T>);
+struct LeafGen<T>(#[allow(unused_tuple_struct_fields)] T);
 
 impl<T> Drop for LeafGen<T> {
     fn drop(&mut self) {}
diff --git a/src/test/codegen-units/item-collection/unsizing.rs b/src/test/codegen-units/item-collection/unsizing.rs
index 81675377941..111a7231209 100644
--- a/src/test/codegen-units/item-collection/unsizing.rs
+++ b/src/test/codegen-units/item-collection/unsizing.rs
@@ -40,7 +40,7 @@ impl Trait for u32 {
 }
 
 #[derive(Clone, Copy)]
-struct Wrapper<T: ?Sized>(*const T);
+struct Wrapper<T: ?Sized>(#[allow(unused_tuple_struct_fields)] *const T);
 
 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Wrapper<U>> for Wrapper<T> {}
 
diff --git a/src/test/run-make-fulldeps/issues-41478-43796/a.rs b/src/test/run-make-fulldeps/issues-41478-43796/a.rs
index fd67221144a..b072235b5bc 100644
--- a/src/test/run-make-fulldeps/issues-41478-43796/a.rs
+++ b/src/test/run-make-fulldeps/issues-41478-43796/a.rs
@@ -1,5 +1,5 @@
 #![crate_type = "lib"]
-pub struct V<S>(S);
+pub struct V<S>(#[allow(unused_tuple_struct_fields)] S);
 pub trait An {
     type U;
 }
diff --git a/src/test/ui/align-with-extern-c-fn.rs b/src/test/ui/align-with-extern-c-fn.rs
index f77f40998de..9e490e27ad1 100644
--- a/src/test/ui/align-with-extern-c-fn.rs
+++ b/src/test/ui/align-with-extern-c-fn.rs
@@ -8,7 +8,7 @@
 #![feature(repr_align)]
 
 #[repr(align(16))]
-pub struct A(i64);
+pub struct A(#[allow(unused_tuple_struct_fields)] i64);
 
 #[allow(improper_ctypes_definitions)]
 pub extern "C" fn foo(x: A) {}
diff --git a/src/test/ui/allocator/no_std-alloc-error-handler-custom.rs b/src/test/ui/allocator/no_std-alloc-error-handler-custom.rs
index c9b4abbfd3f..54b7c8bb9c6 100644
--- a/src/test/ui/allocator/no_std-alloc-error-handler-custom.rs
+++ b/src/test/ui/allocator/no_std-alloc-error-handler-custom.rs
@@ -92,7 +92,7 @@ fn panic(panic_info: &core::panic::PanicInfo) -> ! {
 extern fn rust_eh_personality() {}
 
 #[derive(Debug)]
-struct Page([[u64; 32]; 16]);
+struct Page(#[allow(unused_tuple_struct_fields)] [[u64; 32]; 16]);
 
 #[start]
 pub fn main(_argc: isize, _argv: *const *const u8) -> isize {
diff --git a/src/test/ui/allocator/no_std-alloc-error-handler-default.rs b/src/test/ui/allocator/no_std-alloc-error-handler-default.rs
index d6cd4a6af85..ffa331a992c 100644
--- a/src/test/ui/allocator/no_std-alloc-error-handler-default.rs
+++ b/src/test/ui/allocator/no_std-alloc-error-handler-default.rs
@@ -79,7 +79,7 @@ fn panic(panic_info: &core::panic::PanicInfo) -> ! {
 extern fn rust_eh_personality() {}
 
 #[derive(Debug)]
-struct Page([[u64; 32]; 16]);
+struct Page(#[allow(unused_tuple_struct_fields)] [[u64; 32]; 16]);
 
 #[start]
 pub fn main(_argc: isize, _argv: *const *const u8) -> isize {
diff --git a/src/test/ui/array-slice-vec/show-boxed-slice.rs b/src/test/ui/array-slice-vec/show-boxed-slice.rs
index dfa4c720bb0..c10f779b1f6 100644
--- a/src/test/ui/array-slice-vec/show-boxed-slice.rs
+++ b/src/test/ui/array-slice-vec/show-boxed-slice.rs
@@ -1,7 +1,7 @@
 // run-pass
 
 #[derive(Debug)]
-struct Foo(Box<[u8]>);
+struct Foo(#[allow(unused_tuple_struct_fields)] Box<[u8]>);
 
 pub fn main() {
     println!("{:?}", Foo(Box::new([0, 1, 2])));
diff --git a/src/test/ui/associated-consts/associated-const-type-parameters.rs b/src/test/ui/associated-consts/associated-const-type-parameters.rs
index 47c3313ec28..e7ead1045e6 100644
--- a/src/test/ui/associated-consts/associated-const-type-parameters.rs
+++ b/src/test/ui/associated-consts/associated-const-type-parameters.rs
@@ -17,7 +17,7 @@ impl Foo for Def {
     const X: i32 = 97;
 }
 
-struct Proxy<T>(T);
+struct Proxy<T>(#[allow(unused_tuple_struct_fields)] T);
 
 impl<T: Foo> Foo for Proxy<T> {
     const X: i32 = T::X;
diff --git a/src/test/ui/associated-type-bounds/enum-bounds.rs b/src/test/ui/associated-type-bounds/enum-bounds.rs
index a6b0bb7070b..193f2efe199 100644
--- a/src/test/ui/associated-type-bounds/enum-bounds.rs
+++ b/src/test/ui/associated-type-bounds/enum-bounds.rs
@@ -1,6 +1,7 @@
 // run-pass
 
 #![feature(associated_type_bounds)]
+#![allow(dead_code)]
 
 trait Tr1 { type As1; }
 trait Tr2 { type As2; }
diff --git a/src/test/ui/associated-types/associated-types-method.rs b/src/test/ui/associated-types/associated-types-method.rs
index 64132cfeed7..45df3ac20c2 100644
--- a/src/test/ui/associated-types/associated-types-method.rs
+++ b/src/test/ui/associated-types/associated-types-method.rs
@@ -5,6 +5,7 @@
 trait Device {
     type Resources;
 }
+#[allow(unused_tuple_struct_fields)]
 struct Foo<D, R>(D, R);
 
 trait Tr {
diff --git a/src/test/ui/associated-types/associated-types-struct-field-numbered.rs b/src/test/ui/associated-types/associated-types-struct-field-numbered.rs
index fa59060629d..8612911d8f8 100644
--- a/src/test/ui/associated-types/associated-types-struct-field-numbered.rs
+++ b/src/test/ui/associated-types/associated-types-struct-field-numbered.rs
@@ -9,7 +9,7 @@ pub trait UnifyKey {
     fn dummy(&self) { }
 }
 
-pub struct Node<K:UnifyKey>(K, K::Value);
+pub struct Node<K:UnifyKey>(#[allow(unused_tuple_struct_fields)] K, K::Value);
 
 fn foo<K : UnifyKey<Value=Option<V>>,V : Clone>(node: &Node<K>) -> Option<V> {
     node.1.clone()
diff --git a/src/test/ui/async-await/async-fn-size-moved-locals.rs b/src/test/ui/async-await/async-fn-size-moved-locals.rs
index a603ebd6e85..15566256600 100644
--- a/src/test/ui/async-await/async-fn-size-moved-locals.rs
+++ b/src/test/ui/async-await/async-fn-size-moved-locals.rs
@@ -17,7 +17,7 @@ use std::pin::Pin;
 use std::task::{Context, Poll};
 
 const BIG_FUT_SIZE: usize = 1024;
-struct BigFut([u8; BIG_FUT_SIZE]);
+struct BigFut(#[allow(unused_tuple_struct_fields)] [u8; BIG_FUT_SIZE]);
 
 impl BigFut {
     fn new() -> Self {
diff --git a/src/test/ui/async-await/async-fn-size-uninit-locals.rs b/src/test/ui/async-await/async-fn-size-uninit-locals.rs
index d5d7b3fc3f0..31a086ba975 100644
--- a/src/test/ui/async-await/async-fn-size-uninit-locals.rs
+++ b/src/test/ui/async-await/async-fn-size-uninit-locals.rs
@@ -16,7 +16,7 @@ use std::pin::Pin;
 use std::task::{Context, Poll};
 
 const BIG_FUT_SIZE: usize = 1024;
-struct Big([u8; BIG_FUT_SIZE]);
+struct Big(#[allow(unused_tuple_struct_fields)] [u8; BIG_FUT_SIZE]);
 
 impl Big {
     fn new() -> Self {
diff --git a/src/test/ui/auto-traits/auto-traits.rs b/src/test/ui/auto-traits/auto-traits.rs
index 567b86c2762..7b52d9c176e 100644
--- a/src/test/ui/auto-traits/auto-traits.rs
+++ b/src/test/ui/auto-traits/auto-traits.rs
@@ -9,7 +9,7 @@ unsafe auto trait AutoUnsafe {}
 impl !Auto for bool {}
 impl !AutoUnsafe for bool {}
 
-struct AutoBool(bool);
+struct AutoBool(#[allow(unused_tuple_struct_fields)] bool);
 
 impl Auto for AutoBool {}
 unsafe impl AutoUnsafe for AutoBool {}
diff --git a/src/test/ui/bench/issue-32062.rs b/src/test/ui/bench/issue-32062.rs
index dc45061da5b..7eb52196e16 100644
--- a/src/test/ui/bench/issue-32062.rs
+++ b/src/test/ui/bench/issue-32062.rs
@@ -15,7 +15,7 @@ trait Parser {
     }
 }
 
-struct Token<T>(T::Item) where T: Iterator;
+struct Token<T>(#[allow(unused_tuple_struct_fields)] T::Item) where T: Iterator;
 
 impl<T> Parser for Token<T> where T: Iterator {
     type Input = T;
@@ -25,7 +25,7 @@ impl<T> Parser for Token<T> where T: Iterator {
     }
 }
 
-struct Chain<L, R>(L, R);
+struct Chain<L, R>(#[allow(unused_tuple_struct_fields)] L, #[allow(unused_tuple_struct_fields)] R);
 
 impl<L, R> Parser for Chain<L, R> where L: Parser, R: Parser<Input = L::Input> {
     type Input = L::Input;
diff --git a/src/test/ui/binding/match-tag.rs b/src/test/ui/binding/match-tag.rs
index eceb6467784..407716aa28a 100644
--- a/src/test/ui/binding/match-tag.rs
+++ b/src/test/ui/binding/match-tag.rs
@@ -3,7 +3,7 @@
 #![allow(non_camel_case_types)]
 
 
-
+#[allow(unused_tuple_struct_fields)]
 enum color {
     rgb(isize, isize, isize),
     rgba(isize, isize, isize, isize),
diff --git a/src/test/ui/binding/or-pattern.rs b/src/test/ui/binding/or-pattern.rs
index 2ab44a96c3a..47623a3d722 100644
--- a/src/test/ui/binding/or-pattern.rs
+++ b/src/test/ui/binding/or-pattern.rs
@@ -1,7 +1,7 @@
 // run-pass
 #![allow(non_camel_case_types)]
 
-enum blah { a(isize, isize, usize), b(isize, isize), c, }
+enum blah { a(isize, isize, #[allow(unused_tuple_struct_fields)] usize), b(isize, isize), c, }
 
 fn or_alt(q: blah) -> isize {
     match q { blah::a(x, y, _) | blah::b(x, y) => { return x + y; } blah::c => { return 0; } }
diff --git a/src/test/ui/binding/simple-generic-match.rs b/src/test/ui/binding/simple-generic-match.rs
index 50cfe19fef4..2cf050d011d 100644
--- a/src/test/ui/binding/simple-generic-match.rs
+++ b/src/test/ui/binding/simple-generic-match.rs
@@ -3,6 +3,6 @@
 
 // pretty-expanded FIXME #23616
 
-enum clam<T> { a(T), }
+enum clam<T> { a(#[allow(unused_tuple_struct_fields)] T), }
 
 pub fn main() { let c = clam::a(2); match c { clam::a::<isize>(_) => { } } }
diff --git a/src/test/ui/builtin-superkinds/builtin-superkinds-in-metadata2.rs b/src/test/ui/builtin-superkinds/builtin-superkinds-in-metadata2.rs
index 117014b44ee..cdde48871ea 100644
--- a/src/test/ui/builtin-superkinds/builtin-superkinds-in-metadata2.rs
+++ b/src/test/ui/builtin-superkinds/builtin-superkinds-in-metadata2.rs
@@ -12,7 +12,7 @@ use trait_superkinds_in_metadata::RequiresCopy;
 use std::marker;
 
 #[derive(Copy, Clone)]
-struct X<T>(T);
+struct X<T>(#[allow(unused_tuple_struct_fields)] T);
 
 impl<T:Sync> RequiresShare for X<T> { }
 
diff --git a/src/test/ui/chalkify/builtin-copy-clone.rs b/src/test/ui/chalkify/builtin-copy-clone.rs
index 4323e87b08d..7712e946542 100644
--- a/src/test/ui/chalkify/builtin-copy-clone.rs
+++ b/src/test/ui/chalkify/builtin-copy-clone.rs
@@ -4,7 +4,7 @@
 // Test that `Clone` is correctly implemented for builtin types.
 
 #[derive(Copy, Clone)]
-struct S(i32);
+struct S(#[allow(unused_tuple_struct_fields)] i32);
 
 fn test_clone<T: Clone>(arg: T) {
     let _ = arg.clone();
diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.fixed b/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.fixed
index 2b86b0ddade..173dd2e2cff 100644
--- a/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.fixed
+++ b/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.fixed
@@ -18,10 +18,10 @@ impl Foo {
     }
 }
 
-struct S(Foo);
+struct S(#[allow(unused_tuple_struct_fields)] Foo);
 
 #[derive(Clone)]
-struct T(i32);
+struct T(#[allow(unused_tuple_struct_fields)] i32);
 
 struct U(S, T);
 
diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.rs b/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.rs
index 3cac4abfad7..cfc4555ca03 100644
--- a/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.rs
+++ b/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.rs
@@ -18,10 +18,10 @@ impl Foo {
     }
 }
 
-struct S(Foo);
+struct S(#[allow(unused_tuple_struct_fields)] Foo);
 
 #[derive(Clone)]
-struct T(i32);
+struct T(#[allow(unused_tuple_struct_fields)] i32);
 
 struct U(S, T);
 
diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.fixed b/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.fixed
index 63e4000e833..e99dbb5ab3a 100644
--- a/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.fixed
+++ b/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.fixed
@@ -13,7 +13,7 @@ impl Drop for Foo {
 }
 
 #[derive(Debug)]
-struct ConstainsDropField(Foo, Foo);
+struct ConstainsDropField(Foo, #[allow(unused_tuple_struct_fields)] Foo);
 
 // `t` needs Drop because one of its elements needs drop,
 // therefore precise capture might affect drop ordering
diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.rs b/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.rs
index 9d9c54298cf..62a984c9eeb 100644
--- a/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.rs
+++ b/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.rs
@@ -13,7 +13,7 @@ impl Drop for Foo {
 }
 
 #[derive(Debug)]
-struct ConstainsDropField(Foo, Foo);
+struct ConstainsDropField(Foo, #[allow(unused_tuple_struct_fields)] Foo);
 
 // `t` needs Drop because one of its elements needs drop,
 // therefore precise capture might affect drop ordering
diff --git a/src/test/ui/codegen/issue-16602-3.rs b/src/test/ui/codegen/issue-16602-3.rs
index dbfeef053da..ca1ab3cc7fe 100644
--- a/src/test/ui/codegen/issue-16602-3.rs
+++ b/src/test/ui/codegen/issue-16602-3.rs
@@ -2,6 +2,7 @@
 #![allow(unused_variables)]
 #![allow(unused_assignments)]
 #[derive(Debug)]
+#[allow(unused_tuple_struct_fields)]
 enum Foo {
     Bar(u32, u32),
     Baz(&'static u32, &'static u32)
diff --git a/src/test/ui/coercion/issue-14589.rs b/src/test/ui/coercion/issue-14589.rs
index 5d8aab2ce74..d35ee5c731e 100644
--- a/src/test/ui/coercion/issue-14589.rs
+++ b/src/test/ui/coercion/issue-14589.rs
@@ -20,5 +20,5 @@ impl<T> Test<T> {
 }
 
 trait Foo { fn dummy(&self) { }}
-struct Output(isize);
+struct Output(#[allow(unused_tuple_struct_fields)] isize);
 impl Foo for Output {}
diff --git a/src/test/ui/const-generics/conservative_is_privately_uninhabited_uses_correct_param_env-1.rs b/src/test/ui/const-generics/conservative_is_privately_uninhabited_uses_correct_param_env-1.rs
index aa0f9131aa7..c9e26c302bf 100644
--- a/src/test/ui/const-generics/conservative_is_privately_uninhabited_uses_correct_param_env-1.rs
+++ b/src/test/ui/const-generics/conservative_is_privately_uninhabited_uses_correct_param_env-1.rs
@@ -9,6 +9,7 @@ trait Foo {
     const ASSOC: usize = 1;
 }
 
+#[allow(unused_tuple_struct_fields)]
 struct Iced<T: Foo>(T, [(); T::ASSOC])
 where
     [(); T::ASSOC]: ;
diff --git a/src/test/ui/const-generics/conservative_is_privately_uninhabited_uses_correct_param_env-2.rs b/src/test/ui/const-generics/conservative_is_privately_uninhabited_uses_correct_param_env-2.rs
index d0864414cc1..3017920fc98 100644
--- a/src/test/ui/const-generics/conservative_is_privately_uninhabited_uses_correct_param_env-2.rs
+++ b/src/test/ui/const-generics/conservative_is_privately_uninhabited_uses_correct_param_env-2.rs
@@ -9,6 +9,7 @@ trait Foo {
     const ASSOC: usize = 1;
 }
 
+#[allow(unused_tuple_struct_fields)]
 struct Iced<T: Foo>(T, [(); T::ASSOC])
 where
     [(); T::ASSOC]: ;
diff --git a/src/test/ui/const-generics/const-argument-cross-crate.rs b/src/test/ui/const-generics/const-argument-cross-crate.rs
index fda3ec3eef7..5693409e992 100644
--- a/src/test/ui/const-generics/const-argument-cross-crate.rs
+++ b/src/test/ui/const-generics/const-argument-cross-crate.rs
@@ -4,7 +4,7 @@
 
 extern crate const_generic_lib;
 
-struct Container(const_generic_lib::Alias);
+struct Container(#[allow(unused_tuple_struct_fields)] const_generic_lib::Alias);
 
 fn main() {
     let res = const_generic_lib::function(const_generic_lib::Struct([14u8, 1u8, 2u8]));
diff --git a/src/test/ui/const-generics/generic_const_exprs/associated-consts.rs b/src/test/ui/const-generics/generic_const_exprs/associated-consts.rs
index 4d89f188ad7..b839008d424 100644
--- a/src/test/ui/const-generics/generic_const_exprs/associated-consts.rs
+++ b/src/test/ui/const-generics/generic_const_exprs/associated-consts.rs
@@ -16,7 +16,7 @@ impl BlockCipher for BarCipher {
     const BLOCK_SIZE: usize = 32;
 }
 
-pub struct Block<C>(C);
+pub struct Block<C>(#[allow(unused_tuple_struct_fields)] C);
 
 pub fn test<C: BlockCipher, const M: usize>()
 where
diff --git a/src/test/ui/consts/assoc-const.rs b/src/test/ui/consts/assoc-const.rs
index b70479d255b..f542f2dcb52 100644
--- a/src/test/ui/consts/assoc-const.rs
+++ b/src/test/ui/consts/assoc-const.rs
@@ -6,7 +6,7 @@ trait Nat {
 }
 
 struct Zero;
-struct Succ<N>(N);
+struct Succ<N>(#[allow(unused_tuple_struct_fields)] N);
 
 impl Nat for Zero {
     const VALUE: usize = 0;
diff --git a/src/test/ui/consts/const-needs_drop.rs b/src/test/ui/consts/const-needs_drop.rs
index 58e80116442..11ee7084ce8 100644
--- a/src/test/ui/consts/const-needs_drop.rs
+++ b/src/test/ui/consts/const-needs_drop.rs
@@ -2,8 +2,10 @@
 
 use std::mem;
 
+#[allow(unused_tuple_struct_fields)]
 struct Trivial(u8, f32);
 
+#[allow(unused_tuple_struct_fields)]
 struct NonTrivial(u8, String);
 
 const CONST_U8: bool = mem::needs_drop::<u8>();
diff --git a/src/test/ui/consts/const-size_of_val-align_of_val.rs b/src/test/ui/consts/const-size_of_val-align_of_val.rs
index c3de6dc2075..e8323e4ae60 100644
--- a/src/test/ui/consts/const-size_of_val-align_of_val.rs
+++ b/src/test/ui/consts/const-size_of_val-align_of_val.rs
@@ -5,7 +5,7 @@
 
 use std::{mem, ptr};
 
-struct Foo(u32);
+struct Foo(#[allow(unused_tuple_struct_fields)] u32);
 
 #[derive(Clone, Copy)]
 struct Bar {
diff --git a/src/test/ui/consts/const_in_pattern/warn_corner_cases.rs b/src/test/ui/consts/const_in_pattern/warn_corner_cases.rs
index 51e1af359cd..15cf3c84d85 100644
--- a/src/test/ui/consts/const_in_pattern/warn_corner_cases.rs
+++ b/src/test/ui/consts/const_in_pattern/warn_corner_cases.rs
@@ -15,7 +15,7 @@
 #![warn(indirect_structural_match)]
 
 #[derive(Copy, Clone, Debug)]
-struct NoDerive(u32);
+struct NoDerive(#[allow(unused_tuple_struct_fields)] u32);
 
 // This impl makes `NoDerive` irreflexive.
 impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
diff --git a/src/test/ui/consts/issue-70773-mir-typeck-lt-norm.rs b/src/test/ui/consts/issue-70773-mir-typeck-lt-norm.rs
index 9d44aa1361c..dd56faa3185 100644
--- a/src/test/ui/consts/issue-70773-mir-typeck-lt-norm.rs
+++ b/src/test/ui/consts/issue-70773-mir-typeck-lt-norm.rs
@@ -1,7 +1,7 @@
 // run-pass
 
 const HASH_LEN: usize = 20;
-struct Hash([u8; HASH_LEN]);
+struct Hash(#[allow(unused_tuple_struct_fields)] [u8; HASH_LEN]);
 fn init_hash(_: &mut [u8; HASH_LEN]) {}
 
 fn foo<'a>() -> &'a () {
diff --git a/src/test/ui/consts/rvalue-static-promotion.rs b/src/test/ui/consts/rvalue-static-promotion.rs
index 2d7e4ab3989..c48d9eae928 100644
--- a/src/test/ui/consts/rvalue-static-promotion.rs
+++ b/src/test/ui/consts/rvalue-static-promotion.rs
@@ -4,7 +4,7 @@ use std::cell::Cell;
 
 const NONE_CELL_STRING: Option<Cell<String>> = None;
 
-struct Foo<T>(T);
+struct Foo<T>(#[allow(unused_tuple_struct_fields)] T);
 impl<T> Foo<T> {
     const FOO: Option<Box<T>> = None;
 }
diff --git a/src/test/ui/consts/transmute-const.rs b/src/test/ui/consts/transmute-const.rs
index 5044d99ec51..c5c3dfc4cc7 100644
--- a/src/test/ui/consts/transmute-const.rs
+++ b/src/test/ui/consts/transmute-const.rs
@@ -3,7 +3,7 @@
 use std::mem;
 
 #[repr(transparent)]
-struct Foo(u32);
+struct Foo(#[allow(unused_tuple_struct_fields)] u32);
 
 const TRANSMUTED_U32: u32 = unsafe { mem::transmute(Foo(3)) };
 
diff --git a/src/test/ui/deriving/deriving-clone-generic-tuple-struct.rs b/src/test/ui/deriving/deriving-clone-generic-tuple-struct.rs
index 8b9840de172..3480ccc1089 100644
--- a/src/test/ui/deriving/deriving-clone-generic-tuple-struct.rs
+++ b/src/test/ui/deriving/deriving-clone-generic-tuple-struct.rs
@@ -2,6 +2,7 @@
 // pretty-expanded FIXME #23616
 
 #[derive(Clone)]
+#[allow(unused_tuple_struct_fields)]
 struct S<T>(T, ());
 
 pub fn main() {
diff --git a/src/test/ui/deriving/deriving-copyclone.rs b/src/test/ui/deriving/deriving-copyclone.rs
index 78d74a11ffc..f8403b1feac 100644
--- a/src/test/ui/deriving/deriving-copyclone.rs
+++ b/src/test/ui/deriving/deriving-copyclone.rs
@@ -23,7 +23,7 @@ impl Clone for Liar {
 
 /// This struct is actually Copy... at least, it thinks it is!
 #[derive(Copy, Clone)]
-struct Innocent(Liar);
+struct Innocent(#[allow(unused_tuple_struct_fields)] Liar);
 
 impl Innocent {
     fn new() -> Self {
diff --git a/src/test/ui/deriving/issue-58319.rs b/src/test/ui/deriving/issue-58319.rs
index 757307d944f..8041bd5bb3c 100644
--- a/src/test/ui/deriving/issue-58319.rs
+++ b/src/test/ui/deriving/issue-58319.rs
@@ -3,6 +3,7 @@ fn main() {}
 #[derive(Clone)]
 pub struct Little;
 #[derive(Clone)]
+#[allow(unused_tuple_struct_fields)]
 pub struct Big(
     Little,
     Little,
diff --git a/src/test/ui/drop/dropck-eyepatch-reorder.rs b/src/test/ui/drop/dropck-eyepatch-reorder.rs
index b4605878a54..0d7af3d4f61 100644
--- a/src/test/ui/drop/dropck-eyepatch-reorder.rs
+++ b/src/test/ui/drop/dropck-eyepatch-reorder.rs
@@ -12,10 +12,10 @@ trait Foo { fn foo(&self, _: &str); }
 
 struct Dt<A: Foo>(&'static str, A);
 struct Dr<'a, B:'a+Foo>(&'static str, &'a B);
-struct Pt<A: Foo, B: Foo>(&'static str, A, B);
-struct Pr<'a, 'b, B:'a+'b+Foo>(&'static str, &'a B, &'b B);
-struct St<A: Foo>(&'static str, A);
-struct Sr<'a, B:'a+Foo>(&'static str, &'a B);
+struct Pt<A: Foo, B: Foo>(&'static str, #[allow(unused_tuple_struct_fields)] A, B);
+struct Pr<'a, 'b, B:'a+'b+Foo>(&'static str, #[allow(unused_tuple_struct_fields)] &'a B, &'b B);
+struct St<A: Foo>(&'static str, #[allow(unused_tuple_struct_fields)] A);
+struct Sr<'a, B:'a+Foo>(&'static str, #[allow(unused_tuple_struct_fields)] &'a B);
 
 impl<A: Foo> Drop for Dt<A> {
     fn drop(&mut self) { println!("drop {}", self.0); self.1.foo(self.0); }
diff --git a/src/test/ui/drop/dropck-eyepatch.rs b/src/test/ui/drop/dropck-eyepatch.rs
index 9255391e412..3c4840d5c7a 100644
--- a/src/test/ui/drop/dropck-eyepatch.rs
+++ b/src/test/ui/drop/dropck-eyepatch.rs
@@ -35,10 +35,10 @@ trait Foo { fn foo(&self, _: &str); }
 
 struct Dt<A: Foo>(&'static str, A);
 struct Dr<'a, B:'a+Foo>(&'static str, &'a B);
-struct Pt<A,B: Foo>(&'static str, A, B);
-struct Pr<'a, 'b, B:'a+'b+Foo>(&'static str, &'a B, &'b B);
-struct St<A: Foo>(&'static str, A);
-struct Sr<'a, B:'a+Foo>(&'static str, &'a B);
+struct Pt<A,B: Foo>(&'static str, #[allow(unused_tuple_struct_fields)] A, B);
+struct Pr<'a, 'b, B:'a+'b+Foo>(&'static str, #[allow(unused_tuple_struct_fields)] &'a B, &'b B);
+struct St<A: Foo>(&'static str, #[allow(unused_tuple_struct_fields)] A);
+struct Sr<'a, B:'a+Foo>(&'static str, #[allow(unused_tuple_struct_fields)] &'a B);
 
 impl<A: Foo> Drop for Dt<A> {
     fn drop(&mut self) { println!("drop {}", self.0); self.1.foo(self.0); }
diff --git a/src/test/ui/drop/dynamic-drop.rs b/src/test/ui/drop/dynamic-drop.rs
index 736123ed119..e7068677423 100644
--- a/src/test/ui/drop/dynamic-drop.rs
+++ b/src/test/ui/drop/dynamic-drop.rs
@@ -103,7 +103,7 @@ fn dynamic_drop(a: &Allocator, c: bool) {
     };
 }
 
-struct TwoPtrs<'a>(Ptr<'a>, Ptr<'a>);
+struct TwoPtrs<'a>(Ptr<'a>, #[allow(unused_tuple_struct_fields)] Ptr<'a>);
 fn struct_dynamic_drop(a: &Allocator, c0: bool, c1: bool, c: bool) {
     for i in 0..2 {
         let x;
diff --git a/src/test/ui/dropck/issue-28498-ugeh-with-passed-to-fn.rs b/src/test/ui/dropck/issue-28498-ugeh-with-passed-to-fn.rs
index 23fd86a093b..04d0d32033a 100644
--- a/src/test/ui/dropck/issue-28498-ugeh-with-passed-to-fn.rs
+++ b/src/test/ui/dropck/issue-28498-ugeh-with-passed-to-fn.rs
@@ -21,7 +21,7 @@ impl Drop for ScribbleOnDrop {
     }
 }
 
-struct Foo<T>(u32, T, Box<for <'r> fn(&'r T) -> String>);
+struct Foo<T>(u32, T, #[allow(unused_tuple_struct_fields)] Box<for <'r> fn(&'r T) -> String>);
 
 unsafe impl<#[may_dangle] T> Drop for Foo<T> {
     fn drop(&mut self) {
diff --git a/src/test/ui/enum-discriminant/discriminant_value-wrapper.rs b/src/test/ui/enum-discriminant/discriminant_value-wrapper.rs
index 65dc9166330..8e162d5c455 100644
--- a/src/test/ui/enum-discriminant/discriminant_value-wrapper.rs
+++ b/src/test/ui/enum-discriminant/discriminant_value-wrapper.rs
@@ -4,6 +4,7 @@
 
 use std::mem;
 
+#[allow(unused_tuple_struct_fields)]
 enum ADT {
     First(u32, u32),
     Second(u64)
diff --git a/src/test/ui/enum-discriminant/discriminant_value.rs b/src/test/ui/enum-discriminant/discriminant_value.rs
index eb60aaf4b2d..65ab411dbcb 100644
--- a/src/test/ui/enum-discriminant/discriminant_value.rs
+++ b/src/test/ui/enum-discriminant/discriminant_value.rs
@@ -27,13 +27,14 @@ enum CLike3 {
     D
 }
 
+#[allow(unused_tuple_struct_fields)]
 enum ADT {
     First(u32, u32),
     Second(u64)
 }
 
 enum NullablePointer {
-    Something(&'static u32),
+    Something(#[allow(unused_tuple_struct_fields)] &'static u32),
     Nothing
 }
 
diff --git a/src/test/ui/generator/size-moved-locals.rs b/src/test/ui/generator/size-moved-locals.rs
index 74c60d98154..3c756a86fc5 100644
--- a/src/test/ui/generator/size-moved-locals.rs
+++ b/src/test/ui/generator/size-moved-locals.rs
@@ -18,7 +18,7 @@
 use std::ops::Generator;
 
 const FOO_SIZE: usize = 1024;
-struct Foo([u8; FOO_SIZE]);
+struct Foo(#[allow(unused_tuple_struct_fields)] [u8; FOO_SIZE]);
 
 impl Drop for Foo {
     fn drop(&mut self) {}
diff --git a/src/test/ui/generics/generic-default-type-params-cross-crate.rs b/src/test/ui/generics/generic-default-type-params-cross-crate.rs
index 9e5eaa72c15..834b15be1c5 100644
--- a/src/test/ui/generics/generic-default-type-params-cross-crate.rs
+++ b/src/test/ui/generics/generic-default-type-params-cross-crate.rs
@@ -5,7 +5,7 @@
 
 extern crate default_type_params_xc;
 
-struct Vec<T, A = default_type_params_xc::Heap>(Option<(T,A)>);
+struct Vec<T, A = default_type_params_xc::Heap>(#[allow(unused_tuple_struct_fields)] Option<(T,A)>);
 
 struct Foo;
 
diff --git a/src/test/ui/generics/generic-ivec-leak.rs b/src/test/ui/generics/generic-ivec-leak.rs
index a8ea1d5069b..9610bdcb338 100644
--- a/src/test/ui/generics/generic-ivec-leak.rs
+++ b/src/test/ui/generics/generic-ivec-leak.rs
@@ -1,5 +1,5 @@
 // run-pass
 #![allow(non_camel_case_types)]
-enum wrapper<T> { wrapped(T), }
+enum wrapper<T> { wrapped(#[allow(unused_tuple_struct_fields)] T), }
 
 pub fn main() { let _w = wrapper::wrapped(vec![1, 2, 3, 4, 5]); }
diff --git a/src/test/ui/generics/generic-newtype-struct.rs b/src/test/ui/generics/generic-newtype-struct.rs
index 570c982cc87..aa879f01a58 100644
--- a/src/test/ui/generics/generic-newtype-struct.rs
+++ b/src/test/ui/generics/generic-newtype-struct.rs
@@ -1,7 +1,7 @@
 // run-pass
 // pretty-expanded FIXME #23616
 
-struct S<T>(T);
+struct S<T>(#[allow(unused_tuple_struct_fields)] T);
 
 pub fn main() {
     let _s = S(2);
diff --git a/src/test/ui/generics/generic-no-mangle.fixed b/src/test/ui/generics/generic-no-mangle.fixed
index 9126ac167cf..501acb6e163 100644
--- a/src/test/ui/generics/generic-no-mangle.fixed
+++ b/src/test/ui/generics/generic-no-mangle.fixed
@@ -76,7 +76,7 @@ impl<T> Trait2<T> for Foo {
     fn qux<'a>(x: &'a i32) -> &i32 { x } //~ ERROR functions generic over types or consts must be mangled
 }
 
-pub struct Bar<T>(T);
+pub struct Bar<T>(#[allow(unused_tuple_struct_fields)] T);
 
 impl<T> Bar<T> {
     
@@ -111,7 +111,7 @@ impl<T> Trait3 for Bar<T> {
     fn baz<U>() {} //~ ERROR functions generic over types or consts must be mangled
 }
 
-pub struct Baz<'a>(&'a i32);
+pub struct Baz<'a>(#[allow(unused_tuple_struct_fields)] &'a i32);
 
 impl<'a> Baz<'a> {
     #[no_mangle]
diff --git a/src/test/ui/generics/generic-no-mangle.rs b/src/test/ui/generics/generic-no-mangle.rs
index e283cf4bfe5..74e407078e8 100644
--- a/src/test/ui/generics/generic-no-mangle.rs
+++ b/src/test/ui/generics/generic-no-mangle.rs
@@ -76,7 +76,7 @@ impl<T> Trait2<T> for Foo {
     fn qux<'a>(x: &'a i32) -> &i32 { x } //~ ERROR functions generic over types or consts must be mangled
 }
 
-pub struct Bar<T>(T);
+pub struct Bar<T>(#[allow(unused_tuple_struct_fields)] T);
 
 impl<T> Bar<T> {
     #[no_mangle]
@@ -111,7 +111,7 @@ impl<T> Trait3 for Bar<T> {
     fn baz<U>() {} //~ ERROR functions generic over types or consts must be mangled
 }
 
-pub struct Baz<'a>(&'a i32);
+pub struct Baz<'a>(#[allow(unused_tuple_struct_fields)] &'a i32);
 
 impl<'a> Baz<'a> {
     #[no_mangle]
diff --git a/src/test/ui/generics/generic-recursive-tag.rs b/src/test/ui/generics/generic-recursive-tag.rs
index 74f5b701d98..b344da1c7dd 100644
--- a/src/test/ui/generics/generic-recursive-tag.rs
+++ b/src/test/ui/generics/generic-recursive-tag.rs
@@ -1,7 +1,7 @@
 // run-pass
 #![allow(non_camel_case_types)]
 
-enum list<T> { cons(Box<T>, Box<list<T>>), nil, }
+enum list<T> { #[allow(unused_tuple_struct_fields)] cons(Box<T>, Box<list<T>>), nil, }
 
 pub fn main() {
     let _a: list<isize> =
diff --git a/src/test/ui/generics/generic-tag-corruption.rs b/src/test/ui/generics/generic-tag-corruption.rs
index aa26183a0d4..35de3c1f712 100644
--- a/src/test/ui/generics/generic-tag-corruption.rs
+++ b/src/test/ui/generics/generic-tag-corruption.rs
@@ -5,6 +5,6 @@
 // This used to cause memory corruption in stage 0.
 // pretty-expanded FIXME #23616
 
-enum thing<K> { some(K), }
+enum thing<K> { some(#[allow(unused_tuple_struct_fields)] K), }
 
 pub fn main() { let _x = thing::some("hi".to_string()); }
diff --git a/src/test/ui/generics/generic-tag-local.rs b/src/test/ui/generics/generic-tag-local.rs
index cc85e6e0f0a..c5772e84193 100644
--- a/src/test/ui/generics/generic-tag-local.rs
+++ b/src/test/ui/generics/generic-tag-local.rs
@@ -3,6 +3,6 @@
 
 // pretty-expanded FIXME #23616
 
-enum clam<T> { a(T), }
+enum clam<T> { a(#[allow(unused_tuple_struct_fields)] T), }
 
 pub fn main() { let _c = clam::a(3); }
diff --git a/src/test/ui/generics/generic-tag.rs b/src/test/ui/generics/generic-tag.rs
index 67f2ccdde34..31fc2178d6d 100644
--- a/src/test/ui/generics/generic-tag.rs
+++ b/src/test/ui/generics/generic-tag.rs
@@ -6,7 +6,7 @@
 
 #![allow(unused_variables)]
 
-enum option<T> { some(Box<T>), none, }
+enum option<T> { some(#[allow(unused_tuple_struct_fields)] Box<T>), none, }
 
 pub fn main() {
     let mut a: option<isize> = option::some::<isize>(Box::new(10));
diff --git a/src/test/ui/impl-trait/bounds_regression.rs b/src/test/ui/impl-trait/bounds_regression.rs
index 0fdeb6bdee1..31fc46203d3 100644
--- a/src/test/ui/impl-trait/bounds_regression.rs
+++ b/src/test/ui/impl-trait/bounds_regression.rs
@@ -15,7 +15,7 @@ pub fn future_from_generator<
     GenFuture(x)
 }
 
-struct GenFuture<T: FakeGenerator<Yield = ()>>(T);
+struct GenFuture<T: FakeGenerator<Yield = ()>>(#[allow(unused_tuple_struct_fields)] T);
 
 impl<T: FakeGenerator<Yield = ()>> FakeFuture for GenFuture<T> {
     type Output = T::Return;
diff --git a/src/test/ui/issues/issue-13027.rs b/src/test/ui/issues/issue-13027.rs
index 1bab82a543f..64bf2a11d0e 100644
--- a/src/test/ui/issues/issue-13027.rs
+++ b/src/test/ui/issues/issue-13027.rs
@@ -164,7 +164,7 @@ fn range_shadow_multi_pats() {
 
 fn misc() {
     enum Foo {
-        Bar(usize, bool)
+        Bar(#[allow(unused_tuple_struct_fields)] usize, bool)
     }
     // This test basically mimics how trace_macros! macro is implemented,
     // which is a rare combination of vector patterns, multiple wild-card
diff --git a/src/test/ui/issues/issue-14382.rs b/src/test/ui/issues/issue-14382.rs
index 671e7a22667..dca24d0be8a 100644
--- a/src/test/ui/issues/issue-14382.rs
+++ b/src/test/ui/issues/issue-14382.rs
@@ -1,6 +1,6 @@
 // run-pass
 #[derive(Debug)]
-struct Matrix4<S>(S);
+struct Matrix4<S>(#[allow(unused_tuple_struct_fields)] S);
 trait POrd<S> {}
 
 fn translate<S: POrd<S>>(s: S) -> Matrix4<S> { Matrix4(s) }
diff --git a/src/test/ui/issues/issue-15858.rs b/src/test/ui/issues/issue-15858.rs
index 41d2f13952a..8d65afc4883 100644
--- a/src/test/ui/issues/issue-15858.rs
+++ b/src/test/ui/issues/issue-15858.rs
@@ -12,7 +12,7 @@ impl Bar for BarImpl {
 }
 
 
-struct Foo<B: Bar>(B);
+struct Foo<B: Bar>(#[allow(unused_tuple_struct_fields)] B);
 
 impl<B: Bar> Drop for Foo<B> {
     fn drop(&mut self) {
diff --git a/src/test/ui/issues/issue-17905.rs b/src/test/ui/issues/issue-17905.rs
index 95133a45844..dae9648b917 100644
--- a/src/test/ui/issues/issue-17905.rs
+++ b/src/test/ui/issues/issue-17905.rs
@@ -1,6 +1,7 @@
 // run-pass
 
 #[derive(Debug)]
+#[allow(unused_tuple_struct_fields)]
 struct Pair<T, V> (T, V);
 
 impl Pair<
diff --git a/src/test/ui/issues/issue-2063.rs b/src/test/ui/issues/issue-2063.rs
index 9dbac6ccee1..f08f9d4cfe4 100644
--- a/src/test/ui/issues/issue-2063.rs
+++ b/src/test/ui/issues/issue-2063.rs
@@ -3,7 +3,7 @@
 // cause compiler to loop.  Note that no instances
 // of such a type could ever be constructed.
 
-struct T(Box<T>);
+struct T(#[allow(unused_tuple_struct_fields)] Box<T>);
 
 trait ToStr2 {
     fn my_to_string(&self) -> String;
diff --git a/src/test/ui/issues/issue-23491.rs b/src/test/ui/issues/issue-23491.rs
index d2ded88aeff..1cb969731e2 100644
--- a/src/test/ui/issues/issue-23491.rs
+++ b/src/test/ui/issues/issue-23491.rs
@@ -2,7 +2,7 @@
 #![allow(unused_variables)]
 #![feature(box_syntax)]
 
-struct Node<T: ?Sized>(T);
+struct Node<T: ?Sized>(#[allow(unused_tuple_struct_fields)] T);
 
 fn main() {
     let x: Box<Node<[isize]>> = box Node([]);
diff --git a/src/test/ui/issues/issue-24308.rs b/src/test/ui/issues/issue-24308.rs
index 9c39a5d2238..4a582c68efc 100644
--- a/src/test/ui/issues/issue-24308.rs
+++ b/src/test/ui/issues/issue-24308.rs
@@ -4,7 +4,7 @@ pub trait Foo {
     fn method2();
 }
 
-struct Slice<'a, T: 'a>(&'a [T]);
+struct Slice<'a, T: 'a>(#[allow(unused_tuple_struct_fields)] &'a [T]);
 
 impl<'a, T: 'a> Foo for Slice<'a, T> {
     fn method2() {
diff --git a/src/test/ui/issues/issue-24805-dropck-itemless.rs b/src/test/ui/issues/issue-24805-dropck-itemless.rs
index 555eefeb3a1..45761b61c3e 100644
--- a/src/test/ui/issues/issue-24805-dropck-itemless.rs
+++ b/src/test/ui/issues/issue-24805-dropck-itemless.rs
@@ -19,7 +19,7 @@ impl<'a, T> UserDefined for &'a T { }
 //   ```
 macro_rules! impl_drop {
     ($Bound:ident, $Id:ident) => {
-        struct $Id<T: $Bound>(T);
+        struct $Id<T: $Bound>(#[allow(unused_tuple_struct_fields)] T);
         unsafe impl <#[may_dangle] T: $Bound> Drop for $Id<T> {
             fn drop(&mut self) { }
         }
diff --git a/src/test/ui/issues/issue-25089.rs b/src/test/ui/issues/issue-25089.rs
index 0f0f78623a2..c988f8f55fa 100644
--- a/src/test/ui/issues/issue-25089.rs
+++ b/src/test/ui/issues/issue-25089.rs
@@ -4,7 +4,7 @@
 
 use std::thread;
 
-struct Foo(i32);
+struct Foo(#[allow(unused_tuple_struct_fields)] i32);
 
 impl Drop for Foo {
     fn drop(&mut self) {
diff --git a/src/test/ui/issues/issue-25679.rs b/src/test/ui/issues/issue-25679.rs
index 89544c9eb88..b548da98888 100644
--- a/src/test/ui/issues/issue-25679.rs
+++ b/src/test/ui/issues/issue-25679.rs
@@ -2,6 +2,7 @@
 trait Device {
     type Resources;
 }
+#[allow(unused_tuple_struct_fields)]
 struct Foo<D, R>(D, R);
 
 impl<D: Device> Foo<D, D::Resources> {
diff --git a/src/test/ui/issues/issue-25700-1.rs b/src/test/ui/issues/issue-25700-1.rs
index 7bc9673a5be..5e71a52ba4e 100644
--- a/src/test/ui/issues/issue-25700-1.rs
+++ b/src/test/ui/issues/issue-25700-1.rs
@@ -1,5 +1,5 @@
 // run-pass
-struct S<T: 'static>(Option<&'static T>);
+struct S<T: 'static>(#[allow(unused_tuple_struct_fields)] Option<&'static T>);
 
 trait Tr { type Out; }
 impl<T> Tr for T { type Out = T; }
diff --git a/src/test/ui/issues/issue-25700-2.rs b/src/test/ui/issues/issue-25700-2.rs
index b161e68abaf..89b1db496f9 100644
--- a/src/test/ui/issues/issue-25700-2.rs
+++ b/src/test/ui/issues/issue-25700-2.rs
@@ -3,8 +3,9 @@ pub trait Parser {
     type Input;
 }
 
-pub struct Iter<P: Parser>(P, P::Input);
+pub struct Iter<P: Parser>(#[allow(unused_tuple_struct_fields)] P, P::Input);
 
+#[allow(unused_tuple_struct_fields)]
 pub struct Map<P, F>(P, F);
 impl<P, F> Parser for Map<P, F> where F: FnMut(P) {
     type Input = u8;
diff --git a/src/test/ui/issues/issue-25700.rs b/src/test/ui/issues/issue-25700.rs
index 45c452d618d..e5b9a97523d 100644
--- a/src/test/ui/issues/issue-25700.rs
+++ b/src/test/ui/issues/issue-25700.rs
@@ -1,4 +1,4 @@
-struct S<T: 'static>(Option<&'static T>);
+struct S<T: 'static>(#[allow(unused_tuple_struct_fields)] Option<&'static T>);
 
 trait Tr { type Out; }
 impl<T> Tr for T { type Out = T; }
diff --git a/src/test/ui/issues/issue-26127.rs b/src/test/ui/issues/issue-26127.rs
index cb479a23085..f3f9c1d9ae8 100644
--- a/src/test/ui/issues/issue-26127.rs
+++ b/src/test/ui/issues/issue-26127.rs
@@ -1,7 +1,7 @@
 // run-pass
 trait Tr { type T; }
 impl Tr for u8 { type T=(); }
-struct S<I: Tr>(I::T);
+struct S<I: Tr>(#[allow(unused_tuple_struct_fields)] I::T);
 
 fn foo<I: Tr>(i: I::T) {
     S::<I>(i);
diff --git a/src/test/ui/issues/issue-26641.rs b/src/test/ui/issues/issue-26641.rs
index 4b6f2c2b3bc..e08edd0b5cb 100644
--- a/src/test/ui/issues/issue-26641.rs
+++ b/src/test/ui/issues/issue-26641.rs
@@ -1,5 +1,5 @@
 // run-pass
-struct Parser<'a>(Box<dyn FnMut(Parser) + 'a>);
+struct Parser<'a>(#[allow(unused_tuple_struct_fields)] Box<dyn FnMut(Parser) + 'a>);
 
 fn main() {
     let _x = Parser(Box::new(|_|{}));
diff --git a/src/test/ui/issues/issue-26709.rs b/src/test/ui/issues/issue-26709.rs
index 281ae13399d..1bd2651dd6c 100644
--- a/src/test/ui/issues/issue-26709.rs
+++ b/src/test/ui/issues/issue-26709.rs
@@ -1,5 +1,5 @@
 // run-pass
-struct Wrapper<'a, T: ?Sized>(&'a mut i32, T);
+struct Wrapper<'a, T: ?Sized>(&'a mut i32, #[allow(unused_tuple_struct_fields)] T);
 
 impl<'a, T: ?Sized> Drop for Wrapper<'a, T> {
     fn drop(&mut self) {
diff --git a/src/test/ui/issues/issue-27240.rs b/src/test/ui/issues/issue-27240.rs
index a22db76b9bc..eaf254f3361 100644
--- a/src/test/ui/issues/issue-27240.rs
+++ b/src/test/ui/issues/issue-27240.rs
@@ -2,12 +2,12 @@
 #![allow(unused_assignments)]
 #![allow(unused_variables)]
 use std::fmt;
-struct NoisyDrop<T: fmt::Debug>(T);
+struct NoisyDrop<T: fmt::Debug>(#[allow(unused_tuple_struct_fields)] T);
 impl<T: fmt::Debug> Drop for NoisyDrop<T> {
     fn drop(&mut self) {}
 }
 
-struct Bar<T: fmt::Debug>([*const NoisyDrop<T>; 2]);
+struct Bar<T: fmt::Debug>(#[allow(unused_tuple_struct_fields)] [*const NoisyDrop<T>; 2]);
 
 fn fine() {
     let (u,b);
@@ -15,6 +15,7 @@ fn fine() {
     b = Bar([&NoisyDrop(&u), &NoisyDrop(&u)]);
 }
 
+#[allow(unused_tuple_struct_fields)]
 struct Bar2<T: fmt::Debug>(*const NoisyDrop<T>, *const NoisyDrop<T>);
 
 fn lolwut() {
diff --git a/src/test/ui/issues/issue-28498-must-work-ex1.rs b/src/test/ui/issues/issue-28498-must-work-ex1.rs
index 4699d3352ad..ab6d190e0a1 100644
--- a/src/test/ui/issues/issue-28498-must-work-ex1.rs
+++ b/src/test/ui/issues/issue-28498-must-work-ex1.rs
@@ -6,7 +6,7 @@
 
 use std::cell::Cell;
 
-struct Concrete<'a>(u32, Cell<Option<&'a Concrete<'a>>>);
+struct Concrete<'a>(#[allow(unused_tuple_struct_fields)] u32, Cell<Option<&'a Concrete<'a>>>);
 
 fn main() {
     let mut data = Vec::new();
diff --git a/src/test/ui/issues/issue-28498-must-work-ex2.rs b/src/test/ui/issues/issue-28498-must-work-ex2.rs
index cadf62461fd..378d736ee3d 100644
--- a/src/test/ui/issues/issue-28498-must-work-ex2.rs
+++ b/src/test/ui/issues/issue-28498-must-work-ex2.rs
@@ -6,7 +6,7 @@
 
 use std::cell::Cell;
 
-struct Concrete<'a>(u32, Cell<Option<&'a Concrete<'a>>>);
+struct Concrete<'a>(#[allow(unused_tuple_struct_fields)] u32, Cell<Option<&'a Concrete<'a>>>);
 
 struct Foo<T> { data: Vec<T> }
 
diff --git a/src/test/ui/issues/issue-28498-ugeh-ex1.rs b/src/test/ui/issues/issue-28498-ugeh-ex1.rs
index 90cf2cddcf0..24bf706cef9 100644
--- a/src/test/ui/issues/issue-28498-ugeh-ex1.rs
+++ b/src/test/ui/issues/issue-28498-ugeh-ex1.rs
@@ -8,7 +8,7 @@
 #![feature(dropck_eyepatch)]
 use std::cell::Cell;
 
-struct Concrete<'a>(u32, Cell<Option<&'a Concrete<'a>>>);
+struct Concrete<'a>(#[allow(unused_tuple_struct_fields)] u32, Cell<Option<&'a Concrete<'a>>>);
 
 struct Foo<T> { data: Vec<T> }
 
diff --git a/src/test/ui/issues/issue-29147-rpass.rs b/src/test/ui/issues/issue-29147-rpass.rs
index 101bca307f1..439f8bb5308 100644
--- a/src/test/ui/issues/issue-29147-rpass.rs
+++ b/src/test/ui/issues/issue-29147-rpass.rs
@@ -1,5 +1,6 @@
 // run-pass
 #![recursion_limit="1024"]
+#![allow(dead_code)]
 
 use std::mem;
 
diff --git a/src/test/ui/issues/issue-29147.rs b/src/test/ui/issues/issue-29147.rs
index 271bc526033..190ecf46009 100644
--- a/src/test/ui/issues/issue-29147.rs
+++ b/src/test/ui/issues/issue-29147.rs
@@ -1,4 +1,5 @@
 #![recursion_limit="1024"]
+#![allow(dead_code)]
 
 pub struct S0<T>(T,T);
 pub struct S1<T>(Option<Box<S0<S0<T>>>>,Option<Box<S0<S0<T>>>>);
diff --git a/src/test/ui/issues/issue-29147.stderr b/src/test/ui/issues/issue-29147.stderr
index 5570e887edc..138d477dc6b 100644
--- a/src/test/ui/issues/issue-29147.stderr
+++ b/src/test/ui/issues/issue-29147.stderr
@@ -1,11 +1,11 @@
 error[E0283]: type annotations needed
-  --> $DIR/issue-29147.rs:21:13
+  --> $DIR/issue-29147.rs:22:13
    |
 LL |     let _ = <S5<_>>::xxx;
    |             ^^^^^^^^^^^^ cannot infer type for struct `S5<_>`
    |
 note: multiple `impl`s satisfying `S5<_>: Foo` found
-  --> $DIR/issue-29147.rs:17:1
+  --> $DIR/issue-29147.rs:18:1
    |
 LL | impl Foo for S5<u32> { fn xxx(&self) {} }
    | ^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/issues/issue-31267-additional.rs b/src/test/ui/issues/issue-31267-additional.rs
index 70dce2c9490..7f0cbd658f1 100644
--- a/src/test/ui/issues/issue-31267-additional.rs
+++ b/src/test/ui/issues/issue-31267-additional.rs
@@ -6,7 +6,7 @@ struct Bar;
 const BAZ: Bar = Bar;
 
 #[derive(Debug)]
-struct Foo([Bar; 1]);
+struct Foo(#[allow(unused_tuple_struct_fields)] [Bar; 1]);
 
 struct Biz;
 
diff --git a/src/test/ui/issues/issue-31299.rs b/src/test/ui/issues/issue-31299.rs
index d93ffcb2262..78c3252d32e 100644
--- a/src/test/ui/issues/issue-31299.rs
+++ b/src/test/ui/issues/issue-31299.rs
@@ -25,9 +25,9 @@ impl<T> Front for Vec<T> {
     type Back = Vec<T>;
 }
 
-struct PtrBack<T: Front>(Vec<T::Back>);
+struct PtrBack<T: Front>(#[allow(unused_tuple_struct_fields)] Vec<T::Back>);
 
-struct M(PtrBack<Vec<M>>);
+struct M(#[allow(unused_tuple_struct_fields)] PtrBack<Vec<M>>);
 
 #[allow(unused_must_use)]
 fn main() {
diff --git a/src/test/ui/issues/issue-34571.rs b/src/test/ui/issues/issue-34571.rs
index bad1bebc697..5498091da58 100644
--- a/src/test/ui/issues/issue-34571.rs
+++ b/src/test/ui/issues/issue-34571.rs
@@ -1,7 +1,7 @@
 // run-pass
 #[repr(u8)]
 enum Foo {
-    Foo(u8),
+    Foo(#[allow(unused_tuple_struct_fields)] u8),
 }
 
 fn main() {
diff --git a/src/test/ui/issues/issue-36053.rs b/src/test/ui/issues/issue-36053.rs
index a61c02c0a12..5c6d0780416 100644
--- a/src/test/ui/issues/issue-36053.rs
+++ b/src/test/ui/issues/issue-36053.rs
@@ -7,7 +7,7 @@
 
 use std::iter::FusedIterator;
 
-struct Thing<'a>(&'a str);
+struct Thing<'a>(#[allow(unused_tuple_struct_fields)] &'a str);
 impl<'a> Iterator for Thing<'a> {
     type Item = &'a str;
     fn next(&mut self) -> Option<&'a str> {
diff --git a/src/test/ui/issues/issue-36278-prefix-nesting.rs b/src/test/ui/issues/issue-36278-prefix-nesting.rs
index 62d1f5f8258..a809f7f1329 100644
--- a/src/test/ui/issues/issue-36278-prefix-nesting.rs
+++ b/src/test/ui/issues/issue-36278-prefix-nesting.rs
@@ -5,6 +5,7 @@
 use std::mem;
 
 const SZ: usize = 100;
+#[allow(unused_tuple_struct_fields)]
 struct P<T: ?Sized>([u8; SZ], T);
 
 type Ack<T> = P<P<T>>;
diff --git a/src/test/ui/issues/issue-40003.rs b/src/test/ui/issues/issue-40003.rs
index 642de6b8fe3..5e61361f987 100644
--- a/src/test/ui/issues/issue-40003.rs
+++ b/src/test/ui/issues/issue-40003.rs
@@ -153,7 +153,7 @@ mod stream {
     }
 
     enum Slot<T> {
-        Next(usize),
+        Next(#[allow(unused_tuple_struct_fields)] usize),
         _Data { _a: T },
     }
 
diff --git a/src/test/ui/issues/issue-4252.rs b/src/test/ui/issues/issue-4252.rs
index 48e617fd7eb..0d47a7f0c16 100644
--- a/src/test/ui/issues/issue-4252.rs
+++ b/src/test/ui/issues/issue-4252.rs
@@ -7,7 +7,7 @@ trait X {
 }
 
 #[derive(Debug)]
-struct Y(isize);
+struct Y(#[allow(unused_tuple_struct_fields)] isize);
 
 #[derive(Debug)]
 struct Z<T: X+std::fmt::Debug> {
diff --git a/src/test/ui/issues/issue-46069.rs b/src/test/ui/issues/issue-46069.rs
index 1d4f789828d..c418128c186 100644
--- a/src/test/ui/issues/issue-46069.rs
+++ b/src/test/ui/issues/issue-46069.rs
@@ -2,7 +2,7 @@
 use std::iter::{Fuse, Cloned};
 use std::slice::Iter;
 
-struct Foo<'a, T: 'a>(&'a T);
+struct Foo<'a, T: 'a>(#[allow(unused_tuple_struct_fields)] &'a T);
 impl<'a, T: 'a> Copy for Foo<'a, T> {}
 impl<'a, T: 'a> Clone for Foo<'a, T> {
     fn clone(&self) -> Self { *self }
diff --git a/src/test/ui/issues/issue-5315.rs b/src/test/ui/issues/issue-5315.rs
index 38c98254b93..0c121a5eee6 100644
--- a/src/test/ui/issues/issue-5315.rs
+++ b/src/test/ui/issues/issue-5315.rs
@@ -1,7 +1,7 @@
 // run-pass
 // pretty-expanded FIXME #23616
 
-struct A(bool);
+struct A(#[allow(unused_tuple_struct_fields)] bool);
 
 pub fn main() {
     let f = A;
diff --git a/src/test/ui/issues/issue-61894.rs b/src/test/ui/issues/issue-61894.rs
index c018ac73fb5..776fdbb7466 100644
--- a/src/test/ui/issues/issue-61894.rs
+++ b/src/test/ui/issues/issue-61894.rs
@@ -4,7 +4,7 @@
 
 use std::any::type_name;
 
-struct Bar<M>(M);
+struct Bar<M>(#[allow(unused_tuple_struct_fields)] M);
 
 impl<M> Bar<M> {
     fn foo(&self) -> &'static str {
diff --git a/src/test/ui/issues/issue-7911.rs b/src/test/ui/issues/issue-7911.rs
index de833324bd2..f64887136ca 100644
--- a/src/test/ui/issues/issue-7911.rs
+++ b/src/test/ui/issues/issue-7911.rs
@@ -6,7 +6,7 @@
 trait FooBar {
     fn dummy(&self) { }
 }
-struct Bar(i32);
+struct Bar(#[allow(unused_tuple_struct_fields)] i32);
 struct Foo { bar: Bar }
 
 impl FooBar for Bar {}
diff --git a/src/test/ui/layout/unsafe-cell-hides-niche.rs b/src/test/ui/layout/unsafe-cell-hides-niche.rs
index 73b32066fad..68bcc3c1aff 100644
--- a/src/test/ui/layout/unsafe-cell-hides-niche.rs
+++ b/src/test/ui/layout/unsafe-cell-hides-niche.rs
@@ -14,10 +14,10 @@ use std::mem::size_of;
 use std::num::NonZeroU32 as N32;
 use std::sync::{Mutex, RwLock};
 
-struct Wrapper<T>(T);
+struct Wrapper<T>(#[allow(unused_tuple_struct_fields)] T);
 
 #[repr(transparent)]
-struct Transparent<T>(T);
+struct Transparent<T>(#[allow(unused_tuple_struct_fields)] T);
 
 struct NoNiche<T>(UnsafeCell<T>);
 
diff --git a/src/test/ui/lint/dead-code/tuple-struct-field.rs b/src/test/ui/lint/dead-code/tuple-struct-field.rs
index c8fd32c64d6..b15d7063686 100644
--- a/src/test/ui/lint/dead-code/tuple-struct-field.rs
+++ b/src/test/ui/lint/dead-code/tuple-struct-field.rs
@@ -1,12 +1,37 @@
-// check-pass
+#![deny(unused_tuple_struct_fields)]
+//~^ NOTE: the lint level is defined here
 
-#![deny(dead_code)]
+use std::marker::PhantomData;
 
 const LEN: usize = 4;
 
-#[derive(Debug)]
-struct Wrapper([u8; LEN]);
+struct SingleUnused(i32, [u8; LEN], String);
+//~^ ERROR: field `1` is never read
+//~| NOTE: field in this struct
+//~| HELP: consider changing the field to be of unit type
+
+struct MultipleUnused(i32, f32, String, u8);
+//~^ ERROR: fields `0`, `1`, `2` and `3` are never read
+//~| NOTE: fields in this struct
+//~| HELP: consider changing the fields to be of unit type
+
+struct GoodUnit(());
+
+struct GoodPhantom(PhantomData<i32>);
+
+struct Void;
+struct GoodVoid(Void);
 
 fn main() {
-    println!("{:?}", Wrapper([0, 1, 2, 3]));
+    let w = SingleUnused(42, [0, 1, 2, 3], "abc".to_string());
+    let _ = w.0;
+    let _ = w.2;
+
+    let m = MultipleUnused(42, 3.14, "def".to_string(), 4u8);
+
+    let gu = GoodUnit(());
+    let gp = GoodPhantom(PhantomData);
+    let gv = GoodVoid(Void);
+
+    let _ = (gu, gp, gv, m);
 }
diff --git a/src/test/ui/lint/dead-code/tuple-struct-field.stderr b/src/test/ui/lint/dead-code/tuple-struct-field.stderr
new file mode 100644
index 00000000000..ca0989f5b98
--- /dev/null
+++ b/src/test/ui/lint/dead-code/tuple-struct-field.stderr
@@ -0,0 +1,33 @@
+error: field `1` is never read
+  --> $DIR/tuple-struct-field.rs:8:26
+   |
+LL | struct SingleUnused(i32, [u8; LEN], String);
+   |        ------------      ^^^^^^^^^
+   |        |
+   |        field in this struct
+   |
+note: the lint level is defined here
+  --> $DIR/tuple-struct-field.rs:1:9
+   |
+LL | #![deny(unused_tuple_struct_fields)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: consider changing the field to be of unit type to suppress this warning while preserving the field numbering, or remove the field
+   |
+LL | struct SingleUnused(i32, (), String);
+   |                          ~~
+
+error: fields `0`, `1`, `2` and `3` are never read
+  --> $DIR/tuple-struct-field.rs:13:23
+   |
+LL | struct MultipleUnused(i32, f32, String, u8);
+   |        -------------- ^^^  ^^^  ^^^^^^  ^^
+   |        |
+   |        fields in this struct
+   |
+help: consider changing the fields to be of unit type to suppress this warning while preserving the field numbering, or remove the fields
+   |
+LL | struct MultipleUnused((), (), (), ());
+   |                       ~~  ~~  ~~  ~~
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/lint/dead-code/with-impl.rs b/src/test/ui/lint/dead-code/with-impl.rs
index 84829c98e57..812fcdd09b6 100644
--- a/src/test/ui/lint/dead-code/with-impl.rs
+++ b/src/test/ui/lint/dead-code/with-impl.rs
@@ -2,7 +2,7 @@
 
 #![deny(dead_code)]
 
-pub struct GenericFoo<T>(T);
+pub struct GenericFoo<T>(#[allow(unused_tuple_struct_fields)] T);
 
 type Foo = GenericFoo<u32>;
 
diff --git a/src/test/ui/list.rs b/src/test/ui/list.rs
index cb83d4103dc..ffe9f93860a 100644
--- a/src/test/ui/list.rs
+++ b/src/test/ui/list.rs
@@ -3,7 +3,7 @@
 #![allow(non_camel_case_types)]
 // pretty-expanded FIXME #23616
 
-enum list { cons(isize, Box<list>), nil, }
+enum list { #[allow(unused_tuple_struct_fields)] cons(isize, Box<list>), nil, }
 
 pub fn main() {
     list::cons(10, Box::new(list::cons(11, Box::new(list::cons(12, Box::new(list::nil))))));
diff --git a/src/test/ui/macros/html-literals.rs b/src/test/ui/macros/html-literals.rs
index ae45e97c8b0..26f00fed9c4 100644
--- a/src/test/ui/macros/html-literals.rs
+++ b/src/test/ui/macros/html-literals.rs
@@ -88,6 +88,7 @@ pub fn main() {
     );
 }
 
+#[allow(unused_tuple_struct_fields)]
 enum HTMLFragment {
     tag(String, Vec<HTMLFragment> ),
     text(String),
diff --git a/src/test/ui/macros/macro-tt-followed-by-seq.rs b/src/test/ui/macros/macro-tt-followed-by-seq.rs
index 90131ebd920..080dbcfdd41 100644
--- a/src/test/ui/macros/macro-tt-followed-by-seq.rs
+++ b/src/test/ui/macros/macro-tt-followed-by-seq.rs
@@ -5,6 +5,7 @@
 use self::Join::*;
 
 #[derive(Debug)]
+#[allow(unused_tuple_struct_fields)]
 enum Join<A,B> {
   Keep(A,B),
   Skip(A,B),
diff --git a/src/test/ui/methods/method-argument-inference-associated-type.rs b/src/test/ui/methods/method-argument-inference-associated-type.rs
index acd4a8465b0..a3c31fab1c2 100644
--- a/src/test/ui/methods/method-argument-inference-associated-type.rs
+++ b/src/test/ui/methods/method-argument-inference-associated-type.rs
@@ -7,7 +7,7 @@ pub trait Service {
     fn call(&self, _req: Self::Request);
 }
 
-pub struct S<T>(T);
+pub struct S<T>(#[allow(unused_tuple_struct_fields)] T);
 
 impl Service for ClientMap {
     type Request = S<Box<dyn Fn(i32)>>;
diff --git a/src/test/ui/methods/method-probe-no-guessing-dyn-trait.rs b/src/test/ui/methods/method-probe-no-guessing-dyn-trait.rs
index af362efe15c..ec41b711709 100644
--- a/src/test/ui/methods/method-probe-no-guessing-dyn-trait.rs
+++ b/src/test/ui/methods/method-probe-no-guessing-dyn-trait.rs
@@ -15,7 +15,7 @@ trait MyTrait1 {
 
 impl MyTrait1 for Foo<u32> {}
 
-struct Foo<T>(T);
+struct Foo<T>(#[allow(unused_tuple_struct_fields)] T);
 
 impl Deref for Foo<()> {
     type Target = dyn MyTrait1 + 'static;
@@ -33,7 +33,7 @@ trait MyTrait2 {
 }
 
 impl MyTrait2 for u32 {}
-struct Bar<T>(T, u32);
+struct Bar<T>(#[allow(unused_tuple_struct_fields)] T, u32);
 impl Deref for Bar<u8> {
     type Target = dyn MyTrait2 + 'static;
     fn deref(&self) -> &(dyn MyTrait2 + 'static) {
diff --git a/src/test/ui/mir/mir_codegen_switch.rs b/src/test/ui/mir/mir_codegen_switch.rs
index d2589ae4ad2..9c93499d948 100644
--- a/src/test/ui/mir/mir_codegen_switch.rs
+++ b/src/test/ui/mir/mir_codegen_switch.rs
@@ -1,7 +1,7 @@
 // run-pass
 enum Abc {
-    A(u8),
-    B(i8),
+    A(#[allow(unused_tuple_struct_fields)] u8),
+    B(#[allow(unused_tuple_struct_fields)] i8),
     C,
     D,
 }
diff --git a/src/test/ui/mir/mir_fat_ptr.rs b/src/test/ui/mir/mir_fat_ptr.rs
index fb34de62f31..7c3e07c9e34 100644
--- a/src/test/ui/mir/mir_fat_ptr.rs
+++ b/src/test/ui/mir/mir_fat_ptr.rs
@@ -1,7 +1,7 @@
 // run-pass
 // test that ordinary fat pointer operations work.
 
-struct Wrapper<T: ?Sized>(u32, T);
+struct Wrapper<T: ?Sized>(#[allow(unused_tuple_struct_fields)] u32, T);
 
 struct FatPtrContainer<'a> {
     ptr: &'a [u8]
diff --git a/src/test/ui/mir/mir_raw_fat_ptr.rs b/src/test/ui/mir/mir_raw_fat_ptr.rs
index aa2b499b027..6aceefbe715 100644
--- a/src/test/ui/mir/mir_raw_fat_ptr.rs
+++ b/src/test/ui/mir/mir_raw_fat_ptr.rs
@@ -103,6 +103,7 @@ impl<T> Foo for T {
     }
 }
 
+#[allow(unused_tuple_struct_fields)]
 struct S<T:?Sized>(u32, T);
 
 fn main_ref() {
diff --git a/src/test/ui/mir/mir_refs_correct.rs b/src/test/ui/mir/mir_refs_correct.rs
index 729db2d25f5..6cd9526b749 100644
--- a/src/test/ui/mir/mir_refs_correct.rs
+++ b/src/test/ui/mir/mir_refs_correct.rs
@@ -3,7 +3,7 @@
 
 extern crate mir_external_refs as ext;
 
-struct S(u8);
+struct S(#[allow(unused_tuple_struct_fields)] u8);
 #[derive(Debug, PartialEq, Eq)]
 struct Unit;
 
@@ -46,7 +46,7 @@ impl<I, O> T<I, O> for O {}
 impl X for S {}
 
 enum E {
-    U(u8)
+    U(#[allow(unused_tuple_struct_fields)] u8)
 }
 
 #[derive(PartialEq, Debug, Eq)]
diff --git a/src/test/ui/nullable-pointer-iotareduction.rs b/src/test/ui/nullable-pointer-iotareduction.rs
index f9edba67434..d345fec8118 100644
--- a/src/test/ui/nullable-pointer-iotareduction.rs
+++ b/src/test/ui/nullable-pointer-iotareduction.rs
@@ -8,7 +8,7 @@
 // trying to get assert failure messages that at least identify which case
 // failed.
 
-enum E<T> { Thing(isize, T), Nothing((), ((), ()), [i8; 0]) }
+enum E<T> { Thing(isize, T), #[allow(unused_tuple_struct_fields)] Nothing((), ((), ()), [i8; 0]) }
 impl<T> E<T> {
     fn is_none(&self) -> bool {
         match *self {
diff --git a/src/test/ui/optimization-fuel-0.rs b/src/test/ui/optimization-fuel-0.rs
index a97c5750f94..2643dbea1c4 100644
--- a/src/test/ui/optimization-fuel-0.rs
+++ b/src/test/ui/optimization-fuel-0.rs
@@ -6,7 +6,9 @@ use std::mem::size_of;
 
 // compile-flags: -Z fuel=foo=0
 
+#[allow(unused_tuple_struct_fields)]
 struct S1(u8, u16, u8);
+#[allow(unused_tuple_struct_fields)]
 struct S2(u8, u16, u8);
 
 fn main() {
diff --git a/src/test/ui/optimization-fuel-1.rs b/src/test/ui/optimization-fuel-1.rs
index a09f91c68ab..d5e2255d9f0 100644
--- a/src/test/ui/optimization-fuel-1.rs
+++ b/src/test/ui/optimization-fuel-1.rs
@@ -6,7 +6,9 @@ use std::mem::size_of;
 
 // compile-flags: -Z fuel=foo=1
 
+#[allow(unused_tuple_struct_fields)]
 struct S1(u8, u16, u8);
+#[allow(unused_tuple_struct_fields)]
 struct S2(u8, u16, u8);
 
 fn main() {
diff --git a/src/test/ui/packed/packed-struct-drop-aligned.rs b/src/test/ui/packed/packed-struct-drop-aligned.rs
index b95cdbbbaad..9f9f41e2515 100644
--- a/src/test/ui/packed/packed-struct-drop-aligned.rs
+++ b/src/test/ui/packed/packed-struct-drop-aligned.rs
@@ -24,7 +24,7 @@ impl<'a> Drop for Aligned<'a> {
 }
 
 #[repr(transparent)]
-struct NotCopy(u8);
+struct NotCopy(#[allow(unused_tuple_struct_fields)] u8);
 
 #[repr(packed)]
 struct Packed<'a>(NotCopy, Aligned<'a>);
diff --git a/src/test/ui/packed/packed-struct-optimized-enum.rs b/src/test/ui/packed/packed-struct-optimized-enum.rs
index 7ce62464ef0..5e1a1f518c5 100644
--- a/src/test/ui/packed/packed-struct-optimized-enum.rs
+++ b/src/test/ui/packed/packed-struct-optimized-enum.rs
@@ -1,6 +1,6 @@
 // run-pass
 #[repr(packed)]
-struct Packed<T: Copy>(T);
+struct Packed<T: Copy>(#[allow(unused_tuple_struct_fields)] T);
 
 impl<T: Copy> Copy for Packed<T> {}
 impl<T: Copy> Clone for Packed<T> {
diff --git a/src/test/ui/packed/packed-tuple-struct-layout.rs b/src/test/ui/packed/packed-tuple-struct-layout.rs
index b88637fbe56..931be5b9414 100644
--- a/src/test/ui/packed/packed-tuple-struct-layout.rs
+++ b/src/test/ui/packed/packed-tuple-struct-layout.rs
@@ -2,9 +2,11 @@
 use std::mem;
 
 #[repr(packed)]
+#[allow(unused_tuple_struct_fields)]
 struct S4(u8,[u8; 3]);
 
 #[repr(packed)]
+#[allow(unused_tuple_struct_fields)]
 struct S5(u8,u32);
 
 pub fn main() {
diff --git a/src/test/ui/parser/issues/issue-70388-without-witness.fixed b/src/test/ui/parser/issues/issue-70388-without-witness.fixed
index 464e78fd035..8d981405ea1 100644
--- a/src/test/ui/parser/issues/issue-70388-without-witness.fixed
+++ b/src/test/ui/parser/issues/issue-70388-without-witness.fixed
@@ -1,7 +1,7 @@
 // run-rustfix
 // This is for checking if we can apply suggestions as-is.
 
-pub struct Foo(i32);
+pub struct Foo(#[allow(unused_tuple_struct_fields)] i32);
 
 fn main() {
     let Foo(..) = Foo(0); //~ ERROR unexpected `...`
diff --git a/src/test/ui/parser/issues/issue-70388-without-witness.rs b/src/test/ui/parser/issues/issue-70388-without-witness.rs
index 9e35e4c38aa..bf36073083a 100644
--- a/src/test/ui/parser/issues/issue-70388-without-witness.rs
+++ b/src/test/ui/parser/issues/issue-70388-without-witness.rs
@@ -1,7 +1,7 @@
 // run-rustfix
 // This is for checking if we can apply suggestions as-is.
 
-pub struct Foo(i32);
+pub struct Foo(#[allow(unused_tuple_struct_fields)] i32);
 
 fn main() {
     let Foo(...) = Foo(0); //~ ERROR unexpected `...`
diff --git a/src/test/ui/range_inclusive.rs b/src/test/ui/range_inclusive.rs
index 7e7a15924b7..c9107d24ed0 100644
--- a/src/test/ui/range_inclusive.rs
+++ b/src/test/ui/range_inclusive.rs
@@ -11,7 +11,7 @@ fn foo() -> isize { 42 }
 pub fn return_range_to() -> RangeToInclusive<i32> { return ..=1; }
 
 #[derive(Debug)]
-struct P(u8);
+struct P(#[allow(unused_tuple_struct_fields)] u8);
 
 pub fn main() {
     let mut count = 0;
diff --git a/src/test/ui/recursion/issue-26548-recursion-via-normalize.rs b/src/test/ui/recursion/issue-26548-recursion-via-normalize.rs
index 366ea7d3b3f..91958dffcf4 100644
--- a/src/test/ui/recursion/issue-26548-recursion-via-normalize.rs
+++ b/src/test/ui/recursion/issue-26548-recursion-via-normalize.rs
@@ -1,9 +1,8 @@
-//~ ERROR cycle detected when computing layout of `S`
+//~ ERROR cycle detected when computing layout of `core::option::Option<S>`
+//~| NOTE ...which requires computing layout of `S`...
 //~| NOTE ...which requires computing layout of `core::option::Option<<S as Mirror>::It>`...
-//~| NOTE ...which requires computing layout of `core::option::Option<S>`...
-//~| NOTE ...which again requires computing layout of `S`, completing the cycle
-
-// build-fail
+//~| NOTE ...which again requires computing layout of `core::option::Option<S>`, completing the cycle
+//~| NOTE cycle used when computing layout of `core::option::Option<<S as Mirror>::It>`
 
 trait Mirror {
     type It: ?Sized;
@@ -14,6 +13,5 @@ impl<T: ?Sized> Mirror for T {
 struct S(Option<<S as Mirror>::It>);
 
 fn main() {
-    //~^ NOTE cycle used when elaborating drops for `main`
     let _s = S(None);
 }
diff --git a/src/test/ui/recursion/issue-26548-recursion-via-normalize.stderr b/src/test/ui/recursion/issue-26548-recursion-via-normalize.stderr
index 5b675dc9f81..a75097cdbfb 100644
--- a/src/test/ui/recursion/issue-26548-recursion-via-normalize.stderr
+++ b/src/test/ui/recursion/issue-26548-recursion-via-normalize.stderr
@@ -1,13 +1,9 @@
-error[E0391]: cycle detected when computing layout of `S`
+error[E0391]: cycle detected when computing layout of `core::option::Option<S>`
    |
+   = note: ...which requires computing layout of `S`...
    = note: ...which requires computing layout of `core::option::Option<<S as Mirror>::It>`...
-   = note: ...which requires computing layout of `core::option::Option<S>`...
-   = note: ...which again requires computing layout of `S`, completing the cycle
-note: cycle used when elaborating drops for `main`
-  --> $DIR/issue-26548-recursion-via-normalize.rs:16:1
-   |
-LL | fn main() {
-   | ^^^^^^^^^
+   = note: ...which again requires computing layout of `core::option::Option<S>`, completing the cycle
+   = note: cycle used when computing layout of `core::option::Option<<S as Mirror>::It>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-direct-unsafe-ptr-embedded.rs b/src/test/ui/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-direct-unsafe-ptr-embedded.rs
index c6d7166e740..1914e155493 100644
--- a/src/test/ui/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-direct-unsafe-ptr-embedded.rs
+++ b/src/test/ui/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-direct-unsafe-ptr-embedded.rs
@@ -5,7 +5,7 @@
 
 #![warn(pointer_structural_match)]
 
-struct NoDerive(i32);
+struct NoDerive(#[allow(unused_tuple_struct_fields)] i32);
 
 // This impl makes NoDerive irreflexive
 // (which doesn't matter here because `<*const T>::eq` won't recur on `T`).
diff --git a/src/test/ui/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-direct-unsafe-ptr-param.rs b/src/test/ui/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-direct-unsafe-ptr-param.rs
index cc7ea6cde8d..e713b003b00 100644
--- a/src/test/ui/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-direct-unsafe-ptr-param.rs
+++ b/src/test/ui/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-direct-unsafe-ptr-param.rs
@@ -5,7 +5,7 @@
 
 #![warn(pointer_structural_match)]
 
-struct NoDerive(i32);
+struct NoDerive(#[allow(unused_tuple_struct_fields)] i32);
 
 // This impl makes NoDerive irreflexive
 // (which doesn't matter here because `<*const T>::eq` won't recur on `T`).
diff --git a/src/test/ui/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-indirect-unsafe-ptr-embedded.rs b/src/test/ui/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-indirect-unsafe-ptr-embedded.rs
index 86db09cc08f..04da14c5419 100644
--- a/src/test/ui/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-indirect-unsafe-ptr-embedded.rs
+++ b/src/test/ui/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-indirect-unsafe-ptr-embedded.rs
@@ -5,7 +5,7 @@
 
 #![warn(pointer_structural_match)]
 
-struct NoDerive(i32);
+struct NoDerive(#[allow(unused_tuple_struct_fields)] i32);
 
 // This impl makes NoDerive irreflexive
 // (which doesn't matter here because `<*const T>::eq` won't recur on `T`).
diff --git a/src/test/ui/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-indirect-unsafe-ptr-param.rs b/src/test/ui/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-indirect-unsafe-ptr-param.rs
index 99c574d0780..8313c25e753 100644
--- a/src/test/ui/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-indirect-unsafe-ptr-param.rs
+++ b/src/test/ui/rfc-1445-restrict-constants-in-patterns/allow-hide-behind-indirect-unsafe-ptr-param.rs
@@ -5,7 +5,7 @@
 
 #![warn(pointer_structural_match)]
 
-struct NoDerive(i32);
+struct NoDerive(#[allow(unused_tuple_struct_fields)] i32);
 
 // This impl makes NoDerive irreflexive
 // (which doesn't matter here because `<*const T>::eq` won't recur on `T`).
diff --git a/src/test/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.rs b/src/test/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.rs
index 4a8a0949379..7623839fdd1 100644
--- a/src/test/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.rs
+++ b/src/test/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-direct-struct-embedded.rs
@@ -5,7 +5,7 @@
 //
 // See discussion on rust-lang/rust#62307 and rust-lang/rust#62339
 
-struct NoDerive(i32);
+struct NoDerive(#[allow(unused_tuple_struct_fields)] i32);
 
 // This impl makes NoDerive irreflexive.
 impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
diff --git a/src/test/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.rs b/src/test/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.rs
index fe62774d220..894739ff705 100644
--- a/src/test/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.rs
+++ b/src/test/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.rs
@@ -7,7 +7,7 @@
 #![warn(indirect_structural_match)]
 // run-pass
 
-struct NoDerive(i32);
+struct NoDerive(#[allow(unused_tuple_struct_fields)] i32);
 
 // This impl makes NoDerive irreflexive.
 impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
diff --git a/src/test/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.rs b/src/test/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.rs
index c3a30674ea3..1699dae4624 100644
--- a/src/test/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.rs
+++ b/src/test/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.rs
@@ -7,7 +7,7 @@
 #![warn(indirect_structural_match)]
 // run-pass
 
-struct NoDerive(i32);
+struct NoDerive(#[allow(unused_tuple_struct_fields)] i32);
 
 // This impl makes NoDerive irreflexive.
 impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
diff --git a/src/test/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.rs b/src/test/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.rs
index 4d0e80d5af3..2672bdd9e56 100644
--- a/src/test/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.rs
+++ b/src/test/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.rs
@@ -7,7 +7,7 @@
 #![warn(indirect_structural_match)]
 // run-pass
 
-struct NoDerive(i32);
+struct NoDerive(#[allow(unused_tuple_struct_fields)] i32);
 
 // This impl makes NoDerive irreflexive.
 impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
diff --git a/src/test/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.rs b/src/test/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.rs
index 432f196ec81..3489995ae71 100644
--- a/src/test/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.rs
+++ b/src/test/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.rs
@@ -7,7 +7,7 @@
 #![warn(indirect_structural_match)]
 // run-pass
 
-struct NoDerive(i32);
+struct NoDerive(#[allow(unused_tuple_struct_fields)] i32);
 
 // This impl makes NoDerive irreflexive.
 impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop.rs b/src/test/ui/rfc-2632-const-trait-impl/const-drop.rs
index f50e70939df..04462c0a11b 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/const-drop.rs
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-drop.rs
@@ -96,7 +96,7 @@ implements_const_drop! {
 }
 
 fn main() {
-    struct HasDropGlue(Box<u8>);
+    struct HasDropGlue(#[allow(unused_tuple_struct_fields)] Box<u8>);
     struct HasDropImpl;
     impl Drop for HasDropImpl {
         fn drop(&mut self) {
diff --git a/src/test/ui/rfcs/rfc-2151-raw-identifiers/attr.rs b/src/test/ui/rfcs/rfc-2151-raw-identifiers/attr.rs
index 2fe1e05e509..d359067f627 100644
--- a/src/test/ui/rfcs/rfc-2151-raw-identifiers/attr.rs
+++ b/src/test/ui/rfcs/rfc-2151-raw-identifiers/attr.rs
@@ -7,7 +7,7 @@ struct Test {
 }
 
 #[r#derive(r#Debug)]
-struct Test2(u32);
+struct Test2(#[allow(unused_tuple_struct_fields)] u32);
 
 pub fn main() {
     assert_eq!(mem::size_of::<Test>(), 9);
diff --git a/src/test/ui/specialization/specialization-cross-crate.rs b/src/test/ui/specialization/specialization-cross-crate.rs
index 4171505aa37..d9381d66152 100644
--- a/src/test/ui/specialization/specialization-cross-crate.rs
+++ b/src/test/ui/specialization/specialization-cross-crate.rs
@@ -14,7 +14,7 @@ struct NotClone;
 struct MarkedAndClone;
 impl MyMarker for MarkedAndClone {}
 
-struct MyType<T>(T);
+struct MyType<T>(#[allow(unused_tuple_struct_fields)] T);
 impl<T> Foo for MyType<T> {
     default fn foo(&self) -> &'static str {
         "generic MyType"
diff --git a/src/test/ui/specialization/specialization-translate-projections-with-lifetimes.rs b/src/test/ui/specialization/specialization-translate-projections-with-lifetimes.rs
index 5c2781a9c63..904aeaa088b 100644
--- a/src/test/ui/specialization/specialization-translate-projections-with-lifetimes.rs
+++ b/src/test/ui/specialization/specialization-translate-projections-with-lifetimes.rs
@@ -14,7 +14,7 @@ impl<'a> WithAssoc for &'a () {
     type Item = &'a u32;
 }
 
-struct Cloned<I>(I);
+struct Cloned<I>(#[allow(unused_tuple_struct_fields)] I);
 
 impl<'a, I, T: 'a> Iterator for Cloned<I>
     where I: WithAssoc<Item=&'a T>, T: Clone
diff --git a/src/test/ui/stdlib-unit-tests/raw-fat-ptr.rs b/src/test/ui/stdlib-unit-tests/raw-fat-ptr.rs
index 9f50659ed60..6b0b09c9894 100644
--- a/src/test/ui/stdlib-unit-tests/raw-fat-ptr.rs
+++ b/src/test/ui/stdlib-unit-tests/raw-fat-ptr.rs
@@ -39,6 +39,7 @@ impl<T> Foo for T {
     }
 }
 
+#[allow(unused_tuple_struct_fields)]
 struct S<T:?Sized>(u32, T);
 
 fn main() {
diff --git a/src/test/ui/struct-ctor-mangling.rs b/src/test/ui/struct-ctor-mangling.rs
index f242cb8457f..ba6abbf03a5 100644
--- a/src/test/ui/struct-ctor-mangling.rs
+++ b/src/test/ui/struct-ctor-mangling.rs
@@ -4,7 +4,7 @@ fn size_of_val<T>(_: &T) -> usize {
     std::mem::size_of::<T>()
 }
 
-struct Foo(i64);
+struct Foo(#[allow(unused_tuple_struct_fields)] i64);
 
 // Test that the (symbol) mangling of `Foo` (the `struct` type) and that of
 // `typeof Foo` (the function type of the `struct` constructor) don't collide.
diff --git a/src/test/ui/structs-enums/enum-null-pointer-opt.rs b/src/test/ui/structs-enums/enum-null-pointer-opt.rs
index 32fdbf620a9..85fa1eac2e2 100644
--- a/src/test/ui/structs-enums/enum-null-pointer-opt.rs
+++ b/src/test/ui/structs-enums/enum-null-pointer-opt.rs
@@ -10,8 +10,8 @@ use std::sync::Arc;
 trait Trait { fn dummy(&self) { } }
 trait Mirror { type Image; }
 impl<T> Mirror for T { type Image = T; }
-struct ParamTypeStruct<T>(T);
-struct AssocTypeStruct<T>(<T as Mirror>::Image);
+struct ParamTypeStruct<T>(#[allow(unused_tuple_struct_fields)] T);
+struct AssocTypeStruct<T>(#[allow(unused_tuple_struct_fields)] <T as Mirror>::Image);
 #[repr(transparent)]
 union MaybeUninitUnion<T: Copy> {
     _value: T,
@@ -46,7 +46,7 @@ fn main() {
     struct Foo {
         _a: Box<isize>
     }
-    struct Bar(Box<isize>);
+    struct Bar(#[allow(unused_tuple_struct_fields)] Box<isize>);
 
     // Should apply through structs
     assert_eq!(size_of::<Foo>(), size_of::<Option<Foo>>());
diff --git a/src/test/ui/structs-enums/enum-nullable-simplifycfg-misopt.rs b/src/test/ui/structs-enums/enum-nullable-simplifycfg-misopt.rs
index 53892a4e0ae..a05cf8b93d5 100644
--- a/src/test/ui/structs-enums/enum-nullable-simplifycfg-misopt.rs
+++ b/src/test/ui/structs-enums/enum-nullable-simplifycfg-misopt.rs
@@ -6,7 +6,7 @@
  * represented with nullable pointers could be misoptimized in some cases.
  */
 
-enum List<X> { Nil, Cons(X, Box<List<X>>) }
+enum List<X> { Nil, Cons(X, #[allow(unused_tuple_struct_fields)] Box<List<X>>) }
 pub fn main() {
     match List::Cons(10, Box::new(List::Nil)) {
         List::Cons(10, _) => {}
diff --git a/src/test/ui/structs-enums/resource-in-struct.rs b/src/test/ui/structs-enums/resource-in-struct.rs
index 35a4b14bc3f..9613ca62a49 100644
--- a/src/test/ui/structs-enums/resource-in-struct.rs
+++ b/src/test/ui/structs-enums/resource-in-struct.rs
@@ -25,7 +25,7 @@ fn close_res(i: closable) -> close_res {
     }
 }
 
-enum option<T> { none, some(T), }
+enum option<T> { none, some(#[allow(unused_tuple_struct_fields)] T), }
 
 fn sink(_res: option<close_res>) { }
 
diff --git a/src/test/ui/structs-enums/tuple-struct-construct.rs b/src/test/ui/structs-enums/tuple-struct-construct.rs
index 972fc9dc04a..fbf97e6b225 100644
--- a/src/test/ui/structs-enums/tuple-struct-construct.rs
+++ b/src/test/ui/structs-enums/tuple-struct-construct.rs
@@ -1,4 +1,5 @@
 // run-pass
+#[allow(unused_tuple_struct_fields)]
 #[derive(Debug)]
 struct Foo(isize, isize);
 
diff --git a/src/test/ui/structs-enums/uninstantiable-struct.rs b/src/test/ui/structs-enums/uninstantiable-struct.rs
index b1ef525614e..b24effe5a9c 100644
--- a/src/test/ui/structs-enums/uninstantiable-struct.rs
+++ b/src/test/ui/structs-enums/uninstantiable-struct.rs
@@ -1,4 +1,4 @@
 // run-pass
-pub struct Z(&'static Z);
+pub struct Z(#[allow(unused_tuple_struct_fields)] &'static Z);
 
 pub fn main() {}
diff --git a/src/test/ui/trailing-comma.rs b/src/test/ui/trailing-comma.rs
index 97006ae50a0..90adba99e54 100644
--- a/src/test/ui/trailing-comma.rs
+++ b/src/test/ui/trailing-comma.rs
@@ -3,7 +3,7 @@
 
 fn f<T,>(_: T,) {}
 
-struct Foo<T,>(T);
+struct Foo<T,>(#[allow(unused_tuple_struct_fields)] T);
 
 struct Bar;
 
@@ -14,7 +14,7 @@ impl Bar {
 }
 
 enum Baz {
-    Qux(isize,),
+    Qux(#[allow(unused_tuple_struct_fields)] isize,),
 }
 
 #[allow(unused,)]
diff --git a/src/test/ui/traits/augmented-assignments-trait.rs b/src/test/ui/traits/augmented-assignments-trait.rs
index 8c418daffdf..747a5393f12 100644
--- a/src/test/ui/traits/augmented-assignments-trait.rs
+++ b/src/test/ui/traits/augmented-assignments-trait.rs
@@ -1,7 +1,7 @@
 // run-pass
 use std::ops::AddAssign;
 
-struct Int(i32);
+struct Int(#[allow(unused_tuple_struct_fields)] i32);
 
 impl AddAssign for Int {
     fn add_assign(&mut self, _: Int) {
diff --git a/src/test/ui/traits/negative-impls/negated-auto-traits-rpass.rs b/src/test/ui/traits/negative-impls/negated-auto-traits-rpass.rs
index 010dbf24664..a1042f8310a 100644
--- a/src/test/ui/traits/negative-impls/negated-auto-traits-rpass.rs
+++ b/src/test/ui/traits/negative-impls/negated-auto-traits-rpass.rs
@@ -7,7 +7,7 @@ use std::marker::Send;
 pub struct WaitToken;
 impl !Send for WaitToken {}
 
-pub struct Test<T>(T);
+pub struct Test<T>(#[allow(unused_tuple_struct_fields)] T);
 unsafe impl<T: 'static> Send for Test<T> {}
 
 pub fn spawn<F>(_: F) -> () where F: FnOnce(), F: Send + 'static {}
diff --git a/src/test/ui/traits/object/exclusion.rs b/src/test/ui/traits/object/exclusion.rs
index 0b8b0e2f5ef..766dceeaffe 100644
--- a/src/test/ui/traits/object/exclusion.rs
+++ b/src/test/ui/traits/object/exclusion.rs
@@ -8,7 +8,7 @@ trait Future: 'static {
     }
 }
 
-struct Map<A>(A);
+struct Map<A>(#[allow(unused_tuple_struct_fields)] A);
 impl<A: Future> Future for Map<A> {}
 
 pub struct Promise;
diff --git a/src/test/ui/traits/object/generics.rs b/src/test/ui/traits/object/generics.rs
index e5a96af3810..5a4a6aecc6b 100644
--- a/src/test/ui/traits/object/generics.rs
+++ b/src/test/ui/traits/object/generics.rs
@@ -25,7 +25,7 @@ impl<A1, A2, A3> Impl<A1, A2, A3> {
 
 // test for #8601
 
-enum Type<T> { Constant(T) }
+enum Type<T> { Constant(#[allow(unused_tuple_struct_fields)] T) }
 
 trait Trait<K,V> {
     fn method(&self, _: Type<(K,V)>) -> isize;
diff --git a/src/test/ui/traits/pointee-deduction.rs b/src/test/ui/traits/pointee-deduction.rs
index f888246967d..c333b0129c8 100644
--- a/src/test/ui/traits/pointee-deduction.rs
+++ b/src/test/ui/traits/pointee-deduction.rs
@@ -13,8 +13,8 @@ impl Foo for () {
     type Bar = ();
 }
 
-struct Wrapper1<T: Foo>(<T as Foo>::Bar);
-struct Wrapper2<T: Foo>(<Wrapper1<T> as Pointee>::Metadata);
+struct Wrapper1<T: Foo>(#[allow(unused_tuple_struct_fields)] <T as Foo>::Bar);
+struct Wrapper2<T: Foo>(#[allow(unused_tuple_struct_fields)] <Wrapper1<T> as Pointee>::Metadata);
 
 fn main() {
     let _: Wrapper2<()> = Wrapper2(());
diff --git a/src/test/ui/traits/principal-less-objects.rs b/src/test/ui/traits/principal-less-objects.rs
index 82c76eb693a..62bad0d7d77 100644
--- a/src/test/ui/traits/principal-less-objects.rs
+++ b/src/test/ui/traits/principal-less-objects.rs
@@ -7,7 +7,7 @@ use std::mem;
 // Array is to make sure the size is not exactly pointer-size, so
 // we can be sure we are measuring the right size in the
 // `size_of_val` test.
-struct SetOnDrop<'a>(&'a AtomicUsize, [u8; 64]);
+struct SetOnDrop<'a>(&'a AtomicUsize, #[allow(unused_tuple_struct_fields)] [u8; 64]);
 impl<'a> Drop for SetOnDrop<'a> {
     fn drop(&mut self) {
         self.0.store(self.0.load(Ordering::Relaxed) + 1, Ordering::Relaxed);
diff --git a/src/test/ui/type-alias-enum-variants/enum-variant-generic-args-pass.rs b/src/test/ui/type-alias-enum-variants/enum-variant-generic-args-pass.rs
index 19fcc78721a..0aa644db052 100644
--- a/src/test/ui/type-alias-enum-variants/enum-variant-generic-args-pass.rs
+++ b/src/test/ui/type-alias-enum-variants/enum-variant-generic-args-pass.rs
@@ -9,7 +9,7 @@
 
 #![allow(irrefutable_let_patterns)]
 
-enum Enum<T> { TSVariant(T), SVariant { _v: T }, UVariant }
+enum Enum<T> { TSVariant(#[allow(unused_tuple_struct_fields)] T), SVariant { _v: T }, UVariant }
 type Alias<T> = Enum<T>;
 type AliasFixed = Enum<()>;
 
diff --git a/src/test/ui/unboxed-closures/type-id-higher-rank.rs b/src/test/ui/unboxed-closures/type-id-higher-rank.rs
index 355d1109941..1f8aec205fb 100644
--- a/src/test/ui/unboxed-closures/type-id-higher-rank.rs
+++ b/src/test/ui/unboxed-closures/type-id-higher-rank.rs
@@ -4,7 +4,7 @@
 
 use std::any::{Any, TypeId};
 
-struct Struct<'a>(&'a ());
+struct Struct<'a>(#[allow(unused_tuple_struct_fields)] &'a ());
 trait Trait<'a> {}
 
 fn main() {
diff --git a/src/test/ui/unsized-locals/unsized-exprs-rpass.rs b/src/test/ui/unsized-locals/unsized-exprs-rpass.rs
index 8fcb6d93d39..175b02fcb81 100644
--- a/src/test/ui/unsized-locals/unsized-exprs-rpass.rs
+++ b/src/test/ui/unsized-locals/unsized-exprs-rpass.rs
@@ -2,7 +2,7 @@
 #![allow(incomplete_features, unused_braces, unused_parens)]
 #![feature(unsized_tuple_coercion, unsized_locals, unsized_fn_params)]
 
-struct A<X: ?Sized>(X);
+struct A<X: ?Sized>(#[allow(unused_tuple_struct_fields)] X);
 
 fn udrop<T: ?Sized>(_x: T) {}
 fn foo() -> Box<[u8]> {
diff --git a/src/test/ui/unsized/unchanged-param.rs b/src/test/ui/unsized/unchanged-param.rs
index 93c7af68ac3..6bdc89310eb 100644
--- a/src/test/ui/unsized/unchanged-param.rs
+++ b/src/test/ui/unsized/unchanged-param.rs
@@ -1,8 +1,8 @@
 // run-pass
 // Test that we allow unsizing even if there is an unchanged param in the
 // field getting unsized.
-struct A<T, U: ?Sized + 'static>(T, B<T, U>);
-struct B<T, U: ?Sized>(T, U);
+struct A<T, U: ?Sized + 'static>(#[allow(unused_tuple_struct_fields)] T, B<T, U>);
+struct B<T, U: ?Sized>(#[allow(unused_tuple_struct_fields)] T, U);
 
 fn main() {
     let x: A<[u32; 1], [u32; 1]> = A([0; 1], B([0; 1], [0; 1]));
diff --git a/src/tools/clippy/tests/ui/borrow_interior_mutable_const/auxiliary/helper.rs b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/auxiliary/helper.rs
index 2289f7875f0..f13733af3d0 100644
--- a/src/tools/clippy/tests/ui/borrow_interior_mutable_const/auxiliary/helper.rs
+++ b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/auxiliary/helper.rs
@@ -2,6 +2,7 @@
 // As the most common case is the `http` crate, it replicates `http::HeadewrName`'s structure.
 
 #![allow(clippy::declare_interior_mutable_const)]
+#![allow(unused_tuple_struct_fields)]
 
 use std::sync::atomic::AtomicUsize;
 
diff --git a/src/tools/clippy/tests/ui/format.fixed b/src/tools/clippy/tests/ui/format.fixed
index f4db2d20c71..6b754f3bd71 100644
--- a/src/tools/clippy/tests/ui/format.fixed
+++ b/src/tools/clippy/tests/ui/format.fixed
@@ -1,6 +1,7 @@
 // run-rustfix
 
 #![allow(
+    unused_tuple_struct_fields,
     clippy::print_literal,
     clippy::redundant_clone,
     clippy::to_string_in_format_args,
diff --git a/src/tools/clippy/tests/ui/format.rs b/src/tools/clippy/tests/ui/format.rs
index bf687cb1e96..ca9826b356e 100644
--- a/src/tools/clippy/tests/ui/format.rs
+++ b/src/tools/clippy/tests/ui/format.rs
@@ -1,6 +1,7 @@
 // run-rustfix
 
 #![allow(
+    unused_tuple_struct_fields,
     clippy::print_literal,
     clippy::redundant_clone,
     clippy::to_string_in_format_args,
diff --git a/src/tools/clippy/tests/ui/format.stderr b/src/tools/clippy/tests/ui/format.stderr
index a0f8e7d1937..6c35caeb034 100644
--- a/src/tools/clippy/tests/ui/format.stderr
+++ b/src/tools/clippy/tests/ui/format.stderr
@@ -1,5 +1,5 @@
 error: useless use of `format!`
-  --> $DIR/format.rs:18:5
+  --> $DIR/format.rs:19:5
    |
 LL |     format!("foo");
    |     ^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"foo".to_string()`
@@ -7,19 +7,19 @@ LL |     format!("foo");
    = note: `-D clippy::useless-format` implied by `-D warnings`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:19:5
+  --> $DIR/format.rs:20:5
    |
 LL |     format!("{{}}");
    |     ^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"{}".to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:20:5
+  --> $DIR/format.rs:21:5
    |
 LL |     format!("{{}} abc {{}}");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"{} abc {}".to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:21:5
+  --> $DIR/format.rs:22:5
    |
 LL | /     format!(
 LL | |         r##"foo {{}}
@@ -34,91 +34,91 @@ LL ~ " bar"##.to_string();
    |
 
 error: useless use of `format!`
-  --> $DIR/format.rs:26:13
+  --> $DIR/format.rs:27:13
    |
 LL |     let _ = format!("");
    |             ^^^^^^^^^^^ help: consider using `String::new()`: `String::new()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:28:5
+  --> $DIR/format.rs:29:5
    |
 LL |     format!("{}", "foo");
    |     ^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"foo".to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:32:5
+  --> $DIR/format.rs:33:5
    |
 LL |     format!("{:+}", "foo"); // Warn when the format makes no difference.
    |     ^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"foo".to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:33:5
+  --> $DIR/format.rs:34:5
    |
 LL |     format!("{:<}", "foo"); // Warn when the format makes no difference.
    |     ^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"foo".to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:38:5
+  --> $DIR/format.rs:39:5
    |
 LL |     format!("{}", arg);
    |     ^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `arg.to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:42:5
+  --> $DIR/format.rs:43:5
    |
 LL |     format!("{:+}", arg); // Warn when the format makes no difference.
    |     ^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `arg.to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:43:5
+  --> $DIR/format.rs:44:5
    |
 LL |     format!("{:<}", arg); // Warn when the format makes no difference.
    |     ^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `arg.to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:70:5
+  --> $DIR/format.rs:71:5
    |
 LL |     format!("{}", 42.to_string());
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `42.to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:72:5
+  --> $DIR/format.rs:73:5
    |
 LL |     format!("{}", x.display().to_string());
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `x.display().to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:76:18
+  --> $DIR/format.rs:77:18
    |
 LL |     let _ = Some(format!("{}", a + "bar"));
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `a + "bar"`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:80:22
+  --> $DIR/format.rs:81:22
    |
 LL |     let _s: String = format!("{}", &*v.join("/n"));
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `(&*v.join("/n")).to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:86:13
+  --> $DIR/format.rs:87:13
    |
 LL |     let _ = format!("{x}");
    |             ^^^^^^^^^^^^^^ help: consider using `.to_string()`: `x.to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:88:13
+  --> $DIR/format.rs:89:13
    |
 LL |     let _ = format!("{y}", y = x);
    |             ^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `x.to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:92:13
+  --> $DIR/format.rs:93:13
    |
 LL |     let _ = format!("{abc}");
    |             ^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `abc.to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:94:13
+  --> $DIR/format.rs:95:13
    |
 LL |     let _ = format!("{xx}");
    |             ^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `xx.to_string()`
diff --git a/src/tools/clippy/tests/ui/from_iter_instead_of_collect.fixed b/src/tools/clippy/tests/ui/from_iter_instead_of_collect.fixed
index 403c3b3e443..48f8093311c 100644
--- a/src/tools/clippy/tests/ui/from_iter_instead_of_collect.fixed
+++ b/src/tools/clippy/tests/ui/from_iter_instead_of_collect.fixed
@@ -1,7 +1,7 @@
 // run-rustfix
 
 #![warn(clippy::from_iter_instead_of_collect)]
-#![allow(unused_imports)]
+#![allow(unused_imports, unused_tuple_struct_fields)]
 
 use std::collections::{BTreeMap, BTreeSet, HashMap, VecDeque};
 
diff --git a/src/tools/clippy/tests/ui/from_iter_instead_of_collect.rs b/src/tools/clippy/tests/ui/from_iter_instead_of_collect.rs
index fefc7b01a65..ebe0ad278be 100644
--- a/src/tools/clippy/tests/ui/from_iter_instead_of_collect.rs
+++ b/src/tools/clippy/tests/ui/from_iter_instead_of_collect.rs
@@ -1,7 +1,7 @@
 // run-rustfix
 
 #![warn(clippy::from_iter_instead_of_collect)]
-#![allow(unused_imports)]
+#![allow(unused_imports, unused_tuple_struct_fields)]
 
 use std::collections::{BTreeMap, BTreeSet, HashMap, VecDeque};
 
diff --git a/src/tools/clippy/tests/ui/must_use_candidates.fixed b/src/tools/clippy/tests/ui/must_use_candidates.fixed
index 9556f6f82cc..04a74a009e0 100644
--- a/src/tools/clippy/tests/ui/must_use_candidates.fixed
+++ b/src/tools/clippy/tests/ui/must_use_candidates.fixed
@@ -1,6 +1,6 @@
 // run-rustfix
 #![feature(never_type)]
-#![allow(unused_mut, clippy::redundant_allocation)]
+#![allow(unused_mut, unused_tuple_struct_fields, clippy::redundant_allocation)]
 #![warn(clippy::must_use_candidate)]
 use std::rc::Rc;
 use std::sync::atomic::{AtomicBool, Ordering};
diff --git a/src/tools/clippy/tests/ui/must_use_candidates.rs b/src/tools/clippy/tests/ui/must_use_candidates.rs
index 37324220171..f04122f4eea 100644
--- a/src/tools/clippy/tests/ui/must_use_candidates.rs
+++ b/src/tools/clippy/tests/ui/must_use_candidates.rs
@@ -1,6 +1,6 @@
 // run-rustfix
 #![feature(never_type)]
-#![allow(unused_mut, clippy::redundant_allocation)]
+#![allow(unused_mut, unused_tuple_struct_fields, clippy::redundant_allocation)]
 #![warn(clippy::must_use_candidate)]
 use std::rc::Rc;
 use std::sync::atomic::{AtomicBool, Ordering};
diff --git a/src/tools/clippy/tests/ui/numbered_fields.fixed b/src/tools/clippy/tests/ui/numbered_fields.fixed
index 3710b3e9c81..68c987eb4c6 100644
--- a/src/tools/clippy/tests/ui/numbered_fields.fixed
+++ b/src/tools/clippy/tests/ui/numbered_fields.fixed
@@ -1,5 +1,6 @@
 //run-rustfix
 #![warn(clippy::init_numbered_fields)]
+#![allow(unused_tuple_struct_fields)]
 
 #[derive(Default)]
 struct TupleStruct(u32, u32, u8);
diff --git a/src/tools/clippy/tests/ui/numbered_fields.rs b/src/tools/clippy/tests/ui/numbered_fields.rs
index 2af84bc0642..2ef4fb4de53 100644
--- a/src/tools/clippy/tests/ui/numbered_fields.rs
+++ b/src/tools/clippy/tests/ui/numbered_fields.rs
@@ -1,5 +1,6 @@
 //run-rustfix
 #![warn(clippy::init_numbered_fields)]
+#![allow(unused_tuple_struct_fields)]
 
 #[derive(Default)]
 struct TupleStruct(u32, u32, u8);
diff --git a/src/tools/clippy/tests/ui/numbered_fields.stderr b/src/tools/clippy/tests/ui/numbered_fields.stderr
index 01691c8b141..60c0d789806 100644
--- a/src/tools/clippy/tests/ui/numbered_fields.stderr
+++ b/src/tools/clippy/tests/ui/numbered_fields.stderr
@@ -1,5 +1,5 @@
 error: used a field initializer for a tuple struct
-  --> $DIR/numbered_fields.rs:18:13
+  --> $DIR/numbered_fields.rs:19:13
    |
 LL |       let _ = TupleStruct {
    |  _____________^
@@ -12,7 +12,7 @@ LL | |     };
    = note: `-D clippy::init-numbered-fields` implied by `-D warnings`
 
 error: used a field initializer for a tuple struct
-  --> $DIR/numbered_fields.rs:25:13
+  --> $DIR/numbered_fields.rs:26:13
    |
 LL |       let _ = TupleStruct {
    |  _____________^
diff --git a/src/tools/clippy/tests/ui/option_if_let_else.fixed b/src/tools/clippy/tests/ui/option_if_let_else.fixed
index e12e13a57f1..b6d5e106f05 100644
--- a/src/tools/clippy/tests/ui/option_if_let_else.fixed
+++ b/src/tools/clippy/tests/ui/option_if_let_else.fixed
@@ -1,6 +1,7 @@
 // run-rustfix
 #![warn(clippy::option_if_let_else)]
 #![allow(
+    unused_tuple_struct_fields,
     clippy::redundant_closure,
     clippy::ref_option_ref,
     clippy::equatable_if_let,
diff --git a/src/tools/clippy/tests/ui/option_if_let_else.rs b/src/tools/clippy/tests/ui/option_if_let_else.rs
index b5206fc26a9..35bae159343 100644
--- a/src/tools/clippy/tests/ui/option_if_let_else.rs
+++ b/src/tools/clippy/tests/ui/option_if_let_else.rs
@@ -1,6 +1,7 @@
 // run-rustfix
 #![warn(clippy::option_if_let_else)]
 #![allow(
+    unused_tuple_struct_fields,
     clippy::redundant_closure,
     clippy::ref_option_ref,
     clippy::equatable_if_let,
diff --git a/src/tools/clippy/tests/ui/option_if_let_else.stderr b/src/tools/clippy/tests/ui/option_if_let_else.stderr
index 40aef977b98..daba606004e 100644
--- a/src/tools/clippy/tests/ui/option_if_let_else.stderr
+++ b/src/tools/clippy/tests/ui/option_if_let_else.stderr
@@ -1,5 +1,5 @@
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:11:5
+  --> $DIR/option_if_let_else.rs:12:5
    |
 LL | /     if let Some(x) = string {
 LL | |         (true, x)
@@ -11,19 +11,19 @@ LL | |     }
    = note: `-D clippy::option-if-let-else` implied by `-D warnings`
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:29:13
+  --> $DIR/option_if_let_else.rs:30:13
    |
 LL |     let _ = if let Some(s) = *string { s.len() } else { 0 };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `string.map_or(0, |s| s.len())`
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:30:13
+  --> $DIR/option_if_let_else.rs:31:13
    |
 LL |     let _ = if let Some(s) = &num { s } else { &0 };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.as_ref().map_or(&0, |s| s)`
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:31:13
+  --> $DIR/option_if_let_else.rs:32:13
    |
 LL |       let _ = if let Some(s) = &mut num {
    |  _____________^
@@ -43,13 +43,13 @@ LL ~     });
    |
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:37:13
+  --> $DIR/option_if_let_else.rs:38:13
    |
 LL |     let _ = if let Some(ref s) = num { s } else { &0 };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.as_ref().map_or(&0, |s| s)`
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:38:13
+  --> $DIR/option_if_let_else.rs:39:13
    |
 LL |       let _ = if let Some(mut s) = num {
    |  _____________^
@@ -69,7 +69,7 @@ LL ~     });
    |
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:44:13
+  --> $DIR/option_if_let_else.rs:45:13
    |
 LL |       let _ = if let Some(ref mut s) = num {
    |  _____________^
@@ -89,7 +89,7 @@ LL ~     });
    |
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:53:5
+  --> $DIR/option_if_let_else.rs:54:5
    |
 LL | /     if let Some(x) = arg {
 LL | |         let y = x * x;
@@ -108,7 +108,7 @@ LL +     })
    |
 
 error: use Option::map_or_else instead of an if let/else
-  --> $DIR/option_if_let_else.rs:66:13
+  --> $DIR/option_if_let_else.rs:67:13
    |
 LL |       let _ = if let Some(x) = arg {
    |  _____________^
@@ -120,7 +120,7 @@ LL | |     };
    | |_____^ help: try: `arg.map_or_else(|| side_effect(), |x| x)`
 
 error: use Option::map_or_else instead of an if let/else
-  --> $DIR/option_if_let_else.rs:75:13
+  --> $DIR/option_if_let_else.rs:76:13
    |
 LL |       let _ = if let Some(x) = arg {
    |  _____________^
@@ -143,7 +143,7 @@ LL ~     }, |x| x * x * x * x);
    |
 
 error: use Option::map_or_else instead of an if let/else
-  --> $DIR/option_if_let_else.rs:108:13
+  --> $DIR/option_if_let_else.rs:109:13
    |
 LL | /             if let Some(idx) = s.find('.') {
 LL | |                 vec![s[..idx].to_string(), s[idx..].to_string()]
@@ -153,13 +153,13 @@ LL | |             }
    | |_____________^ help: try: `s.find('.').map_or_else(|| vec![s.to_string()], |idx| vec![s[..idx].to_string(), s[idx..].to_string()])`
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:132:13
+  --> $DIR/option_if_let_else.rs:133:13
    |
 LL |     let _ = if let Some(x) = optional { x + 2 } else { 5 };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `optional.map_or(5, |x| x + 2)`
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:141:13
+  --> $DIR/option_if_let_else.rs:142:13
    |
 LL |       let _ = if let Some(x) = Some(0) {
    |  _____________^
@@ -181,13 +181,13 @@ LL ~         });
    |
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:169:13
+  --> $DIR/option_if_let_else.rs:170:13
    |
 LL |     let _ = if let Some(x) = Some(0) { s.len() + x } else { s.len() };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Some(0).map_or(s.len(), |x| s.len() + x)`
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:173:13
+  --> $DIR/option_if_let_else.rs:174:13
    |
 LL |       let _ = if let Some(x) = Some(0) {
    |  _____________^
diff --git a/src/tools/clippy/tests/ui/unreadable_literal.fixed b/src/tools/clippy/tests/ui/unreadable_literal.fixed
index e726b652ef1..a67363b09ea 100644
--- a/src/tools/clippy/tests/ui/unreadable_literal.fixed
+++ b/src/tools/clippy/tests/ui/unreadable_literal.fixed
@@ -1,6 +1,7 @@
 // run-rustfix
 
 #![warn(clippy::unreadable_literal)]
+#![allow(unused_tuple_struct_fields)]
 
 struct Foo(u64);
 
diff --git a/src/tools/clippy/tests/ui/unreadable_literal.rs b/src/tools/clippy/tests/ui/unreadable_literal.rs
index 5bbb2fc9dc1..82f04e7ced5 100644
--- a/src/tools/clippy/tests/ui/unreadable_literal.rs
+++ b/src/tools/clippy/tests/ui/unreadable_literal.rs
@@ -1,6 +1,7 @@
 // run-rustfix
 
 #![warn(clippy::unreadable_literal)]
+#![allow(unused_tuple_struct_fields)]
 
 struct Foo(u64);
 
diff --git a/src/tools/clippy/tests/ui/unreadable_literal.stderr b/src/tools/clippy/tests/ui/unreadable_literal.stderr
index ee5466fd517..b51130c6a6a 100644
--- a/src/tools/clippy/tests/ui/unreadable_literal.stderr
+++ b/src/tools/clippy/tests/ui/unreadable_literal.stderr
@@ -1,5 +1,5 @@
 error: digits of hex or binary literal not grouped by four
-  --> $DIR/unreadable_literal.rs:25:9
+  --> $DIR/unreadable_literal.rs:26:9
    |
 LL |         0x1_234_567,
    |         ^^^^^^^^^^^ help: consider: `0x0123_4567`
@@ -7,7 +7,7 @@ LL |         0x1_234_567,
    = note: `-D clippy::unusual-byte-groupings` implied by `-D warnings`
 
 error: long literal lacking separators
-  --> $DIR/unreadable_literal.rs:33:17
+  --> $DIR/unreadable_literal.rs:34:17
    |
 LL |     let _bad = (0b110110_i64, 0x12345678_usize, 123456_f32, 1.234567_f32);
    |                 ^^^^^^^^^^^^ help: consider: `0b11_0110_i64`
@@ -15,55 +15,55 @@ LL |     let _bad = (0b110110_i64, 0x12345678_usize, 123456_f32, 1.234567_f32);
    = note: `-D clippy::unreadable-literal` implied by `-D warnings`
 
 error: long literal lacking separators
-  --> $DIR/unreadable_literal.rs:33:31
+  --> $DIR/unreadable_literal.rs:34:31
    |
 LL |     let _bad = (0b110110_i64, 0x12345678_usize, 123456_f32, 1.234567_f32);
    |                               ^^^^^^^^^^^^^^^^ help: consider: `0x1234_5678_usize`
 
 error: long literal lacking separators
-  --> $DIR/unreadable_literal.rs:33:49
+  --> $DIR/unreadable_literal.rs:34:49
    |
 LL |     let _bad = (0b110110_i64, 0x12345678_usize, 123456_f32, 1.234567_f32);
    |                                                 ^^^^^^^^^^ help: consider: `123_456_f32`
 
 error: long literal lacking separators
-  --> $DIR/unreadable_literal.rs:33:61
+  --> $DIR/unreadable_literal.rs:34:61
    |
 LL |     let _bad = (0b110110_i64, 0x12345678_usize, 123456_f32, 1.234567_f32);
    |                                                             ^^^^^^^^^^^^ help: consider: `1.234_567_f32`
 
 error: long literal lacking separators
-  --> $DIR/unreadable_literal.rs:35:20
+  --> $DIR/unreadable_literal.rs:36:20
    |
 LL |     let _bad_sci = 1.123456e1;
    |                    ^^^^^^^^^^ help: consider: `1.123_456e1`
 
 error: long literal lacking separators
-  --> $DIR/unreadable_literal.rs:37:18
+  --> $DIR/unreadable_literal.rs:38:18
    |
 LL |     let _fail1 = 0xabcdef;
    |                  ^^^^^^^^ help: consider: `0x00ab_cdef`
 
 error: long literal lacking separators
-  --> $DIR/unreadable_literal.rs:38:23
+  --> $DIR/unreadable_literal.rs:39:23
    |
 LL |     let _fail2: u32 = 0xBAFEBAFE;
    |                       ^^^^^^^^^^ help: consider: `0xBAFE_BAFE`
 
 error: long literal lacking separators
-  --> $DIR/unreadable_literal.rs:39:18
+  --> $DIR/unreadable_literal.rs:40:18
    |
 LL |     let _fail3 = 0xabcdeff;
    |                  ^^^^^^^^^ help: consider: `0x0abc_deff`
 
 error: long literal lacking separators
-  --> $DIR/unreadable_literal.rs:40:24
+  --> $DIR/unreadable_literal.rs:41:24
    |
 LL |     let _fail4: i128 = 0xabcabcabcabcabcabc;
    |                        ^^^^^^^^^^^^^^^^^^^^ help: consider: `0x00ab_cabc_abca_bcab_cabc`
 
 error: long literal lacking separators
-  --> $DIR/unreadable_literal.rs:41:18
+  --> $DIR/unreadable_literal.rs:42:18
    |
 LL |     let _fail5 = 1.100300400;
    |                  ^^^^^^^^^^^ help: consider: `1.100_300_400`