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`
@@ -391,19 +397,22 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
391
397
false
392
398
}
393
399
394
- fn visit_node ( & mut self , node : Node < ' tcx > ) {
400
+ fn visit_node (
401
+ & mut self ,
402
+ node : Node < ' tcx > ,
403
+ ) -> <MarkSymbolVisitor < ' tcx > as Visitor < ' tcx > >:: Result {
395
404
if let Node :: ImplItem ( impl_item) = node
396
405
&& self . should_ignore_impl_item ( impl_item)
397
406
{
398
- return ;
407
+ return ControlFlow :: Continue ( ( ) ) ;
399
408
}
400
409
401
410
let unconditionally_treated_fields_as_live =
402
411
self . repr_unconditionally_treats_fields_as_live ;
403
412
let had_repr_simd = self . repr_has_repr_simd ;
404
413
self . repr_unconditionally_treats_fields_as_live = false ;
405
414
self . repr_has_repr_simd = false ;
406
- match node {
415
+ let walk_result = match node {
407
416
Node :: Item ( item) => match item. kind {
408
417
hir:: ItemKind :: Struct ( ..) | hir:: ItemKind :: Union ( ..) => {
409
418
let def = self . tcx . adt_def ( item. owner_id ) ;
@@ -413,7 +422,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
413
422
414
423
intravisit:: walk_item ( self , item)
415
424
}
416
- hir:: ItemKind :: ForeignMod { .. } => { }
425
+ hir:: ItemKind :: ForeignMod { .. } => ControlFlow :: Continue ( ( ) ) ,
417
426
hir:: ItemKind :: Trait ( .., trait_item_refs) => {
418
427
// mark assoc ty live if the trait is live
419
428
for trait_item in trait_item_refs {
@@ -431,7 +440,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
431
440
if let Some ( trait_id) = self . tcx . trait_of_assoc ( trait_item_id) {
432
441
self . check_def_id ( trait_id) ;
433
442
}
434
- intravisit:: walk_trait_item ( self , trait_item) ;
443
+ intravisit:: walk_trait_item ( self , trait_item)
435
444
}
436
445
Node :: ImplItem ( impl_item) => {
437
446
let item = self . tcx . local_parent ( impl_item. owner_id . def_id ) ;
@@ -452,16 +461,16 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
452
461
_ => { }
453
462
}
454
463
}
455
- intravisit:: walk_impl_item ( self , impl_item) ;
456
- }
457
- Node :: ForeignItem ( foreign_item) => {
458
- intravisit:: walk_foreign_item ( self , foreign_item) ;
464
+ intravisit:: walk_impl_item ( self , impl_item)
459
465
}
466
+ Node :: ForeignItem ( foreign_item) => intravisit:: walk_foreign_item ( self , foreign_item) ,
460
467
Node :: OpaqueTy ( opaq) => intravisit:: walk_opaque_ty ( self , opaq) ,
461
- _ => { }
462
- }
468
+ _ => ControlFlow :: Continue ( ( ) ) ,
469
+ } ;
463
470
self . repr_has_repr_simd = had_repr_simd;
464
471
self . repr_unconditionally_treats_fields_as_live = unconditionally_treated_fields_as_live;
472
+
473
+ walk_result
465
474
}
466
475
467
476
fn mark_as_used_if_union ( & mut self , adt : ty:: AdtDef < ' tcx > , fields : & [ hir:: ExprField < ' _ > ] ) {
@@ -514,15 +523,25 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
514
523
}
515
524
516
525
impl < ' tcx > Visitor < ' tcx > for MarkSymbolVisitor < ' tcx > {
517
- fn visit_nested_body ( & mut self , body : hir:: BodyId ) {
518
- let old_maybe_typeck_results =
519
- self . maybe_typeck_results . replace ( self . tcx . typeck_body ( body) ) ;
526
+ type Result = ControlFlow < ErrorGuaranteed > ;
527
+
528
+ fn visit_nested_body ( & mut self , body : hir:: BodyId ) -> Self :: Result {
529
+ let typeck_results = self . tcx . typeck_body ( body) ;
530
+
531
+ // The result shouldn't be tainted, otherwise it will cause ICE.
532
+ if let Some ( guar) = typeck_results. tainted_by_errors {
533
+ return ControlFlow :: Break ( guar) ;
534
+ }
535
+
536
+ let old_maybe_typeck_results = self . maybe_typeck_results . replace ( typeck_results) ;
520
537
let body = self . tcx . hir_body ( body) ;
521
- self . visit_body ( body) ;
538
+ let result = self . visit_body ( body) ;
522
539
self . maybe_typeck_results = old_maybe_typeck_results;
540
+
541
+ result
523
542
}
524
543
525
- fn visit_variant_data ( & mut self , def : & ' tcx hir:: VariantData < ' tcx > ) {
544
+ fn visit_variant_data ( & mut self , def : & ' tcx hir:: VariantData < ' tcx > ) -> Self :: Result {
526
545
let tcx = self . tcx ;
527
546
let unconditionally_treat_fields_as_live = self . repr_unconditionally_treats_fields_as_live ;
528
547
let has_repr_simd = self . repr_has_repr_simd ;
@@ -539,10 +558,10 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
539
558
} ) ;
540
559
self . live_symbols . extend ( live_fields) ;
541
560
542
- intravisit:: walk_struct_def ( self , def) ;
561
+ intravisit:: walk_struct_def ( self , def)
543
562
}
544
563
545
- fn visit_expr ( & mut self , expr : & ' tcx hir:: Expr < ' tcx > ) {
564
+ fn visit_expr ( & mut self , expr : & ' tcx hir:: Expr < ' tcx > ) -> Self :: Result {
546
565
match expr. kind {
547
566
hir:: ExprKind :: Path ( ref qpath @ QPath :: TypeRelative ( ..) ) => {
548
567
let res = self . typeck_results ( ) . qpath_res ( qpath, expr. hir_id ) ;
@@ -578,20 +597,22 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
578
597
_ => ( ) ,
579
598
}
580
599
581
- intravisit:: walk_expr ( self , expr) ;
600
+ intravisit:: walk_expr ( self , expr)
582
601
}
583
602
584
- fn visit_arm ( & mut self , arm : & ' tcx hir:: Arm < ' tcx > ) {
603
+ fn visit_arm ( & mut self , arm : & ' tcx hir:: Arm < ' tcx > ) -> Self :: Result {
585
604
// Inside the body, ignore constructions of variants
586
605
// necessary for the pattern to match. Those construction sites
587
606
// can't be reached unless the variant is constructed elsewhere.
588
607
let len = self . ignore_variant_stack . len ( ) ;
589
608
self . ignore_variant_stack . extend ( arm. pat . necessary_variants ( ) ) ;
590
- intravisit:: walk_arm ( self , arm) ;
609
+ let result = intravisit:: walk_arm ( self , arm) ;
591
610
self . ignore_variant_stack . truncate ( len) ;
611
+
612
+ result
592
613
}
593
614
594
- fn visit_pat ( & mut self , pat : & ' tcx hir:: Pat < ' tcx > ) {
615
+ fn visit_pat ( & mut self , pat : & ' tcx hir:: Pat < ' tcx > ) -> Self :: Result {
595
616
self . in_pat = true ;
596
617
match pat. kind {
597
618
PatKind :: Struct ( ref path, fields, _) => {
@@ -605,11 +626,13 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
605
626
_ => ( ) ,
606
627
}
607
628
608
- intravisit:: walk_pat ( self , pat) ;
629
+ let result = intravisit:: walk_pat ( self , pat) ;
609
630
self . in_pat = false ;
631
+
632
+ result
610
633
}
611
634
612
- fn visit_pat_expr ( & mut self , expr : & ' tcx rustc_hir:: PatExpr < ' tcx > ) {
635
+ fn visit_pat_expr ( & mut self , expr : & ' tcx rustc_hir:: PatExpr < ' tcx > ) -> Self :: Result {
613
636
match & expr. kind {
614
637
rustc_hir:: PatExprKind :: Path ( qpath) => {
615
638
// mark the type of variant live when meeting E::V in expr
@@ -622,37 +645,41 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
622
645
}
623
646
_ => { }
624
647
}
625
- intravisit:: walk_pat_expr ( self , expr) ;
648
+ intravisit:: walk_pat_expr ( self , expr)
626
649
}
627
650
628
- fn visit_path ( & mut self , path : & hir:: Path < ' tcx > , _: hir:: HirId ) {
651
+ fn visit_path ( & mut self , path : & hir:: Path < ' tcx > , _: hir:: HirId ) -> Self :: Result {
629
652
self . handle_res ( path. res ) ;
630
- intravisit:: walk_path ( self , path) ;
653
+ intravisit:: walk_path ( self , path)
631
654
}
632
655
633
- fn visit_anon_const ( & mut self , c : & ' tcx hir:: AnonConst ) {
656
+ fn visit_anon_const ( & mut self , c : & ' tcx hir:: AnonConst ) -> Self :: Result {
634
657
// When inline const blocks are used in pattern position, paths
635
658
// referenced by it should be considered as used.
636
659
let in_pat = mem:: replace ( & mut self . in_pat , false ) ;
637
660
638
661
self . live_symbols . insert ( c. def_id ) ;
639
- intravisit:: walk_anon_const ( self , c) ;
662
+ let result = intravisit:: walk_anon_const ( self , c) ;
640
663
641
664
self . in_pat = in_pat;
665
+
666
+ result
642
667
}
643
668
644
- fn visit_inline_const ( & mut self , c : & ' tcx hir:: ConstBlock ) {
669
+ fn visit_inline_const ( & mut self , c : & ' tcx hir:: ConstBlock ) -> Self :: Result {
645
670
// When inline const blocks are used in pattern position, paths
646
671
// referenced by it should be considered as used.
647
672
let in_pat = mem:: replace ( & mut self . in_pat , false ) ;
648
673
649
674
self . live_symbols . insert ( c. def_id ) ;
650
- intravisit:: walk_inline_const ( self , c) ;
675
+ let result = intravisit:: walk_inline_const ( self , c) ;
651
676
652
677
self . in_pat = in_pat;
678
+
679
+ result
653
680
}
654
681
655
- fn visit_trait_ref ( & mut self , t : & ' tcx hir:: TraitRef < ' tcx > ) {
682
+ fn visit_trait_ref ( & mut self , t : & ' tcx hir:: TraitRef < ' tcx > ) -> Self :: Result {
656
683
if let Some ( trait_def_id) = t. path . res . opt_def_id ( )
657
684
&& let Some ( segment) = t. path . segments . last ( )
658
685
&& let Some ( args) = segment. args
@@ -674,7 +701,7 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
674
701
}
675
702
}
676
703
677
- intravisit:: walk_trait_ref ( self , t) ;
704
+ intravisit:: walk_trait_ref ( self , t)
678
705
}
679
706
}
680
707
@@ -821,7 +848,7 @@ fn create_and_seed_worklist(
821
848
fn live_symbols_and_ignored_derived_traits (
822
849
tcx : TyCtxt < ' _ > ,
823
850
( ) : ( ) ,
824
- ) -> ( LocalDefIdSet , LocalDefIdMap < FxIndexSet < DefId > > ) {
851
+ ) -> Result < ( LocalDefIdSet , LocalDefIdMap < FxIndexSet < DefId > > ) , ErrorGuaranteed > {
825
852
let ( worklist, mut unsolved_items) = create_and_seed_worklist ( tcx) ;
826
853
let mut symbol_visitor = MarkSymbolVisitor {
827
854
worklist,
@@ -835,7 +862,9 @@ fn live_symbols_and_ignored_derived_traits(
835
862
ignore_variant_stack : vec ! [ ] ,
836
863
ignored_derived_traits : Default :: default ( ) ,
837
864
} ;
838
- symbol_visitor. mark_live_symbols ( ) ;
865
+ if let ControlFlow :: Break ( guar) = symbol_visitor. mark_live_symbols ( ) {
866
+ return Err ( guar) ;
867
+ }
839
868
840
869
// We have marked the primary seeds as live. We now need to process unsolved items from traits
841
870
// and trait impls: add them to the work list if the trait or the implemented type is live.
@@ -849,14 +878,16 @@ fn live_symbols_and_ignored_derived_traits(
849
878
symbol_visitor
850
879
. worklist
851
880
. extend ( items_to_check. drain ( ..) . map ( |id| ( id, ComesFromAllowExpect :: No ) ) ) ;
852
- symbol_visitor. mark_live_symbols ( ) ;
881
+ if let ControlFlow :: Break ( guar) = symbol_visitor. mark_live_symbols ( ) {
882
+ return Err ( guar) ;
883
+ }
853
884
854
885
items_to_check. extend ( unsolved_items. extract_if ( .., |& mut local_def_id| {
855
886
symbol_visitor. check_impl_or_impl_item_live ( local_def_id)
856
887
} ) ) ;
857
888
}
858
889
859
- ( symbol_visitor. live_symbols , symbol_visitor. ignored_derived_traits )
890
+ Ok ( ( symbol_visitor. live_symbols , symbol_visitor. ignored_derived_traits ) )
860
891
}
861
892
862
893
struct DeadItem {
@@ -1136,7 +1167,11 @@ impl<'tcx> DeadVisitor<'tcx> {
1136
1167
}
1137
1168
1138
1169
fn check_mod_deathness ( tcx : TyCtxt < ' _ > , module : LocalModDefId ) {
1139
- let ( live_symbols, ignored_derived_traits) = tcx. live_symbols_and_ignored_derived_traits ( ( ) ) ;
1170
+ let live_symbols_result = tcx. live_symbols_and_ignored_derived_traits ( ( ) ) ;
1171
+ if live_symbols_result. is_err ( ) {
1172
+ return ;
1173
+ }
1174
+ let ( live_symbols, ignored_derived_traits) = live_symbols_result. as_ref ( ) . unwrap ( ) ;
1140
1175
let mut visitor = DeadVisitor { tcx, live_symbols, ignored_derived_traits } ;
1141
1176
1142
1177
let module_items = tcx. hir_module_items ( module) ;
0 commit comments