Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 58bbade

Browse files
authoredJun 25, 2024
Rollup merge of rust-lang#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 rust-lang#98871
2 parents c290e9d + 6997b68 commit 58bbade

File tree

7 files changed

+78
-2
lines changed

7 files changed

+78
-2
lines changed
 

‎compiler/rustc_passes/src/dead.rs

+25
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,31 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
399399
return false;
400400
}
401401

402+
// don't ignore impls for Enums and pub Structs whose methods don't have self receiver,
403+
// cause external crate may call such methods to construct values of these types
404+
if let Some(local_impl_of) = impl_of.as_local()
405+
&& let Some(local_def_id) = def_id.as_local()
406+
&& let Some(fn_sig) =
407+
self.tcx.hir().fn_sig_by_hir_id(self.tcx.local_def_id_to_hir_id(local_def_id))
408+
&& matches!(fn_sig.decl.implicit_self, hir::ImplicitSelfKind::None)
409+
&& let TyKind::Path(hir::QPath::Resolved(_, path)) =
410+
self.tcx.hir().expect_item(local_impl_of).expect_impl().self_ty.kind
411+
&& let Res::Def(def_kind, did) = path.res
412+
{
413+
match def_kind {
414+
// for example, #[derive(Default)] pub struct T(i32);
415+
// external crate can call T::default() to construct T,
416+
// so that don't ignore impl Default for pub Enum and Structs
417+
DefKind::Struct | DefKind::Union if self.tcx.visibility(did).is_public() => {
418+
return false;
419+
}
420+
// don't ignore impl Default for Enums,
421+
// cause we don't know which variant is constructed
422+
DefKind::Enum => return false,
423+
_ => (),
424+
};
425+
}
426+
402427
if let Some(trait_of) = self.tcx.trait_id_of_impl(impl_of)
403428
&& self.tcx.has_attr(trait_of, sym::rustc_trivial_field_reads)
404429
{

‎library/alloc/src/sync/tests.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,7 @@ fn show_arc() {
396396

397397
// Make sure deriving works with Arc<T>
398398
#[derive(Eq, Ord, PartialEq, PartialOrd, Clone, Debug, Default)]
399-
struct Foo {
399+
struct _Foo {
400400
inner: Arc<i32>,
401401
}
402402

‎library/core/src/default.rs

+1
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ use crate::ascii::Char as AsciiChar;
103103
/// ```
104104
#[cfg_attr(not(test), rustc_diagnostic_item = "Default")]
105105
#[stable(feature = "rust1", since = "1.0.0")]
106+
#[cfg_attr(not(bootstrap), rustc_trivial_field_reads)]
106107
pub trait Default: Sized {
107108
/// Returns the "default value" for a type.
108109
///

‎tests/ui/deriving/deriving-default-enum.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,6 @@ enum MyOption<T> {
2222
}
2323

2424
fn main() {
25-
assert_eq!(Foo::default(), Foo::Alpha);
25+
assert!(matches!(Foo::default(), Foo::Alpha));
2626
assert!(matches!(MyOption::<NotDefault>::default(), MyOption::None));
2727
}

‎tests/ui/issues/issue-68696-catch-during-unwind.rs

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
use std::panic::catch_unwind;
99

10+
#[allow(dead_code)]
1011
#[derive(Default)]
1112
struct Guard;
1213

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#![deny(dead_code)]
2+
3+
#[derive(Default)]
4+
struct T; //~ ERROR struct `T` is never constructed
5+
6+
#[derive(Default)]
7+
struct Used;
8+
9+
#[derive(Default)]
10+
enum E {
11+
#[default]
12+
A,
13+
B, //~ ERROR variant `B` is never constructed
14+
}
15+
16+
// external crate can call T2::default() to construct T2,
17+
// so that no warnings for pub adts
18+
#[derive(Default)]
19+
pub struct T2 {
20+
_unread: i32,
21+
}
22+
23+
fn main() {
24+
let _x: Used = Default::default();
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
error: struct `T` is never constructed
2+
--> $DIR/unused-struct-derive-default.rs:4:8
3+
|
4+
LL | struct T;
5+
| ^
6+
|
7+
= note: `T` has a derived impl for the trait `Default`, but this is intentionally ignored during dead code analysis
8+
note: the lint level is defined here
9+
--> $DIR/unused-struct-derive-default.rs:1:9
10+
|
11+
LL | #![deny(dead_code)]
12+
| ^^^^^^^^^
13+
14+
error: variant `B` is never constructed
15+
--> $DIR/unused-struct-derive-default.rs:13:5
16+
|
17+
LL | enum E {
18+
| - variant in this enum
19+
...
20+
LL | B,
21+
| ^
22+
23+
error: aborting due to 2 previous errors
24+

0 commit comments

Comments
 (0)
Failed to load comments.