44// is dead.
55
66use std:: mem;
7+ use std:: ops:: ControlFlow ;
78
89use hir:: def_id:: { LocalDefIdMap , LocalDefIdSet } ;
910use rustc_abi:: FieldIdx ;
1011use rustc_data_structures:: fx:: FxIndexSet ;
11- use rustc_errors:: MultiSpan ;
12+ use rustc_errors:: { ErrorGuaranteed , MultiSpan } ;
1213use rustc_hir:: def:: { CtorOf , DefKind , Res } ;
1314use rustc_hir:: def_id:: { DefId , LocalDefId , LocalModDefId } ;
1415use rustc_hir:: intravisit:: { self , Visitor } ;
@@ -178,12 +179,12 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
178179 . iter ( )
179180 . any ( |adj| matches ! ( adj. kind, ty:: adjustment:: Adjust :: Deref ( _) ) )
180181 {
181- self . visit_expr ( expr) ;
182+ let _ = self . visit_expr ( expr) ;
182183 } else if let hir:: ExprKind :: Field ( base, ..) = expr. kind {
183184 // Ignore write to field
184185 self . handle_assign ( base) ;
185186 } else {
186- self . visit_expr ( expr) ;
187+ let _ = self . visit_expr ( expr) ;
187188 }
188189 }
189190
@@ -318,7 +319,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
318319 }
319320 }
320321
321- fn mark_live_symbols ( & mut self ) {
322+ fn mark_live_symbols ( & mut self ) -> < MarkSymbolVisitor < ' tcx > as Visitor < ' tcx > > :: Result {
322323 while let Some ( work) = self . worklist . pop ( ) {
323324 let ( mut id, comes_from_allow_expect) = work;
324325
@@ -366,8 +367,13 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
366367 continue ;
367368 }
368369
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+ }
370374 }
375+
376+ ControlFlow :: Continue ( ( ) )
371377 }
372378
373379 /// Automatically generated items marked with `rustc_trivial_field_reads`
@@ -391,19 +397,22 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
391397 false
392398 }
393399
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 {
395404 if let Node :: ImplItem ( impl_item) = node
396405 && self . should_ignore_impl_item ( impl_item)
397406 {
398- return ;
407+ return ControlFlow :: Continue ( ( ) ) ;
399408 }
400409
401410 let unconditionally_treated_fields_as_live =
402411 self . repr_unconditionally_treats_fields_as_live ;
403412 let had_repr_simd = self . repr_has_repr_simd ;
404413 self . repr_unconditionally_treats_fields_as_live = false ;
405414 self . repr_has_repr_simd = false ;
406- match node {
415+ let walk_result = match node {
407416 Node :: Item ( item) => match item. kind {
408417 hir:: ItemKind :: Struct ( ..) | hir:: ItemKind :: Union ( ..) => {
409418 let def = self . tcx . adt_def ( item. owner_id ) ;
@@ -413,7 +422,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
413422
414423 intravisit:: walk_item ( self , item)
415424 }
416- hir:: ItemKind :: ForeignMod { .. } => { }
425+ hir:: ItemKind :: ForeignMod { .. } => ControlFlow :: Continue ( ( ) ) ,
417426 hir:: ItemKind :: Trait ( .., trait_item_refs) => {
418427 // mark assoc ty live if the trait is live
419428 for trait_item in trait_item_refs {
@@ -431,7 +440,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
431440 if let Some ( trait_id) = self . tcx . trait_of_assoc ( trait_item_id) {
432441 self . check_def_id ( trait_id) ;
433442 }
434- intravisit:: walk_trait_item ( self , trait_item) ;
443+ intravisit:: walk_trait_item ( self , trait_item)
435444 }
436445 Node :: ImplItem ( impl_item) => {
437446 let item = self . tcx . local_parent ( impl_item. owner_id . def_id ) ;
@@ -452,16 +461,16 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
452461 _ => { }
453462 }
454463 }
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)
459465 }
466+ Node :: ForeignItem ( foreign_item) => intravisit:: walk_foreign_item ( self , foreign_item) ,
460467 Node :: OpaqueTy ( opaq) => intravisit:: walk_opaque_ty ( self , opaq) ,
461- _ => { }
462- }
468+ _ => ControlFlow :: Continue ( ( ) ) ,
469+ } ;
463470 self . repr_has_repr_simd = had_repr_simd;
464471 self . repr_unconditionally_treats_fields_as_live = unconditionally_treated_fields_as_live;
472+
473+ walk_result
465474 }
466475
467476 fn mark_as_used_if_union ( & mut self , adt : ty:: AdtDef < ' tcx > , fields : & [ hir:: ExprField < ' _ > ] ) {
@@ -514,15 +523,25 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
514523}
515524
516525impl < ' 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) ;
520537 let body = self . tcx . hir_body ( body) ;
521- self . visit_body ( body) ;
538+ let result = self . visit_body ( body) ;
522539 self . maybe_typeck_results = old_maybe_typeck_results;
540+
541+ result
523542 }
524543
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 {
526545 let tcx = self . tcx ;
527546 let unconditionally_treat_fields_as_live = self . repr_unconditionally_treats_fields_as_live ;
528547 let has_repr_simd = self . repr_has_repr_simd ;
@@ -539,10 +558,10 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
539558 } ) ;
540559 self . live_symbols . extend ( live_fields) ;
541560
542- intravisit:: walk_struct_def ( self , def) ;
561+ intravisit:: walk_struct_def ( self , def)
543562 }
544563
545- fn visit_expr ( & mut self , expr : & ' tcx hir:: Expr < ' tcx > ) {
564+ fn visit_expr ( & mut self , expr : & ' tcx hir:: Expr < ' tcx > ) -> Self :: Result {
546565 match expr. kind {
547566 hir:: ExprKind :: Path ( ref qpath @ QPath :: TypeRelative ( ..) ) => {
548567 let res = self . typeck_results ( ) . qpath_res ( qpath, expr. hir_id ) ;
@@ -578,20 +597,22 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
578597 _ => ( ) ,
579598 }
580599
581- intravisit:: walk_expr ( self , expr) ;
600+ intravisit:: walk_expr ( self , expr)
582601 }
583602
584- fn visit_arm ( & mut self , arm : & ' tcx hir:: Arm < ' tcx > ) {
603+ fn visit_arm ( & mut self , arm : & ' tcx hir:: Arm < ' tcx > ) -> Self :: Result {
585604 // Inside the body, ignore constructions of variants
586605 // necessary for the pattern to match. Those construction sites
587606 // can't be reached unless the variant is constructed elsewhere.
588607 let len = self . ignore_variant_stack . len ( ) ;
589608 self . ignore_variant_stack . extend ( arm. pat . necessary_variants ( ) ) ;
590- intravisit:: walk_arm ( self , arm) ;
609+ let result = intravisit:: walk_arm ( self , arm) ;
591610 self . ignore_variant_stack . truncate ( len) ;
611+
612+ result
592613 }
593614
594- fn visit_pat ( & mut self , pat : & ' tcx hir:: Pat < ' tcx > ) {
615+ fn visit_pat ( & mut self , pat : & ' tcx hir:: Pat < ' tcx > ) -> Self :: Result {
595616 self . in_pat = true ;
596617 match pat. kind {
597618 PatKind :: Struct ( ref path, fields, _) => {
@@ -605,11 +626,13 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
605626 _ => ( ) ,
606627 }
607628
608- intravisit:: walk_pat ( self , pat) ;
629+ let result = intravisit:: walk_pat ( self , pat) ;
609630 self . in_pat = false ;
631+
632+ result
610633 }
611634
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 {
613636 match & expr. kind {
614637 rustc_hir:: PatExprKind :: Path ( qpath) => {
615638 // mark the type of variant live when meeting E::V in expr
@@ -622,37 +645,41 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
622645 }
623646 _ => { }
624647 }
625- intravisit:: walk_pat_expr ( self , expr) ;
648+ intravisit:: walk_pat_expr ( self , expr)
626649 }
627650
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 {
629652 self . handle_res ( path. res ) ;
630- intravisit:: walk_path ( self , path) ;
653+ intravisit:: walk_path ( self , path)
631654 }
632655
633- fn visit_anon_const ( & mut self , c : & ' tcx hir:: AnonConst ) {
656+ fn visit_anon_const ( & mut self , c : & ' tcx hir:: AnonConst ) -> Self :: Result {
634657 // When inline const blocks are used in pattern position, paths
635658 // referenced by it should be considered as used.
636659 let in_pat = mem:: replace ( & mut self . in_pat , false ) ;
637660
638661 self . live_symbols . insert ( c. def_id ) ;
639- intravisit:: walk_anon_const ( self , c) ;
662+ let result = intravisit:: walk_anon_const ( self , c) ;
640663
641664 self . in_pat = in_pat;
665+
666+ result
642667 }
643668
644- fn visit_inline_const ( & mut self , c : & ' tcx hir:: ConstBlock ) {
669+ fn visit_inline_const ( & mut self , c : & ' tcx hir:: ConstBlock ) -> Self :: Result {
645670 // When inline const blocks are used in pattern position, paths
646671 // referenced by it should be considered as used.
647672 let in_pat = mem:: replace ( & mut self . in_pat , false ) ;
648673
649674 self . live_symbols . insert ( c. def_id ) ;
650- intravisit:: walk_inline_const ( self , c) ;
675+ let result = intravisit:: walk_inline_const ( self , c) ;
651676
652677 self . in_pat = in_pat;
678+
679+ result
653680 }
654681
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 {
656683 if let Some ( trait_def_id) = t. path . res . opt_def_id ( )
657684 && let Some ( segment) = t. path . segments . last ( )
658685 && let Some ( args) = segment. args
@@ -674,7 +701,7 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
674701 }
675702 }
676703
677- intravisit:: walk_trait_ref ( self , t) ;
704+ intravisit:: walk_trait_ref ( self , t)
678705 }
679706}
680707
@@ -821,7 +848,7 @@ fn create_and_seed_worklist(
821848fn live_symbols_and_ignored_derived_traits (
822849 tcx : TyCtxt < ' _ > ,
823850 ( ) : ( ) ,
824- ) -> ( LocalDefIdSet , LocalDefIdMap < FxIndexSet < DefId > > ) {
851+ ) -> Result < ( LocalDefIdSet , LocalDefIdMap < FxIndexSet < DefId > > ) , ErrorGuaranteed > {
825852 let ( worklist, mut unsolved_items) = create_and_seed_worklist ( tcx) ;
826853 let mut symbol_visitor = MarkSymbolVisitor {
827854 worklist,
@@ -835,7 +862,9 @@ fn live_symbols_and_ignored_derived_traits(
835862 ignore_variant_stack : vec ! [ ] ,
836863 ignored_derived_traits : Default :: default ( ) ,
837864 } ;
838- symbol_visitor. mark_live_symbols ( ) ;
865+ if let ControlFlow :: Break ( guar) = symbol_visitor. mark_live_symbols ( ) {
866+ return Err ( guar) ;
867+ }
839868
840869 // We have marked the primary seeds as live. We now need to process unsolved items from traits
841870 // 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(
849878 symbol_visitor
850879 . worklist
851880 . 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+ }
853884
854885 items_to_check. extend ( unsolved_items. extract_if ( .., |& mut local_def_id| {
855886 symbol_visitor. check_impl_or_impl_item_live ( local_def_id)
856887 } ) ) ;
857888 }
858889
859- ( symbol_visitor. live_symbols , symbol_visitor. ignored_derived_traits )
890+ Ok ( ( symbol_visitor. live_symbols , symbol_visitor. ignored_derived_traits ) )
860891}
861892
862893struct DeadItem {
@@ -1136,7 +1167,11 @@ impl<'tcx> DeadVisitor<'tcx> {
11361167}
11371168
11381169fn 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 ( ) ;
11401175 let mut visitor = DeadVisitor { tcx, live_symbols, ignored_derived_traits } ;
11411176
11421177 let module_items = tcx. hir_module_items ( module) ;
0 commit comments