Rollup merge of #126302 - mu001999-contrib:ignore/default, r=michaelwoerister
Detect unused structs which derived Default <!-- If this PR is related to an unstable feature or an otherwise tracked effort, please link to the relevant tracking issue here. If you don't know of a related tracking issue or there are none, feel free to ignore this. This PR will get automatically assigned to a reviewer. In case you would like a specific user to review your work, you can assign it to them by using r? <reviewer name> --> Fixes #98871
This commit is contained in:
commit
58bbade921
7 changed files with 78 additions and 2 deletions
|
@ -399,6 +399,31 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// don't ignore impls for Enums and pub Structs whose methods don't have self receiver,
|
||||||
|
// cause external crate may call such methods to construct values of these types
|
||||||
|
if let Some(local_impl_of) = impl_of.as_local()
|
||||||
|
&& let Some(local_def_id) = def_id.as_local()
|
||||||
|
&& let Some(fn_sig) =
|
||||||
|
self.tcx.hir().fn_sig_by_hir_id(self.tcx.local_def_id_to_hir_id(local_def_id))
|
||||||
|
&& matches!(fn_sig.decl.implicit_self, hir::ImplicitSelfKind::None)
|
||||||
|
&& let TyKind::Path(hir::QPath::Resolved(_, path)) =
|
||||||
|
self.tcx.hir().expect_item(local_impl_of).expect_impl().self_ty.kind
|
||||||
|
&& let Res::Def(def_kind, did) = path.res
|
||||||
|
{
|
||||||
|
match def_kind {
|
||||||
|
// for example, #[derive(Default)] pub struct T(i32);
|
||||||
|
// external crate can call T::default() to construct T,
|
||||||
|
// so that don't ignore impl Default for pub Enum and Structs
|
||||||
|
DefKind::Struct | DefKind::Union if self.tcx.visibility(did).is_public() => {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// don't ignore impl Default for Enums,
|
||||||
|
// cause we don't know which variant is constructed
|
||||||
|
DefKind::Enum => return false,
|
||||||
|
_ => (),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(trait_of) = self.tcx.trait_id_of_impl(impl_of)
|
if let Some(trait_of) = self.tcx.trait_id_of_impl(impl_of)
|
||||||
&& self.tcx.has_attr(trait_of, sym::rustc_trivial_field_reads)
|
&& self.tcx.has_attr(trait_of, sym::rustc_trivial_field_reads)
|
||||||
{
|
{
|
||||||
|
|
|
@ -396,7 +396,7 @@ fn show_arc() {
|
||||||
|
|
||||||
// Make sure deriving works with Arc<T>
|
// Make sure deriving works with Arc<T>
|
||||||
#[derive(Eq, Ord, PartialEq, PartialOrd, Clone, Debug, Default)]
|
#[derive(Eq, Ord, PartialEq, PartialOrd, Clone, Debug, Default)]
|
||||||
struct Foo {
|
struct _Foo {
|
||||||
inner: Arc<i32>,
|
inner: Arc<i32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -103,6 +103,7 @@ use crate::ascii::Char as AsciiChar;
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg_attr(not(test), rustc_diagnostic_item = "Default")]
|
#[cfg_attr(not(test), rustc_diagnostic_item = "Default")]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
#[cfg_attr(not(bootstrap), rustc_trivial_field_reads)]
|
||||||
pub trait Default: Sized {
|
pub trait Default: Sized {
|
||||||
/// Returns the "default value" for a type.
|
/// Returns the "default value" for a type.
|
||||||
///
|
///
|
||||||
|
|
|
@ -22,6 +22,6 @@ enum MyOption<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
assert_eq!(Foo::default(), Foo::Alpha);
|
assert!(matches!(Foo::default(), Foo::Alpha));
|
||||||
assert!(matches!(MyOption::<NotDefault>::default(), MyOption::None));
|
assert!(matches!(MyOption::<NotDefault>::default(), MyOption::None));
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
use std::panic::catch_unwind;
|
use std::panic::catch_unwind;
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct Guard;
|
struct Guard;
|
||||||
|
|
||||||
|
|
25
tests/ui/lint/dead-code/unused-struct-derive-default.rs
Normal file
25
tests/ui/lint/dead-code/unused-struct-derive-default.rs
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
#![deny(dead_code)]
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
struct T; //~ ERROR struct `T` is never constructed
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
struct Used;
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
enum E {
|
||||||
|
#[default]
|
||||||
|
A,
|
||||||
|
B, //~ ERROR variant `B` is never constructed
|
||||||
|
}
|
||||||
|
|
||||||
|
// external crate can call T2::default() to construct T2,
|
||||||
|
// so that no warnings for pub adts
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct T2 {
|
||||||
|
_unread: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let _x: Used = Default::default();
|
||||||
|
}
|
24
tests/ui/lint/dead-code/unused-struct-derive-default.stderr
Normal file
24
tests/ui/lint/dead-code/unused-struct-derive-default.stderr
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
error: struct `T` is never constructed
|
||||||
|
--> $DIR/unused-struct-derive-default.rs:4:8
|
||||||
|
|
|
||||||
|
LL | struct T;
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
= note: `T` has a derived impl for the trait `Default`, but this is intentionally ignored during dead code analysis
|
||||||
|
note: the lint level is defined here
|
||||||
|
--> $DIR/unused-struct-derive-default.rs:1:9
|
||||||
|
|
|
||||||
|
LL | #![deny(dead_code)]
|
||||||
|
| ^^^^^^^^^
|
||||||
|
|
||||||
|
error: variant `B` is never constructed
|
||||||
|
--> $DIR/unused-struct-derive-default.rs:13:5
|
||||||
|
|
|
||||||
|
LL | enum E {
|
||||||
|
| - variant in this enum
|
||||||
|
...
|
||||||
|
LL | B,
|
||||||
|
| ^
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue