Auto merge of #121752 - mu001999:dead_code/improve, r=pnkfelix · rust-lang/rust@c69fda7 (original) (raw)
`@@ -15,7 +15,7 @@ use rustc_hir::{Node, PatKind, TyKind};
`
15
15
`use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
`
16
16
`use rustc_middle::middle:🔏:Level;
`
17
17
`use rustc_middle::query::Providers;
`
18
``
`-
use rustc_middle::ty::{self, TyCtxt, Visibility};
`
``
18
`+
use rustc_middle::ty::{self, TyCtxt};
`
19
19
`use rustc_session::lint;
`
20
20
`use rustc_session::lint::builtin::DEAD_CODE;
`
21
21
`use rustc_span::symbol::{sym, Symbol};
`
`@@ -45,6 +45,18 @@ fn should_explore(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
`
45
45
`)
`
46
46
`}
`
47
47
``
``
48
`+
fn ty_ref_to_pub_struct(tcx: TyCtxt<'_>, ty: &hir::Ty<'_>) -> bool {
`
``
49
`+
if let TyKind::Path(hir::QPath::Resolved(_, path)) = ty.kind
`
``
50
`+
&& let Res::Def(def_kind, def_id) = path.res
`
``
51
`+
&& def_id.is_local()
`
``
52
`+
&& matches!(def_kind, DefKind::Struct | DefKind::Enum | DefKind::Union)
`
``
53
`+
{
`
``
54
`+
tcx.visibility(def_id).is_public()
`
``
55
`+
} else {
`
``
56
`+
true
`
``
57
`+
}
`
``
58
`+
}
`
``
59
+
48
60
`` /// Determine if a work from the worklist is coming from the a #[allow]
``
49
61
`` /// or a #[expect] of dead_code
``
50
62
`#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
`
`@@ -415,6 +427,13 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
`
415
427
` && let ItemKind::Impl(impl_ref) =
`
416
428
`self.tcx.hir().expect_item(local_impl_id).kind
`
417
429
`{
`
``
430
`+
if self.tcx.visibility(trait_id).is_public()
`
``
431
`+
&& matches!(trait_item.kind, hir::TraitItemKind::Fn(..))
`
``
432
`+
&& !ty_ref_to_pub_struct(self.tcx, impl_ref.self_ty)
`
``
433
`+
{
`
``
434
`+
continue;
`
``
435
`+
}
`
``
436
+
418
437
`// mark self_ty live
`
419
438
` intravisit::walk_ty(self, impl_ref.self_ty);
`
420
439
`if let Some(&impl_item_id) =
`
`@@ -465,6 +484,36 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
`
465
484
`}
`
466
485
`}
`
467
486
`}
`
``
487
+
``
488
`+
fn solve_rest_impl_items(&mut self, mut unsolved_impl_items: Vec<(hir::ItemId, LocalDefId)>) {
`
``
489
`+
let mut ready;
`
``
490
`+
(ready, unsolved_impl_items) = unsolved_impl_items
`
``
491
`+
.into_iter()
`
``
492
`+
.partition(|&(impl_id, _)| self.impl_item_with_used_self(impl_id));
`
``
493
+
``
494
`+
while !ready.is_empty() {
`
``
495
`+
self.worklist =
`
``
496
`+
ready.into_iter().map(|(_, id)| (id, ComesFromAllowExpect::No)).collect();
`
``
497
`+
self.mark_live_symbols();
`
``
498
+
``
499
`+
(ready, unsolved_impl_items) = unsolved_impl_items
`
``
500
`+
.into_iter()
`
``
501
`+
.partition(|&(impl_id, _)| self.impl_item_with_used_self(impl_id));
`
``
502
`+
}
`
``
503
`+
}
`
``
504
+
``
505
`+
fn impl_item_with_used_self(&mut self, impl_id: hir::ItemId) -> bool {
`
``
506
`+
if let TyKind::Path(hir::QPath::Resolved(_, path)) =
`
``
507
`+
self.tcx.hir().item(impl_id).expect_impl().self_ty.kind
`
``
508
`+
&& let Res::Def(def_kind, def_id) = path.res
`
``
509
`+
&& let Some(local_def_id) = def_id.as_local()
`
``
510
`+
&& matches!(def_kind, DefKind::Struct | DefKind::Enum | DefKind::Union)
`
``
511
`+
{
`
``
512
`+
self.live_symbols.contains(&local_def_id)
`
``
513
`+
} else {
`
``
514
`+
false
`
``
515
`+
}
`
``
516
`+
}
`
468
517
`}
`
469
518
``
470
519
`impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
`
`@@ -652,6 +701,7 @@ fn check_item<'tcx>(
`
652
701
`tcx: TyCtxt<'tcx>,
`
653
702
`worklist: &mut Vec<(LocalDefId, ComesFromAllowExpect)>,
`
654
703
`struct_constructors: &mut LocalDefIdMap,
`
``
704
`+
unsolved_impl_items: &mut Vec<(hir::ItemId, LocalDefId)>,
`
655
705
`id: hir::ItemId,
`
656
706
`) {
`
657
707
`let allow_dead_code = has_allow_dead_code_or_lang_attr(tcx, id.owner_id.def_id);
`
`@@ -683,16 +733,33 @@ fn check_item<'tcx>(
`
683
733
`.iter()
`
684
734
`.filter_map(|def_id| def_id.as_local());
`
685
735
``
``
736
`+
let ty_is_pub = ty_ref_to_pub_struct(tcx, tcx.hir().item(id).expect_impl().self_ty);
`
``
737
+
686
738
`// And we access the Map here to get HirId from LocalDefId
`
687
``
`-
for id in local_def_ids {
`
``
739
`+
for local_def_id in local_def_ids {
`
``
740
`+
// check the function may construct Self
`
``
741
`+
let mut may_construct_self = true;
`
``
742
`+
if let Some(hir_id) = tcx.opt_local_def_id_to_hir_id(local_def_id)
`
``
743
`+
&& let Some(fn_sig) = tcx.hir().fn_sig_by_hir_id(hir_id)
`
``
744
`+
{
`
``
745
`+
may_construct_self =
`
``
746
`+
matches!(fn_sig.decl.implicit_self, hir::ImplicitSelfKind::None);
`
``
747
`+
}
`
``
748
+
688
749
`// for impl trait blocks, mark associate functions live if the trait is public
`
689
750
`if of_trait
`
690
``
`-
&& (!matches!(tcx.def_kind(id), DefKind::AssocFn)
`
691
``
`-
|| tcx.local_visibility(id) == Visibility::Public)
`
``
751
`+
&& (!matches!(tcx.def_kind(local_def_id), DefKind::AssocFn)
`
``
752
`+
|| tcx.visibility(local_def_id).is_public()
`
``
753
`+
&& (ty_is_pub || may_construct_self))
`
692
754
`{
`
693
``
`-
worklist.push((id, ComesFromAllowExpect::No));
`
694
``
`-
} else if let Some(comes_from_allow) = has_allow_dead_code_or_lang_attr(tcx, id) {
`
695
``
`-
worklist.push((id, comes_from_allow));
`
``
755
`+
worklist.push((local_def_id, ComesFromAllowExpect::No));
`
``
756
`+
} else if of_trait && tcx.visibility(local_def_id).is_public() {
`
``
757
`+
// pub method && private ty & methods not construct self
`
``
758
`+
unsolved_impl_items.push((id, local_def_id));
`
``
759
`+
} else if let Some(comes_from_allow) =
`
``
760
`+
has_allow_dead_code_or_lang_attr(tcx, local_def_id)
`
``
761
`+
{
`
``
762
`+
worklist.push((local_def_id, comes_from_allow));
`
696
763
`}
`
697
764
`}
`
698
765
`}
`
`@@ -743,9 +810,14 @@ fn check_foreign_item(
`
743
810
``
744
811
`fn create_and_seed_worklist(
`
745
812
`tcx: TyCtxt<'_>,
`
746
``
`-
) -> (Vec<(LocalDefId, ComesFromAllowExpect)>, LocalDefIdMap) {
`
``
813
`+
) -> (
`
``
814
`+
Vec<(LocalDefId, ComesFromAllowExpect)>,
`
``
815
`+
LocalDefIdMap,
`
``
816
`+
Vec<(hir::ItemId, LocalDefId)>,
`
``
817
`+
) {
`
747
818
`let effective_visibilities = &tcx.effective_visibilities(());
`
748
819
`` // see MarkSymbolVisitor::struct_constructors
``
``
820
`+
let mut unsolved_impl_item = Vec::new();
`
749
821
`let mut struct_constructors = Default::default();
`
750
822
`let mut worklist = effective_visibilities
`
751
823
`.iter()
`
`@@ -764,7 +836,7 @@ fn create_and_seed_worklist(
`
764
836
``
765
837
`let crate_items = tcx.hir_crate_items(());
`
766
838
`for id in crate_items.items() {
`
767
``
`-
check_item(tcx, &mut worklist, &mut struct_constructors, id);
`
``
839
`+
check_item(tcx, &mut worklist, &mut struct_constructors, &mut unsolved_impl_item, id);
`
768
840
`}
`
769
841
``
770
842
`for id in crate_items.trait_items() {
`
`@@ -775,14 +847,14 @@ fn create_and_seed_worklist(
`
775
847
`check_foreign_item(tcx, &mut worklist, id);
`
776
848
`}
`
777
849
``
778
``
`-
(worklist, struct_constructors)
`
``
850
`+
(worklist, struct_constructors, unsolved_impl_item)
`
779
851
`}
`
780
852
``
781
853
`fn live_symbols_and_ignored_derived_traits(
`
782
854
`tcx: TyCtxt<'_>,
`
783
855
`(): (),
`
784
856
`) -> (LocalDefIdSet, LocalDefIdMap<Vec<(DefId, DefId)>>) {
`
785
``
`-
let (worklist, struct_constructors) = create_and_seed_worklist(tcx);
`
``
857
`+
let (worklist, struct_constructors, unsolved_impl_items) = create_and_seed_worklist(tcx);
`
786
858
`let mut symbol_visitor = MarkSymbolVisitor {
`
787
859
` worklist,
`
788
860
` tcx,
`
`@@ -796,6 +868,8 @@ fn live_symbols_and_ignored_derived_traits(
`
796
868
`ignored_derived_traits: Default::default(),
`
797
869
`};
`
798
870
` symbol_visitor.mark_live_symbols();
`
``
871
`+
symbol_visitor.solve_rest_impl_items(unsolved_impl_items);
`
``
872
+
799
873
`(symbol_visitor.live_symbols, symbol_visitor.ignored_derived_traits)
`
800
874
`}
`
801
875
``