Skip to content

Commit 2059132

Browse files
committed
Auto merge of rust-lang#128606 - compiler-errors:revert-dead-code-changes-beta, r=cuviper
Revert recent changes to dead code analysis (beta flavor) This PR cherry-picks the subset of rust-lang#128404 which actually applies to beta, namely: * 31fe962 Rollup merge of rust-lang#127107 - mu001999-contrib:dead/enhance-2, r=pnkfelix * 2724aea Rollup merge of rust-lang#126618 - mu001999-contrib:dead/enhance, r=pnkfelix * 977c5fd Rollup merge of rust-lang#126315 - mu001999-contrib:fix/126289, r=petrochenkov * 13314df Rollup merge of rust-lang#125572 - mu001999-contrib:dead/enhance, r=pnkfelix And then re-blesses tests. I opted to do a manual backport of that PR since preparing the revert correctly was quite a hassle. r? `@cuviper` (or anyone on release)
2 parents 4b55199 + eeaf3ce commit 2059132

File tree

60 files changed

+167
-531
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+167
-531
lines changed

compiler/rustc_passes/src/dead.rs

+63-121
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use rustc_hir::{Node, PatKind, TyKind};
1515
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
1616
use rustc_middle::middle::privacy::Level;
1717
use rustc_middle::query::Providers;
18-
use rustc_middle::ty::{self, AssocItemContainer, TyCtxt};
18+
use rustc_middle::ty::{self, TyCtxt};
1919
use rustc_middle::{bug, span_bug};
2020
use rustc_session::lint;
2121
use rustc_session::lint::builtin::DEAD_CODE;
@@ -43,63 +43,16 @@ fn should_explore(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
4343
)
4444
}
4545

