diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index dddd61e9f0ba0..254cb753d3a17 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -474,7 +474,12 @@ pub(crate) struct RustcTrivialFieldReadsParser; impl NoArgsAttributeParser for RustcTrivialFieldReadsParser { const PATH: &[Symbol] = &[sym::rustc_trivial_field_reads]; - const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Trait)]); + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ + Allow(Target::Fn), + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::Method(MethodKind::Trait { body: true })), + Allow(Target::Method(MethodKind::TraitImpl)), + ]); const STABILITY: AttributeStability = unstable!(rustc_attrs); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcTrivialFieldReads; } diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs index af3db65bd0a63..6bbc24568a86c 100644 --- a/compiler/rustc_builtin_macros/src/deriving/clone.rs +++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs @@ -104,7 +104,10 @@ pub(crate) fn expand_deriving_clone( explicit_self: true, nonself_args: Vec::new(), ret_ty: Self_, - attributes: thin_vec![cx.attr_word(sym::inline, span)], + attributes: thin_vec![ + cx.attr_word(sym::inline, span), + cx.attr_word(sym::rustc_trivial_field_reads, span) + ], fieldless_variants_strategy: FieldlessVariantsStrategy::Default, combine_substructure: substructure, }], diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs index c41a4e4fd6b8d..c667cfbdfb76e 100644 --- a/compiler/rustc_builtin_macros/src/deriving/debug.rs +++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs @@ -32,7 +32,10 @@ pub(crate) fn expand_deriving_debug( explicit_self: true, nonself_args: vec![(fmtr, sym::character('f'))], ret_ty: Path(path_std!(fmt::Result)), - attributes: thin_vec![cx.attr_word(sym::inline, span)], + attributes: thin_vec![ + cx.attr_word(sym::inline, span), + cx.attr_word(sym::rustc_trivial_field_reads, span) + ], fieldless_variants_strategy: FieldlessVariantsStrategy::SpecializeIfAllVariantsFieldless, combine_substructure: combine_substructure(Box::new(|a, b, c| { diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 6e0669840d48c..824d9d940e81a 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -59,7 +59,7 @@ fn should_explore(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { | DefKind::ExternCrate | DefKind::Use | DefKind::Ctor(..) - | DefKind::ForeignMod => true, + | DefKind::ForeignMod => !find_attr!(tcx, def_id, RustcTrivialFieldReads), DefKind::TyParam | DefKind::ConstParam @@ -432,17 +432,16 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { ControlFlow::Continue(()) } - /// Automatically generated items marked with `rustc_trivial_field_reads` + /// Items marked with `rustc_trivial_field_reads` /// will be ignored for the purposes of dead code analysis (see PR #85200 - /// for discussion). + /// for discussion, and PR #160666). fn should_ignore_impl_item(&mut self, impl_item: &hir::ImplItem<'_>) -> bool { if let hir::ImplItemImplKind::Trait { .. } = impl_item.impl_kind && let impl_of = self.tcx.local_parent(impl_item.owner_id.def_id) - && self.tcx.is_automatically_derived(impl_of.to_def_id()) - && let trait_ref = - self.tcx.impl_trait_ref(impl_of).instantiate_identity().skip_norm_wip() - && find_attr!(self.tcx, trait_ref.def_id, RustcTrivialFieldReads) + && find_attr!(self.tcx, impl_item.owner_id.def_id, RustcTrivialFieldReads) { + let trait_ref = self.tcx.impl_trait_ref(impl_of).instantiate_identity().skip_norm_wip(); + if let ty::Adt(adt_def, _) = trait_ref.self_ty().kind() && let Some(adt_def_id) = adt_def.did().as_local() { @@ -451,7 +450,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { return true; } - false + return false; } fn visit_node( diff --git a/library/core/src/clone.rs b/library/core/src/clone.rs index f124b8bceaded..6ee9d0ae77cfc 100644 --- a/library/core/src/clone.rs +++ b/library/core/src/clone.rs @@ -189,7 +189,6 @@ mod uninit; #[stable(feature = "rust1", since = "1.0.0")] #[lang = "clone"] #[rustc_diagnostic_item = "Clone"] -#[rustc_trivial_field_reads] #[rustc_const_unstable(feature = "const_clone", issue = "142757")] pub const trait Clone: Sized { /// Returns a duplicate of the value. @@ -285,7 +284,7 @@ pub const unsafe trait TrivialClone: [const] Clone {} /// Derive macro generating an impl of the trait `Clone`. #[rustc_builtin_macro] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] -#[allow_internal_unstable(core_intrinsics, derive_clone_copy_internals, trivial_clone)] +#[allow_internal_unstable(core_intrinsics, derive_clone_copy_internals, trivial_clone, rustc_attrs)] pub macro Clone($item:item) { /* compiler built-in */ } diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 6a4c58afc16f3..d5c0043d52565 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -1049,7 +1049,6 @@ impl Display for Arguments<'_> { )] #[doc(alias = "{:?}")] #[rustc_diagnostic_item = "Debug"] -#[rustc_trivial_field_reads] pub trait Debug: PointeeSized { #[doc = include_str!("fmt_trait_method_doc.md")] /// @@ -1089,7 +1088,7 @@ pub(crate) mod macros { /// Derive macro generating an impl of the trait `Debug`. #[rustc_builtin_macro] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] - #[allow_internal_unstable(core_intrinsics, fmt_helpers_for_derive)] + #[allow_internal_unstable(core_intrinsics, fmt_helpers_for_derive, rustc_attrs)] pub macro Debug($item:item) { /* compiler built-in */ } diff --git a/tests/ui/attributes/trivial-field-reads-invalid-targets.rs b/tests/ui/attributes/trivial-field-reads-invalid-targets.rs new file mode 100644 index 0000000000000..f40ccab615511 --- /dev/null +++ b/tests/ui/attributes/trivial-field-reads-invalid-targets.rs @@ -0,0 +1,23 @@ +//! Checks that `#[rustc_trivial_field_reads]` are not allowed due to invalid targets + +#![feature(rustc_attrs)] +#![deny(dead_code)] + +trait Whatever { + #[rustc_trivial_field_reads] //~ERROR the `rustc_trivial_field_reads` attribute cannot be used on required trait methods + fn read(&self); +} + +#[rustc_trivial_field_reads] //~ERROR the `rustc_trivial_field_reads` attribute cannot be used on traits +trait Whatever1 {} + +#[rustc_trivial_field_reads] //~ERROR the `rustc_trivial_field_reads` attribute cannot be used on macro defs + macro_rules! number { + () => { + 67 + }; + } + +fn main() { + let _ = number!(); +} diff --git a/tests/ui/attributes/trivial-field-reads-invalid-targets.stderr b/tests/ui/attributes/trivial-field-reads-invalid-targets.stderr new file mode 100644 index 0000000000000..c93ffd40427e3 --- /dev/null +++ b/tests/ui/attributes/trivial-field-reads-invalid-targets.stderr @@ -0,0 +1,26 @@ +error: the `rustc_trivial_field_reads` attribute cannot be used on required trait methods + --> $DIR/trivial-field-reads-invalid-targets.rs:7:7 + | +LL | #[rustc_trivial_field_reads] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: the `rustc_trivial_field_reads` attribute can only be applied to functions with a body + +error: the `rustc_trivial_field_reads` attribute cannot be used on traits + --> $DIR/trivial-field-reads-invalid-targets.rs:11:3 + | +LL | #[rustc_trivial_field_reads] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: the `rustc_trivial_field_reads` attribute can only be applied to functions + +error: the `rustc_trivial_field_reads` attribute cannot be used on macro defs + --> $DIR/trivial-field-reads-invalid-targets.rs:14:3 + | +LL | #[rustc_trivial_field_reads] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: the `rustc_trivial_field_reads` attribute can only be applied to functions + +error: aborting due to 3 previous errors + diff --git a/tests/ui/derives/deriving-all-codegen.stdout b/tests/ui/derives/deriving-all-codegen.stdout index d0b387dbc8b25..657269e734e3a 100644 --- a/tests/ui/derives/deriving-all-codegen.stdout +++ b/tests/ui/derives/deriving-all-codegen.stdout @@ -32,6 +32,7 @@ unsafe impl ::core::clone::TrivialClone for Empty { } #[automatically_derived] impl ::core::clone::Clone for Empty { #[inline] + #[rustc_trivial_field_reads] fn clone(&self) -> Empty { *self } } #[automatically_derived] @@ -39,6 +40,7 @@ impl ::core::marker::Copy for Empty { } #[automatically_derived] impl ::core::fmt::Debug for Empty { #[inline] + #[rustc_trivial_field_reads] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { ::core::fmt::Formatter::write_str(f, "Empty") } @@ -95,6 +97,7 @@ unsafe impl ::core::clone::TrivialClone for Point { } #[automatically_derived] impl ::core::clone::Clone for Point { #[inline] + #[rustc_trivial_field_reads] fn clone(&self) -> Point { let _: ::core::clone::AssertParamIsClone; *self @@ -105,6 +108,7 @@ impl ::core::marker::Copy for Point { } #[automatically_derived] impl ::core::fmt::Debug for Point { #[inline] + #[rustc_trivial_field_reads] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { ::core::fmt::Formatter::debug_struct_field2_finish(f, "Point", "x", &self.x, "y", &&self.y) @@ -179,6 +183,7 @@ unsafe impl ::core::clone::TrivialClone for PackedPoint { } #[automatically_derived] impl ::core::clone::Clone for PackedPoint { #[inline] + #[rustc_trivial_field_reads] fn clone(&self) -> PackedPoint { let _: ::core::clone::AssertParamIsClone; *self @@ -189,6 +194,7 @@ impl ::core::marker::Copy for PackedPoint { } #[automatically_derived] impl ::core::fmt::Debug for PackedPoint { #[inline] + #[rustc_trivial_field_reads] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { ::core::fmt::Formatter::debug_struct_field2_finish(f, "PackedPoint", "x", &{ self.x }, "y", &&{ self.y }) @@ -257,6 +263,7 @@ unsafe impl ::core::clone::TrivialClone for TupleSingleField { } #[automatically_derived] impl ::core::clone::Clone for TupleSingleField { #[inline] + #[rustc_trivial_field_reads] fn clone(&self) -> TupleSingleField { let _: ::core::clone::AssertParamIsClone; *self @@ -267,6 +274,7 @@ impl ::core::marker::Copy for TupleSingleField { } #[automatically_derived] impl ::core::fmt::Debug for TupleSingleField { #[inline] + #[rustc_trivial_field_reads] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { ::core::fmt::Formatter::debug_tuple_field1_finish(f, "TupleSingleField", &&self.0) @@ -332,6 +340,7 @@ unsafe impl ::core::clone::TrivialClone for SingleField { } #[automatically_derived] impl ::core::clone::Clone for SingleField { #[inline] + #[rustc_trivial_field_reads] fn clone(&self) -> SingleField { let _: ::core::clone::AssertParamIsClone; *self @@ -342,6 +351,7 @@ impl ::core::marker::Copy for SingleField { } #[automatically_derived] impl ::core::fmt::Debug for SingleField { #[inline] + #[rustc_trivial_field_reads] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { ::core::fmt::Formatter::debug_struct_field1_finish(f, "SingleField", "foo", &&self.foo) @@ -416,6 +426,7 @@ unsafe impl ::core::clone::TrivialClone for Big { } #[automatically_derived] impl ::core::clone::Clone for Big { #[inline] + #[rustc_trivial_field_reads] fn clone(&self) -> Big { let _: ::core::clone::AssertParamIsClone; *self @@ -426,6 +437,7 @@ impl ::core::marker::Copy for Big { } #[automatically_derived] impl ::core::fmt::Debug for Big { #[inline] + #[rustc_trivial_field_reads] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { let names: &'static _ = &["b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8"]; @@ -631,6 +643,7 @@ struct NonCopy(u32); #[automatically_derived] impl ::core::clone::Clone for NonCopy { #[inline] + #[rustc_trivial_field_reads] fn clone(&self) -> NonCopy { NonCopy(::core::clone::Clone::clone(&self.0)) } @@ -643,6 +656,7 @@ struct PackedNonCopy(u32); #[automatically_derived] impl ::core::clone::Clone for PackedNonCopy { #[inline] + #[rustc_trivial_field_reads] fn clone(&self) -> PackedNonCopy { PackedNonCopy(::core::clone::Clone::clone(&{ self.0 })) } @@ -654,6 +668,7 @@ struct ManualCopy(u32); #[automatically_derived] impl ::core::clone::Clone for ManualCopy { #[inline] + #[rustc_trivial_field_reads] fn clone(&self) -> ManualCopy { ManualCopy(::core::clone::Clone::clone(&self.0)) } @@ -667,6 +682,7 @@ struct PackedManualCopy(u32); #[automatically_derived] impl ::core::clone::Clone for PackedManualCopy { #[inline] + #[rustc_trivial_field_reads] fn clone(&self) -> PackedManualCopy { PackedManualCopy(::core::clone::Clone::clone(&{ self.0 })) } @@ -678,6 +694,7 @@ struct Unsized([u32]); #[automatically_derived] impl ::core::fmt::Debug for Unsized { #[inline] + #[rustc_trivial_field_reads] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Unsized", &&self.0) @@ -741,6 +758,7 @@ struct Generic { impl ::core::clone::Clone for Generic where T::A: ::core::clone::Clone { #[inline] + #[rustc_trivial_field_reads] fn clone(&self) -> Generic { Generic { t: ::core::clone::Clone::clone(&self.t), @@ -757,6 +775,7 @@ impl impl ::core::fmt::Debug for Generic where T::A: ::core::fmt::Debug { #[inline] + #[rustc_trivial_field_reads] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { ::core::fmt::Formatter::debug_struct_field3_finish(f, "Generic", "t", &self.t, "ta", &self.ta, "u", &&self.u) @@ -860,6 +879,7 @@ impl where T::A: ::core::clone::Clone + ::core::marker::Copy { #[inline] + #[rustc_trivial_field_reads] fn clone(&self) -> PackedGeneric { PackedGeneric(::core::clone::Clone::clone(&{ self.0 }), ::core::clone::Clone::clone(&{ self.1 }), @@ -877,6 +897,7 @@ impl where T::A: ::core::fmt::Debug + ::core::marker::Copy { #[inline] + #[rustc_trivial_field_reads] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { ::core::fmt::Formatter::debug_tuple_field3_finish(f, "PackedGeneric", &{ self.0 }, &{ self.1 }, &&{ self.2 }) @@ -983,6 +1004,7 @@ unsafe impl ::core::clone::TrivialClone for Enum0 { } #[automatically_derived] impl ::core::clone::Clone for Enum0 { #[inline] + #[rustc_trivial_field_reads] fn clone(&self) -> Enum0 { *self } } #[automatically_derived] @@ -990,6 +1012,7 @@ impl ::core::marker::Copy for Enum0 { } #[automatically_derived] impl ::core::fmt::Debug for Enum0 { #[inline] + #[rustc_trivial_field_reads] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { match *self {} } @@ -1038,6 +1061,7 @@ enum Enum1 { #[automatically_derived] impl ::core::clone::Clone for Enum1 { #[inline] + #[rustc_trivial_field_reads] fn clone(&self) -> Enum1 { match self { Enum1::Single { x: __self_0 } => @@ -1048,6 +1072,7 @@ impl ::core::clone::Clone for Enum1 { #[automatically_derived] impl ::core::fmt::Debug for Enum1 { #[inline] + #[rustc_trivial_field_reads] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { match self { Enum1::Single { x: __self_0 } => @@ -1115,11 +1140,13 @@ enum Fieldless1 { #[automatically_derived] impl ::core::clone::Clone for Fieldless1 { #[inline] + #[rustc_trivial_field_reads] fn clone(&self) -> Fieldless1 { Fieldless1::A } } #[automatically_derived] impl ::core::fmt::Debug for Fieldless1 { #[inline] + #[rustc_trivial_field_reads] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { ::core::fmt::Formatter::write_str(f, "A") } @@ -1178,6 +1205,7 @@ unsafe impl ::core::clone::TrivialClone for Fieldless { } #[automatically_derived] impl ::core::clone::Clone for Fieldless { #[inline] + #[rustc_trivial_field_reads] fn clone(&self) -> Fieldless { *self } } #[automatically_derived] @@ -1185,6 +1213,7 @@ impl ::core::marker::Copy for Fieldless { } #[automatically_derived] impl ::core::fmt::Debug for Fieldless { #[inline] + #[rustc_trivial_field_reads] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { ::core::fmt::Formatter::write_str(f, match self { @@ -1248,6 +1277,7 @@ enum Fieldless0 { A, BBB, CC, } #[automatically_derived] impl ::core::fmt::Debug for Fieldless0 { #[inline] + #[rustc_trivial_field_reads] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { ::core::fmt::Formatter::write_str(f, match self { @@ -1274,6 +1304,7 @@ enum Fieldless10 { #[automatically_derived] impl ::core::fmt::Debug for Fieldless10 { #[inline] + #[rustc_trivial_field_reads] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { static __NAMES: &str = "AAAAABBBBCCDDDDDDDDEFFFFFFFFFFFFFGGGGGGHatsuneIIIIIIIJJJJJJJJJ"; @@ -1304,6 +1335,7 @@ unsafe impl ::core::clone::TrivialClone for Mixed { } #[automatically_derived] impl ::core::clone::Clone for Mixed { #[inline] + #[rustc_trivial_field_reads] fn clone(&self) -> Mixed { let _: ::core::clone::AssertParamIsClone; let _: ::core::clone::AssertParamIsClone>; @@ -1316,6 +1348,7 @@ impl ::core::marker::Copy for Mixed { } #[automatically_derived] impl ::core::fmt::Debug for Mixed { #[inline] + #[rustc_trivial_field_reads] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { match self { Mixed::P => ::core::fmt::Formatter::write_str(f, "P"), @@ -1490,6 +1523,7 @@ enum Fielded { X(u32), Y(bool), Z(Option), } #[automatically_derived] impl ::core::clone::Clone for Fielded { #[inline] + #[rustc_trivial_field_reads] fn clone(&self) -> Fielded { match self { Fielded::X(__self_0) => @@ -1504,6 +1538,7 @@ impl ::core::clone::Clone for Fielded { #[automatically_derived] impl ::core::fmt::Debug for Fielded { #[inline] + #[rustc_trivial_field_reads] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { match self { Fielded::X(__self_0) => @@ -1598,6 +1633,7 @@ enum EnumGeneric { One(T), Two(U), } impl ::core::clone::Clone for EnumGeneric { #[inline] + #[rustc_trivial_field_reads] fn clone(&self) -> EnumGeneric { match self { EnumGeneric::One(__self_0) => @@ -1615,6 +1651,7 @@ impl ::core::marker::Copy impl ::core::fmt::Debug for EnumGeneric { #[inline] + #[rustc_trivial_field_reads] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { match self { EnumGeneric::One(__self_0) => @@ -1749,6 +1786,7 @@ unsafe impl ::core::clone::TrivialClone for Union { } #[automatically_derived] impl ::core::clone::Clone for Union { #[inline] + #[rustc_trivial_field_reads] fn clone(&self) -> Union { let _: ::core::clone::AssertParamIsCopy; *self @@ -1766,6 +1804,7 @@ unsafe impl ::core::clone::TrivialClone for FooCopyClone { } #[automatically_derived] impl ::core::clone::Clone for FooCopyClone { #[inline] + #[rustc_trivial_field_reads] fn clone(&self) -> FooCopyClone { let _: ::core::clone::AssertParamIsClone; *self @@ -1779,6 +1818,7 @@ unsafe impl ::core::clone::TrivialClone for FooCloneCopy { } #[automatically_derived] impl ::core::clone::Clone for FooCloneCopy { #[inline] + #[rustc_trivial_field_reads] fn clone(&self) -> FooCloneCopy { let _: ::core::clone::AssertParamIsClone; *self @@ -1794,6 +1834,7 @@ unsafe impl ::core::clone::TrivialClone for FooCopyAndClone { } #[automatically_derived] impl ::core::clone::Clone for FooCopyAndClone { #[inline] + #[rustc_trivial_field_reads] fn clone(&self) -> FooCopyAndClone { let _: ::core::clone::AssertParamIsClone; *self @@ -1811,6 +1852,7 @@ impl ::core::marker::Copy for FooCloneAndCopy { } #[automatically_derived] impl ::core::clone::Clone for FooCloneAndCopy { #[inline] + #[rustc_trivial_field_reads] fn clone(&self) -> FooCloneAndCopy { FooCloneAndCopy(::core::clone::Clone::clone(&self.0)) } diff --git a/tests/ui/lint/dead-code/trivial-field-reads-valid-targets.rs b/tests/ui/lint/dead-code/trivial-field-reads-valid-targets.rs new file mode 100644 index 0000000000000..c97336ed12c23 --- /dev/null +++ b/tests/ui/lint/dead-code/trivial-field-reads-valid-targets.rs @@ -0,0 +1,123 @@ +//! Checks that `#[rustc_trivial_field_reads]` on the allowed targets +//! (issue #160621) + +#![feature(rustc_attrs)] +#![deny(dead_code)] + +trait Access { + fn get_a(&self) -> u32; + fn get_b(&self) -> u32; +} + +struct S { + a: u32, //~ ERROR field `a` is never read + b: u32 +} + +impl Access for S { + #[rustc_trivial_field_reads] + fn get_a(&self) -> u32 { + self.a + } + + fn get_b(&self) -> u32 { + self.b + } +} + +struct T { + a: u32, + b: u32 +} + +impl Access for T { + fn get_a(&self) -> u32 { + self.a + } + + fn get_b(&self) -> u32 { + self.b + } +} + +struct Square { + width: u32, //~ ERROR field `width` is never read + height: u32 +} + +impl Square { + #[rustc_trivial_field_reads] + fn width(&self) -> u32 { + self.width + } + + fn height(&self) -> u32 { + self.height + } +} + +struct U { + a: u32, //~ ERROR field `a` is never read + b: u32 +} + +#[rustc_trivial_field_reads] +fn foo(u: &U) -> u32 { + u.a +} + +fn bar(u: &U) -> u32 { + u.b +} + +struct Whatever { + a: u32, //~ ERROR field `a` is never read + b: u32, +} + +trait ReadWhatever { + #[rustc_trivial_field_reads] + fn read_a(&self, value: &Whatever) -> u32 { + value.a + } + + fn read_b(&self, value: &Whatever) -> u32 { + value.b + } +} + +struct Reader; + +impl ReadWhatever for Reader {} + +fn main() { + let s = S { + a: 0, + b: 0 + }; + + let _ = s.get_a(); + let _ = s.get_b(); + + let t = T { + a: 0, + b: 0 + }; + + let _ = t.get_a(); + let _ = t.get_b(); + + let square = Square { width: 0, height: 0 }; + let _ = square.width(); + let _ = square.height(); + + let u = U { a: 0, b:0 }; + let _ = foo(&u); + let _ = bar(&u); + + let whatever = Whatever { a: 0, b: 0 }; + let reader = Reader; + + let _ = reader.read_a(&whatever); + let _ = reader.read_b(&whatever); +} diff --git a/tests/ui/lint/dead-code/trivial-field-reads-valid-targets.stderr b/tests/ui/lint/dead-code/trivial-field-reads-valid-targets.stderr new file mode 100644 index 0000000000000..b5b86b70e46f1 --- /dev/null +++ b/tests/ui/lint/dead-code/trivial-field-reads-valid-targets.stderr @@ -0,0 +1,41 @@ +error: field `a` is never read + --> $DIR/trivial-field-reads-valid-targets.rs:13:5 + | +LL | struct S { + | - field in this struct +LL | a: u32, + | ^ + | + = note: `S` has a derived impl for the trait `Access`, but this is intentionally ignored during dead code analysis +note: the lint level is defined here + --> $DIR/trivial-field-reads-valid-targets.rs:5:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: field `width` is never read + --> $DIR/trivial-field-reads-valid-targets.rs:44:5 + | +LL | struct Square { + | ------ field in this struct +LL | width: u32, + | ^^^^^ + +error: field `a` is never read + --> $DIR/trivial-field-reads-valid-targets.rs:60:5 + | +LL | struct U { + | - field in this struct +LL | a: u32, + | ^ + +error: field `a` is never read + --> $DIR/trivial-field-reads-valid-targets.rs:74:5 + | +LL | struct Whatever { + | -------- field in this struct +LL | a: u32, + | ^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/stats/macro-stats.stderr b/tests/ui/stats/macro-stats.stderr index c70895067eb5f..b940734acd3f0 100644 --- a/tests/ui/stats/macro-stats.stderr +++ b/tests/ui/stats/macro-stats.stderr @@ -2,13 +2,13 @@ macro-stats ==================================================================== macro-stats MACRO EXPANSION STATS: macro_stats macro-stats Macro Name Uses Lines Avg Lines Bytes Avg Bytes macro-stats ----------------------------------------------------------------------------------- -macro-stats #[derive(Clone)] 8 67 8.4 1_879 234.9 +macro-stats #[derive(Clone)] 8 75 9.4 2_143 267.9 macro-stats #[derive(Hash)] 2 17 8.5 565 282.5 macro-stats q! 1 26 26.0 519 519.0 macro-stats #[derive(Ord)] 1 15 15.0 503 503.0 macro-stats #[derive(Default)] 2 16 8.0 403 201.5 macro-stats #[derive(Eq)] 1 11 11.0 312 312.0 -macro-stats #[derive(Debug)] 1 8 8.0 277 277.0 +macro-stats #[derive(Debug)] 1 9 9.0 310 310.0 macro-stats #[derive(PartialEq)] 1 9 9.0 267 267.0 macro-stats #[derive(PartialOrd)] 1 8 8.0 254 254.0 macro-stats #[derive(Copy)] 1 2 2.0 61 61.0 diff --git a/tests/ui/traits/const-traits/auxiliary/minicore.rs b/tests/ui/traits/const-traits/auxiliary/minicore.rs index e1d1135e6d4ec..a357a727ef9b1 100644 --- a/tests/ui/traits/const-traits/auxiliary/minicore.rs +++ b/tests/ui/traits/const-traits/auxiliary/minicore.rs @@ -445,7 +445,6 @@ impl Deref for Ref<'_, T> { } #[lang = "clone"] -#[rustc_trivial_field_reads] pub const trait Clone: Sized { fn clone(&self) -> Self; fn clone_from(&mut self, source: &Self)