4
4
// is dead.
5
5
6
6
use std:: mem;
7
+ use std:: ops:: ControlFlow ;
7
8
8
9
use hir:: def_id:: { LocalDefIdMap , LocalDefIdSet } ;
9
10
use rustc_abi:: FieldIdx ;
10
11
use rustc_data_structures:: fx:: FxIndexSet ;
11
- use rustc_errors:: MultiSpan ;
12
+ use rustc_errors:: { ErrorGuaranteed , MultiSpan } ;
12
13
use rustc_hir:: def:: { CtorOf , DefKind , Res } ;
13
14
use rustc_hir:: def_id:: { DefId , LocalDefId , LocalModDefId } ;
14
15
use rustc_hir:: intravisit:: { self , Visitor } ;
@@ -178,12 +179,12 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
178
179
. iter ( )
179
180
. any ( |adj| matches ! ( adj. kind, ty:: adjustment:: Adjust :: Deref ( _) ) )
180
181
{
181
- self . visit_expr ( expr) ;
182
+ let _ = self . visit_expr ( expr) ;
182
183
} else if let hir:: ExprKind :: Field ( base, ..) = expr. kind {
183
184
// Ignore write to field
184
185
self . handle_assign ( base) ;
185
186
} else {
186
- self . visit_expr ( expr) ;
187
+ let _ = self . visit_expr ( expr) ;
187
188
}
188
189
}
189
190
@@ -318,7 +319,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
318
319
}
319
320
}
320
321
321
- fn mark_live_symbols ( & mut self ) {
322
+ fn mark_live_symbols ( & mut self ) -> < MarkSymbolVisitor < ' tcx > as Visitor < ' tcx > > :: Result {
322
323
while let Some ( work) = self . worklist . pop ( ) {
323
324
let ( mut id, comes_from_allow_expect) = work;
324
325
@@ -366,8 +367,13 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
366
367
continue ;
367
368
}
368
369
369
- self . visit_node ( self . tcx . hir_node_by_def_id ( id) ) ;
370
+ let visit_result = self . visit_node ( self . tcx . hir_node_by_def_id ( id) ) ;
371
+ if visit_result. is_break ( ) {
372
+ return visit_result;
373
+ }
370
374
}
375
+
376
+ ControlFlow :: Continue ( ( ) )
371
377
}
372
378
373
379
/// Automatically generated items marked with `rustc_trivial_field_reads`
@@ -395,19 +401,22 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
395
401
false
396
402
}
397
403
398
- fn visit_node ( & mut self , node : Node < ' tcx > ) {
404
+ fn visit_node (
405
+ & mut self ,
406
+ node : Node < ' tcx > ,
407
+ ) -> <MarkSymbolVisitor < ' tcx > as Visitor < ' tcx > >:: Result {
399
408
if let Node :: ImplItem ( hir:: ImplItem { owner_id, .. } ) = node
400
409
&& self . should_ignore_item ( owner_id. to_def_id ( ) )
401
410
{
402
- return ;
411
+ return ControlFlow :: Continue ( ( ) ) ;
403
412
}
404
413
405
414
let unconditionally_treated_fields_as_live =
406
415
self . repr_unconditionally_treats_fields_as_live ;
407
416
let had_repr_simd = self . repr_has_repr_simd ;
408
417
self . repr_unconditionally_treats_fields_as_live = false ;
409
418
self . repr_has_repr_simd = false ;
410
- match node {
419
+ let walk_result = match node {
411
420
Node :: Item ( item) => match item. kind {
412
421
hir:: ItemKind :: Struct ( ..) | hir:: ItemKind :: Union ( ..) => {
413
422
let def = self . tcx . adt_def ( item. owner_id ) ;
@@ -417,7 +426,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
417
426
418
427
intravisit:: walk_item ( self , item)
419
428
}
420
- hir:: ItemKind :: ForeignMod { .. } => { }
429
+ hir:: ItemKind :: ForeignMod { .. } => ControlFlow :: Continue ( ( ) ) ,
421
430
hir:: ItemKind :: Trait ( .., trait_item_refs) => {
422
431
// mark assoc ty live if the trait is live
423
432
for trait_item in trait_item_refs {
@@ -435,7 +444,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
435
444
if let Some ( trait_id) = self . tcx . trait_of_assoc ( trait_item_id) {
436
445
self . check_def_id ( trait_id) ;
437
446
}
438
- intravisit:: walk_trait_item ( self , trait_item) ;
447
+ intravisit:: walk_trait_item ( self , trait_item)
439
448
}
440
449
Node :: ImplItem ( impl_item) => {
441
450
let item = self . tcx . local_parent ( impl_item. owner_id . def_id ) ;
@@ -456,16 +465,16 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
456
465
_ => { }
457
466
}
458
467
}
459
- intravisit:: walk_impl_item ( self , impl_item) ;
460
- }
461
- Node :: ForeignItem ( foreign_item) => {
462
- intravisit:: walk_foreign_item ( self , foreign_item) ;
468
+ intravisit:: walk_impl_item ( self , impl_item)
463
469
}
470
+ Node :: ForeignItem ( foreign_item) => intravisit:: walk_foreign_item ( self , foreign_item) ,
464
471
Node :: OpaqueTy ( opaq) => intravisit:: walk_opaque_ty ( self , opaq) ,
465
- _ => { }
466
- }
472
+ _ => ControlFlow :: Continue ( ( ) ) ,
473
+ } ;
467
474
self . repr_has_repr_simd = had_repr_simd;
468
475
self . repr_unconditionally_treats_fields_as_live = unconditionally_treated_fields_as_live;
476
+
477
+ walk_result
469
478
}
470
479
471
480
fn mark_as_used_if_union ( & mut self , adt : ty:: AdtDef < ' tcx > , fields : & [ hir:: ExprField < ' _ > ] ) {
@@ -520,21 +529,25 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
520
529
}
521
530
522
531
impl < ' tcx > Visitor < ' tcx > for MarkSymbolVisitor < ' tcx > {
523
- fn visit_nested_body ( & mut self , body : hir:: BodyId ) {
532
+ type Result = ControlFlow < ErrorGuaranteed > ;
533
+
534
+ fn visit_nested_body ( & mut self , body : hir:: BodyId ) -> Self :: Result {
524
535
let typeck_results = self . tcx . typeck_body ( body) ;
525
536
526
537
// The result shouldn't be tainted, otherwise it will cause ICE.
527
- if typeck_results. tainted_by_errors . is_some ( ) {
528
- return ;
538
+ if let Some ( guar ) = typeck_results. tainted_by_errors {
539
+ return ControlFlow :: Break ( guar ) ;
529
540
}
530
541
531
542
let old_maybe_typeck_results = self . maybe_typeck_results . replace ( typeck_results) ;
532
543
let body = self . tcx . hir_body ( body) ;
533
- self . visit_body ( body) ;
544
+ let result = self . visit_body ( body) ;
534
545
self . maybe_typeck_results = old_maybe_typeck_results;
546
+
547
+ result
535
548
}
536
549
537
- fn visit_variant_data ( & mut self , def : & ' tcx hir:: VariantData < ' tcx > ) {
550
+ fn visit_variant_data ( & mut self , def : & ' tcx hir:: VariantData < ' tcx > ) -> Self :: Result {
538
551
let tcx = self . tcx ;
539
552
let unconditionally_treat_fields_as_live = self . repr_unconditionally_treats_fields_as_live ;
540
553
let has_repr_simd = self . repr_has_repr_simd ;
@@ -551,10 +564,10 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
551
564
} ) ;
552
565
self . live_symbols . extend ( live_fields) ;
553
566
554
- intravisit:: walk_struct_def ( self , def) ;
567
+ intravisit:: walk_struct_def ( self , def)
555
568
}
556
569
557
- fn visit_expr ( & mut self , expr : & ' tcx hir:: Expr < ' tcx > ) {
570
+ fn visit_expr ( & mut self , expr : & ' tcx hir:: Expr < ' tcx > ) -> Self :: Result {
558
571
match expr. kind {
559
572
hir:: ExprKind :: Path ( ref qpath @ QPath :: TypeRelative ( ..) ) => {
560
573
let res = self . typeck_results ( ) . qpath_res ( qpath, expr. hir_id ) ;
@@ -590,20 +603,22 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
590
603
_ => ( ) ,
591
604
}
592
605
593
- intravisit:: walk_expr ( self , expr) ;
606
+ intravisit:: walk_expr ( self , expr)
594
607
}
595
608
596
- fn visit_arm ( & mut self , arm : & ' tcx hir:: Arm < ' tcx > ) {
609
+ fn visit_arm ( & mut self , arm : & ' tcx hir:: Arm < ' tcx > ) -> Self :: Result {
597
610
// Inside the body, ignore constructions of variants
598
611
// necessary for the pattern to match. Those construction sites
599
612
// can't be reached unless the variant is constructed elsewhere.
600
613
let len = self . ignore_variant_stack . len ( ) ;
601
614
self . ignore_variant_stack . extend ( arm. pat . necessary_variants ( ) ) ;
602
- intravisit:: walk_arm ( self , arm) ;
615
+ let result = intravisit:: walk_arm ( self , arm) ;
603
616
self . ignore_variant_stack . truncate ( len) ;
617
+
618
+ result
604
619
}
605
620
606
- fn visit_pat ( & mut self , pat : & ' tcx hir:: Pat < ' tcx > ) {
621
+ fn visit_pat ( & mut self , pat : & ' tcx hir:: Pat < ' tcx > ) -> Self :: Result {
607
622
self . in_pat = true ;
608
623
match pat. kind {
609
624
PatKind :: Struct ( ref path, fields, _) => {
@@ -617,11 +632,13 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
617
632
_ => ( ) ,
618
633
}
619
634
620
- intravisit:: walk_pat ( self , pat) ;
635
+ let result = intravisit:: walk_pat ( self , pat) ;
621
636
self . in_pat = false ;
637
+
638
+ result
622
639
}
623
640
624
- fn visit_pat_expr ( & mut self , expr : & ' tcx rustc_hir:: PatExpr < ' tcx > ) {
641
+ fn visit_pat_expr ( & mut self , expr : & ' tcx rustc_hir:: PatExpr < ' tcx > ) -> Self :: Result {
625
642
match & expr. kind {
626
643
rustc_hir:: PatExprKind :: Path ( qpath) => {
627
644
// mark the type of variant live when meeting E::V in expr
@@ -634,37 +651,41 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
634
651
}
635
652
_ => { }
636
653
}
637
- intravisit:: walk_pat_expr ( self , expr) ;
654
+ intravisit:: walk_pat_expr ( self , expr)
638
655
}
639
656
640
- fn visit_path ( & mut self , path : & hir:: Path < ' tcx > , _: hir:: HirId ) {
657
+ fn visit_path ( & mut self , path : & hir:: Path < ' tcx > , _: hir:: HirId ) -> Self :: Result {
641
658
self . handle_res ( path. res ) ;
642
- intravisit:: walk_path ( self , path) ;
659
+ intravisit:: walk_path ( self , path)
643
660
}
644
661
645
- fn visit_anon_const ( & mut self , c : & ' tcx hir:: AnonConst ) {
662
+ fn visit_anon_const ( & mut self , c : & ' tcx hir:: AnonConst ) -> Self :: Result {
646
663
// When inline const blocks are used in pattern position, paths
647
664
// referenced by it should be considered as used.
648
665
let in_pat = mem:: replace ( & mut self . in_pat , false ) ;
649
666
650
667
self . live_symbols . insert ( c. def_id ) ;
651
- intravisit:: walk_anon_const ( self , c) ;
668
+ let result = intravisit:: walk_anon_const ( self , c) ;
652
669
653
670
self . in_pat = in_pat;
671
+
672
+ result
654
673
}
655
674
656
- fn visit_inline_const ( & mut self , c : & ' tcx hir:: ConstBlock ) {
675
+ fn visit_inline_const ( & mut self , c : & ' tcx hir:: ConstBlock ) -> Self :: Result {
657
676
// When inline const blocks are used in pattern position, paths
658
677
// referenced by it should be considered as used.
659
678
let in_pat = mem:: replace ( & mut self . in_pat , false ) ;
660
679
661
680
self . live_symbols . insert ( c. def_id ) ;
662
- intravisit:: walk_inline_const ( self , c) ;
681
+ let result = intravisit:: walk_inline_const ( self , c) ;
663
682
664
683
self . in_pat = in_pat;
684
+
685
+ result
665
686
}
666
687
667
- fn visit_trait_ref ( & mut self , t : & ' tcx hir:: TraitRef < ' tcx > ) {
688
+ fn visit_trait_ref ( & mut self , t : & ' tcx hir:: TraitRef < ' tcx > ) -> Self :: Result {
668
689
if let Some ( trait_def_id) = t. path . res . opt_def_id ( )
669
690
&& let Some ( segment) = t. path . segments . last ( )
670
691
&& let Some ( args) = segment. args
@@ -686,7 +707,7 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
686
707
}
687
708
}
688
709
689
- intravisit:: walk_trait_ref ( self , t) ;
710
+ intravisit:: walk_trait_ref ( self , t)
690
711
}
691
712
}
692
713
@@ -833,7 +854,7 @@ fn create_and_seed_worklist(
833
854
fn live_symbols_and_ignored_derived_traits (
834
855
tcx : TyCtxt < ' _ > ,
835
856
( ) : ( ) ,
836
- ) -> ( LocalDefIdSet , LocalDefIdMap < FxIndexSet < DefId > > ) {
857
+ ) -> Result < ( LocalDefIdSet , LocalDefIdMap < FxIndexSet < DefId > > ) , ErrorGuaranteed > {
837
858
let ( worklist, mut unsolved_items) = create_and_seed_worklist ( tcx) ;
838
859
let mut symbol_visitor = MarkSymbolVisitor {
839
860
worklist,
@@ -847,7 +868,9 @@ fn live_symbols_and_ignored_derived_traits(
847
868
ignore_variant_stack : vec ! [ ] ,
848
869
ignored_derived_traits : Default :: default ( ) ,
849
870
} ;
850
- symbol_visitor. mark_live_symbols ( ) ;
871
+ if let ControlFlow :: Break ( guar) = symbol_visitor. mark_live_symbols ( ) {
872
+ return Err ( guar) ;
873
+ }
851
874
852
875
// We have marked the primary seeds as live. We now need to process unsolved items from traits
853
876
// and trait impls: add them to the work list if the trait or the implemented type is live.
@@ -861,14 +884,16 @@ fn live_symbols_and_ignored_derived_traits(
861
884
symbol_visitor
862
885
. worklist
863
886
. extend ( items_to_check. drain ( ..) . map ( |id| ( id, ComesFromAllowExpect :: No ) ) ) ;
864
- symbol_visitor. mark_live_symbols ( ) ;
887
+ if let ControlFlow :: Break ( guar) = symbol_visitor. mark_live_symbols ( ) {
888
+ return Err ( guar) ;
889
+ }
865
890
866
891
items_to_check. extend ( unsolved_items. extract_if ( .., |& mut local_def_id| {
867
892
symbol_visitor. check_impl_or_impl_item_live ( local_def_id)
868
893
} ) ) ;
869
894
}
870
895
871
- ( symbol_visitor. live_symbols , symbol_visitor. ignored_derived_traits )
896
+ Ok ( ( symbol_visitor. live_symbols , symbol_visitor. ignored_derived_traits ) )
872
897
}
873
898
874
899
struct DeadItem {
@@ -1148,7 +1173,11 @@ impl<'tcx> DeadVisitor<'tcx> {
1148
1173
}
1149
1174
1150
1175
fn check_mod_deathness ( tcx : TyCtxt < ' _ > , module : LocalModDefId ) {
1151
- let ( live_symbols, ignored_derived_traits) = tcx. live_symbols_and_ignored_derived_traits ( ( ) ) ;
1176
+ let live_symbols_result = tcx. live_symbols_and_ignored_derived_traits ( ( ) ) ;
1177
+ if live_symbols_result. is_err ( ) {
1178
+ return ;
1179
+ }
1180
+ let ( live_symbols, ignored_derived_traits) = live_symbols_result. as_ref ( ) . unwrap ( ) ;
1152
1181
let mut visitor = DeadVisitor { tcx, live_symbols, ignored_derived_traits } ;
1153
1182
1154
1183
let module_items = tcx. hir_module_items ( module) ;
0 commit comments