46-
struct Publicness {
47-
ty_is_public: bool,
48-
ty_and_all_fields_are_public: bool,
49-
}
50-
51-
impl Publicness {
52-
fn new(ty_is_public: bool, ty_and_all_fields_are_public: bool) -> Self {
53-
Self { ty_is_public, ty_and_all_fields_are_public }
54-
}
55-
}
56-
57-
fn struct_all_fields_are_public(tcx: TyCtxt<'_>, id: DefId) -> bool {
58-
// treat PhantomData and positional ZST as public,
59-
// we don't want to lint types which only have them,
60-
// cause it's a common way to use such types to check things like well-formedness
61-
tcx.adt_def(id).all_fields().all(|field| {
62-
let field_type = tcx.type_of(field.did).instantiate_identity();
63-
if field_type.is_phantom_data() {
64-
return true;
65-
}
66-
let is_positional = field.name.as_str().starts_with(|c: char| c.is_ascii_digit());
67-
if is_positional
68-
&& tcx
69-
.layout_of(tcx.param_env(field.did).and(field_type))
70-
.map_or(true, |layout| layout.is_zst())
71-
{
72-
return true;
73-
}
74-
field.vis.is_public()
75-
})
76-
}
77-
78-
/// check struct and its fields are public or not,
79-
/// for enum and union, just check they are public,
80-
/// and doesn't solve types like &T for now, just skip them
81-
fn ty_ref_to_pub_struct(tcx: TyCtxt<'_>, ty: &hir::Ty<'_>) -> Publicness {
46+
fn ty_ref_to_pub_struct(tcx: TyCtxt<'_>, ty: &hir::Ty<'_>) -> bool {
8247
if let TyKind::Path(hir::QPath::Resolved(_, path)) = ty.kind
8348
&& let Res::Def(def_kind, def_id) = path.res
8449
&& def_id.is_local()
50+
&& matches!(def_kind, DefKind::Struct | DefKind::Enum | DefKind::Union)
8551
{
86-
return match def_kind {
87-
DefKind::Enum | DefKind::Union => {
88-
let ty_is_public = tcx.visibility(def_id).is_public();
89-
Publicness::new(ty_is_public, ty_is_public)
90-
}
91-
DefKind::Struct => {
92-
let ty_is_public = tcx.visibility(def_id).is_public();
93-
Publicness::new(
94-
ty_is_public,
95-
ty_is_public && struct_all_fields_are_public(tcx, def_id),
96-
)
97-
}
98-
_ => Publicness::new(true, true),
99-
};
52+
tcx.visibility(def_id).is_public()
53+
} else {
54+
true
10055
}
101-
102-
Publicness::new(true, true)
10356
}
10457

10558
/// Determine if a work from the worklist is coming from a `#[allow]`
@@ -155,10 +108,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
155108

156109
fn handle_res(&mut self, res: Res) {
157110
match res {
158-
Res::Def(
159-
DefKind::Const | DefKind::AssocConst | DefKind::AssocTy | DefKind::TyAlias,
160-
def_id,
161-
) => {
111+
Res::Def(DefKind::Const | DefKind::AssocConst | DefKind::TyAlias, def_id) => {
162112
self.check_def_id(def_id);
163113
}
164114
_ if self.in_pat => {}
@@ -277,10 +227,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
277227
pats: &[hir::PatField<'_>],
278228
) {
279229
let variant = match self.typeck_results().node_type(lhs.hir_id).kind() {
280-
ty::Adt(adt, _) => {
281-
self.check_def_id(adt.did());
282-
adt.variant_of_res(res)
283-
}
230+
ty::Adt(adt, _) => adt.variant_of_res(res),
284231
_ => span_bug!(lhs.span, "non-ADT in struct pattern"),
285232
};
286233
for pat in pats {
@@ -300,10 +247,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
300247
dotdot: hir::DotDotPos,
301248
) {
302249
let variant = match self.typeck_results().node_type(lhs.hir_id).kind() {
303-
ty::Adt(adt, _) => {
304-
self.check_def_id(adt.did());
305-
adt.variant_of_res(res)
306-
}
250+
ty::Adt(adt, _) => adt.variant_of_res(res),
307251
_ => {
308252
self.tcx.dcx().span_delayed_bug(lhs.span, "non-ADT in tuple struct pattern");
309253
return;
@@ -408,6 +352,31 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
408352
return false;
409353
}
410354

355+
// don't ignore impls for Enums and pub Structs whose methods don't have self receiver,
356+
// cause external crate may call such methods to construct values of these types
357+
if let Some(local_impl_of) = impl_of.as_local()
358+
&& let Some(local_def_id) = def_id.as_local()
359+
&& let Some(fn_sig) =
360+
self.tcx.hir().fn_sig_by_hir_id(self.tcx.local_def_id_to_hir_id(local_def_id))
361+
&& matches!(fn_sig.decl.implicit_self, hir::ImplicitSelfKind::None)
362+
&& let TyKind::Path(hir::QPath::Resolved(_, path)) =
363+
self.tcx.hir().expect_item(local_impl_of).expect_impl().self_ty.kind
364+
&& let Res::Def(def_kind, did) = path.res
365+
{
366+
match def_kind {
367+
// for example, #[derive(Default)] pub struct T(i32);
368+
// external crate can call T::default() to construct T,
369+
// so that don't ignore impl Default for pub Enum and Structs
370+
DefKind::Struct | DefKind::Union if self.tcx.visibility(did).is_public() => {
371+
return false;
372+
}
373+
// don't ignore impl Default for Enums,
374+
// cause we don't know which variant is constructed
375+
DefKind::Enum => return false,
376+
_ => (),
377+
};
378+
}
379+
411380
if let Some(trait_of) = self.tcx.trait_id_of_impl(impl_of)
412381
&& self.tcx.has_attr(trait_of, sym::rustc_trivial_field_reads)
413382
{
@@ -450,7 +419,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
450419
intravisit::walk_item(self, item)
451420
}
452421
hir::ItemKind::ForeignMod { .. } => {}
453-
hir::ItemKind::Trait(_, _, _, _, trait_item_refs) => {
422+
hir::ItemKind::Trait(..) => {
454423
for impl_def_id in self.tcx.all_impls(item.owner_id.to_def_id()) {
455424
if let Some(local_def_id) = impl_def_id.as_local()
456425
&& let ItemKind::Impl(impl_ref) =
@@ -463,12 +432,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
463432
intravisit::walk_path(self, impl_ref.of_trait.unwrap().path);
464433
}
465434
}
466-
// mark assoc ty live if the trait is live
467-
for trait_item in trait_item_refs {
468-
if let hir::AssocItemKind::Type = trait_item.kind {
469-
self.check_def_id(trait_item.id.owner_id.to_def_id());
470-
}
471-
}
435+
472436
intravisit::walk_item(self, item)
473437
}
474438
_ => intravisit::walk_item(self, item),
@@ -485,12 +449,11 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
485449
&& let ItemKind::Impl(impl_ref) =
486450
self.tcx.hir().expect_item(local_impl_id).kind
487451
{
488-
if !ty_ref_to_pub_struct(self.tcx, impl_ref.self_ty)
489-
.ty_and_all_fields_are_public
452+
if !matches!(trait_item.kind, hir::TraitItemKind::Type(..))
453+
&& !ty_ref_to_pub_struct(self.tcx, impl_ref.self_ty)
490454
{
491-
// skip impl-items of non pure pub ty,
492-
// cause we don't know the ty is constructed or not,
493-
// check these later in `solve_rest_impl_items`
455+
// skip methods of private ty,
456+
// they would be solved in `solve_rest_impl_items`
494457
continue;
495458
}
496459

@@ -571,21 +534,22 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
571534
&& let Some(local_def_id) = def_id.as_local()
572535
&& matches!(def_kind, DefKind::Struct | DefKind::Enum | DefKind::Union)
573536
{
537+
if self.tcx.visibility(impl_item_id).is_public() {
538+
// for the public method, we don't know the trait item is used or not,
539+
// so we mark the method live if the self is used
540+
return self.live_symbols.contains(&local_def_id);
541+
}
542+
574543
if let Some(trait_item_id) = self.tcx.associated_item(impl_item_id).trait_item_def_id
575544
&& let Some(local_id) = trait_item_id.as_local()
576545
{
577-
// for the local impl item, we can know the trait item is used or not,
546+
// for the private method, we can know the trait item is used or not,
578547
// so we mark the method live if the self is used and the trait item is used
579-
self.live_symbols.contains(&local_id) && self.live_symbols.contains(&local_def_id)
580-
} else {
581-
// for the foreign method and inherent pub method,
582-
// we don't know the trait item or the method is used or not,
583-
// so we mark the method live if the self is used
584-
self.live_symbols.contains(&local_def_id)
548+
return self.live_symbols.contains(&local_id)
549+
&& self.live_symbols.contains(&local_def_id);
585550
}
586-
} else {
587-
false
588551
}
552+
false
589553
}
590554
}
591555

@@ -671,9 +635,6 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
671635
self.handle_field_pattern_match(pat, res, fields);
672636
}
673637
PatKind::Path(ref qpath) => {
674-
if let ty::Adt(adt, _) = self.typeck_results().node_type(pat.hir_id).kind() {
675-
self.check_def_id(adt.did());
676-
}
677638
let res = self.typeck_results().qpath_res(qpath, pat.hir_id);
678639
self.handle_res(res);
679640
}
@@ -810,9 +771,7 @@ fn check_item<'tcx>(
810771
.iter()
811772
.filter_map(|def_id| def_id.as_local());
812773

813-
let self_ty = tcx.hir().item(id).expect_impl().self_ty;
814-
let Publicness { ty_is_public, ty_and_all_fields_are_public } =
815-
ty_ref_to_pub_struct(tcx, self_ty);
774+
let ty_is_pub = ty_ref_to_pub_struct(tcx, tcx.hir().item(id).expect_impl().self_ty);
816775

817776
// And we access the Map here to get HirId from LocalDefId
818777
for local_def_id in local_def_ids {
@@ -828,19 +787,18 @@ fn check_item<'tcx>(
828787
// for trait impl blocks,
829788
// mark the method live if the self_ty is public,
830789
// or the method is public and may construct self
831-
if tcx.visibility(local_def_id).is_public()
832-
&& (ty_and_all_fields_are_public || (ty_is_public && may_construct_self))
790+
if of_trait
791+
&& (!matches!(tcx.def_kind(local_def_id), DefKind::AssocFn)
792+
|| tcx.visibility(local_def_id).is_public()
793+
&& (ty_is_pub || may_construct_self))
833794
{
834-
// if the impl item is public,
835-
// and the ty may be constructed or can be constructed in foreign crates,
836-
// mark the impl item live
837795
worklist.push((local_def_id, ComesFromAllowExpect::No));
838796
} else if let Some(comes_from_allow) =
839797
has_allow_dead_code_or_lang_attr(tcx, local_def_id)
840798
{
841799
worklist.push((local_def_id, comes_from_allow));
842-
} else if of_trait || tcx.visibility(local_def_id).is_public() && ty_is_public {
843-
// private impl items of traits || public impl items not constructs self
800+
} else if of_trait {
801+
// private method || public method not constructs self
844802
unsolved_impl_items.push((id, local_def_id));
845803
}
846804
}
@@ -866,13 +824,10 @@ fn check_trait_item(
866824
worklist: &mut Vec<(LocalDefId, ComesFromAllowExpect)>,
867825
id: hir::TraitItemId,
868826
) {
869-
use hir::TraitItemKind::{Const, Fn, Type};
870-
if matches!(
871-
tcx.def_kind(id.owner_id),
872-
DefKind::AssocConst | DefKind::AssocTy | DefKind::AssocFn
873-
) {
827+
use hir::TraitItemKind::{Const, Fn};
828+
if matches!(tcx.def_kind(id.owner_id), DefKind::AssocConst | DefKind::AssocFn) {
874829
let trait_item = tcx.hir().trait_item(id);
875-
if matches!(trait_item.kind, Const(_, Some(_)) | Type(_, Some(_)) | Fn(..))
830+
if matches!(trait_item.kind, Const(_, Some(_)) | Fn(..))
876831
&& let Some(comes_from_allow) =
877832
has_allow_dead_code_or_lang_attr(tcx, trait_item.owner_id.def_id)
878833
{
@@ -910,14 +865,6 @@ fn create_and_seed_worklist(
910865
effective_vis
911866
.is_public_at_level(Level::Reachable)
912867
.then_some(id)
913-
.filter(|&id|
914-
// checks impls, impl-items and pub structs with all public fields later
915-
match tcx.def_kind(id) {
916-
DefKind::Impl { .. } => false,
917-
DefKind::AssocConst | DefKind::AssocTy | DefKind::AssocFn => !matches!(tcx.associated_item(id).container, AssocItemContainer::ImplContainer),
918-
DefKind::Struct => struct_all_fields_are_public(tcx, id.to_def_id()) || has_allow_dead_code_or_lang_attr(tcx, id).is_some(),
919-
_ => true
920-
})
921868
.map(|id| (id, ComesFromAllowExpect::No))
922869
})
923870
// Seed entry point
@@ -1201,7 +1148,6 @@ impl<'tcx> DeadVisitor<'tcx> {
12011148
}
12021149
match self.tcx.def_kind(def_id) {
12031150
DefKind::AssocConst
1204-
| DefKind::AssocTy
12051151
| DefKind::AssocFn
12061152
| DefKind::Fn
12071153
| DefKind::Static { .. }
@@ -1243,14 +1189,10 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) {
12431189
|| (def_kind == DefKind::Trait && live_symbols.contains(&item.owner_id.def_id))
12441190
{
12451191
for &def_id in tcx.associated_item_def_ids(item.owner_id.def_id) {
1246-
// We have diagnosed unused assocs in traits
1192+
// We have diagnosed unused methods in traits
12471193
if matches!(def_kind, DefKind::Impl { of_trait: true })
1248-
&& matches!(tcx.def_kind(def_id), DefKind::AssocConst | DefKind::AssocTy | DefKind::AssocFn)
1249-
// skip unused public inherent methods,
1250-
// cause we have diagnosed unconstructed struct
1251-
|| matches!(def_kind, DefKind::Impl { of_trait: false })
1252-
&& tcx.visibility(def_id).is_public()
1253-
&& ty_ref_to_pub_struct(tcx, tcx.hir().item(item).expect_impl().self_ty).ty_is_public
1194+
&& tcx.def_kind(def_id) == DefKind::AssocFn
1195+
|| def_kind == DefKind::Trait && tcx.def_kind(def_id) != DefKind::AssocFn
12541196
{
12551197
continue;
12561198
}

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/codegen-units/item-collection/generic-impl.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,16 @@ impl<T> Struct<T> {
2222
}
2323
}
2424

25-
pub struct _LifeTimeOnly<'a> {
25+
pub struct LifeTimeOnly<'a> {
2626
_a: &'a u32,
2727
}
2828

29-
impl<'a> _LifeTimeOnly<'a> {
30-
//~ MONO_ITEM fn _LifeTimeOnly::<'_>::foo
29+
impl<'a> LifeTimeOnly<'a> {
30+
//~ MONO_ITEM fn LifeTimeOnly::<'_>::foo
3131
pub fn foo(&self) {}
32-
//~ MONO_ITEM fn _LifeTimeOnly::<'_>::bar
32+
//~ MONO_ITEM fn LifeTimeOnly::<'_>::bar
3333
pub fn bar(&'a self) {}
34-
//~ MONO_ITEM fn _LifeTimeOnly::<'_>::baz
34+
//~ MONO_ITEM fn LifeTimeOnly::<'_>::baz
3535
pub fn baz<'b>(&'b self) {}
3636

3737
pub fn non_instantiated<T>(&self) {}

0 commit comments

Comments
 (0)