@@ -17,7 +17,7 @@ use rustc_hir::{Node, PatKind, TyKind};
1717use rustc_middle:: middle:: codegen_fn_attrs:: CodegenFnAttrFlags ;
1818use rustc_middle:: middle:: privacy:: Level ;
1919use rustc_middle:: query:: Providers ;
20- use rustc_middle:: ty:: { self , AssocItemContainer , TyCtxt } ;
20+ use rustc_middle:: ty:: { self , AssocItemContainer , Ty , TyCtxt , TypeSuperVisitable , TypeVisitor } ;
2121use rustc_middle:: { bug, span_bug} ;
2222use rustc_session:: lint;
2323use rustc_session:: lint:: builtin:: DEAD_CODE ;
@@ -465,7 +465,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
465465 intravisit:: walk_item ( self , item)
466466 }
467467 hir:: ItemKind :: ForeignMod { .. } => { }
468- hir:: ItemKind :: Trait ( _ , _ , _ , _ , trait_item_refs ) => {
468+ hir:: ItemKind :: Trait ( .. ) => {
469469 for impl_def_id in self . tcx . all_impls ( item. owner_id . to_def_id ( ) ) {
470470 if let Some ( local_def_id) = impl_def_id. as_local ( )
471471 && let ItemKind :: Impl ( impl_ref) =
@@ -478,12 +478,13 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
478478 intravisit:: walk_path ( self , impl_ref. of_trait . unwrap ( ) . path ) ;
479479 }
480480 }
481- // mark assoc ty live if the trait is live
482- for trait_item in trait_item_refs {
483- if let hir:: AssocItemKind :: Type = trait_item. kind {
484- self . check_def_id ( trait_item. id . owner_id . to_def_id ( ) ) ;
485- }
486- }
481+ intravisit:: walk_item ( self , item)
482+ }
483+ hir:: ItemKind :: Fn ( ..) => {
484+ // check `T::Ty` in the types of inputs and output
485+ // the result of type_of maybe different from the fn sig,
486+ // so we also check the fn sig
487+ self . visit_middle_fn_sig ( item. owner_id . def_id ) ;
487488 intravisit:: walk_item ( self , item)
488489 }
489490 _ => intravisit:: walk_item ( self , item) ,
@@ -519,6 +520,21 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
519520 }
520521 }
521522 }
523+
524+ match trait_item. kind {
525+ hir:: TraitItemKind :: Fn ( ..) => {
526+ // check `T::Ty` in the types of inputs and output
527+ // the result of type_of maybe different from the fn sig,
528+ // so we also check the fn sig
529+ self . visit_middle_fn_sig ( trait_item. owner_id . def_id )
530+ }
531+ hir:: TraitItemKind :: Type ( .., Some ( _) ) | hir:: TraitItemKind :: Const ( ..) => {
532+ // check `type X = T::Ty;` or `const X: T::Ty;`
533+ self . visit_middle_ty_by_def_id ( trait_item. owner_id . def_id )
534+ }
535+ _ => ( ) ,
536+ }
537+
522538 intravisit:: walk_trait_item ( self , trait_item) ;
523539 }
524540 Node :: ImplItem ( impl_item) => {
@@ -540,6 +556,20 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
540556 _ => { }
541557 }
542558 }
559+
560+ match impl_item. kind {
561+ hir:: ImplItemKind :: Fn ( ..) => {
562+ // check `T::Ty` in the types of inputs and output
563+ // the result of type_of maybe different from the fn sig,
564+ // so we also check the fn sig
565+ self . visit_middle_fn_sig ( impl_item. owner_id . def_id )
566+ }
567+ hir:: ImplItemKind :: Type ( ..) | hir:: ImplItemKind :: Const ( ..) => {
568+ // check `type X = T::Ty;` or `const X: T::Ty;`
569+ self . visit_middle_ty_by_def_id ( impl_item. owner_id . def_id )
570+ }
571+ }
572+
543573 intravisit:: walk_impl_item ( self , impl_item) ;
544574 }
545575 Node :: ForeignItem ( foreign_item) => {
@@ -600,6 +630,22 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
600630 false
601631 }
602632 }
633+
634+ fn visit_middle_ty ( & mut self , ty : Ty < ' tcx > ) {
635+ <Self as TypeVisitor < TyCtxt < ' tcx > > >:: visit_ty ( self , ty) ;
636+ }
637+
638+ fn visit_middle_ty_by_def_id ( & mut self , def_id : LocalDefId ) {
639+ self . visit_middle_ty ( self . tcx . type_of ( def_id) . instantiate_identity ( ) ) ;
640+ }
641+
642+ fn visit_middle_fn_sig ( & mut self , def_id : LocalDefId ) {
643+ let fn_sig = self . tcx . fn_sig ( def_id) . instantiate_identity ( ) ;
644+ for ty in fn_sig. inputs ( ) . skip_binder ( ) {
645+ self . visit_middle_ty ( ty. clone ( ) ) ;
646+ }
647+ self . visit_middle_ty ( fn_sig. output ( ) . skip_binder ( ) . clone ( ) ) ;
648+ }
603649}
604650
605651impl < ' tcx > Visitor < ' tcx > for MarkSymbolVisitor < ' tcx > {
@@ -631,6 +677,19 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
631677 intravisit:: walk_struct_def ( self , def) ;
632678 }
633679
680+ fn visit_field_def ( & mut self , s : & ' tcx rustc_hir:: FieldDef < ' tcx > ) {
681+ // check `field: T::Ty`
682+ // marks assoc types live whether the field is not used or not
683+ // there are three situations:
684+ // 1. the field is used, it's good
685+ // 2. the field is not used but marked like `#[allow(dead_code)]`,
686+ // it's annoying to mark the assoc type `#[allow(dead_code)]` again
687+ // 3. the field is not used, and will be linted
688+ // the assoc type will be linted after removing the unused field
689+ self . visit_middle_ty_by_def_id ( s. def_id ) ;
690+ intravisit:: walk_field_def ( self , s) ;
691+ }
692+
634693 fn visit_expr ( & mut self , expr : & ' tcx hir:: Expr < ' tcx > ) {
635694 match expr. kind {
636695 hir:: ExprKind :: Path ( ref qpath @ hir:: QPath :: TypeRelative ( ..) ) => {
@@ -663,6 +722,9 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
663722 _ => ( ) ,
664723 }
665724
725+ // check the expr_ty if its type is `T::Ty`
726+ self . visit_middle_ty ( self . typeck_results ( ) . expr_ty ( expr) ) ;
727+
666728 intravisit:: walk_expr ( self , expr) ;
667729 }
668730
@@ -703,6 +765,24 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
703765
704766 fn visit_path ( & mut self , path : & hir:: Path < ' tcx > , _: hir:: HirId ) {
705767 self . handle_res ( path. res ) ;
768+
769+ if let Res :: Def ( def_kind, def_id) = path. res
770+ && matches ! (
771+ def_kind,
772+ DefKind :: Fn
773+ | DefKind :: AssocFn
774+ | DefKind :: AssocTy
775+ | DefKind :: Struct
776+ | DefKind :: Union
777+ | DefKind :: Enum
778+ )
779+ {
780+ let preds = self . tcx . predicates_of ( def_id) . instantiate_identity ( self . tcx ) ;
781+ for pred in preds. iter ( ) {
782+ <Self as TypeVisitor < TyCtxt < ' tcx > > >:: visit_predicate ( self , pred. 0 . as_predicate ( ) ) ;
783+ }
784+ }
785+
706786 intravisit:: walk_path ( self , path) ;
707787 }
708788
@@ -735,6 +815,41 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
735815
736816 self . in_pat = in_pat;
737817 }
818+
819+ fn visit_poly_trait_ref ( & mut self , t : & ' tcx hir:: PolyTraitRef < ' tcx > ) {
820+ // mark the assoc type/const appears in poly-trait-ref live
821+ if let Some ( pathsegment) = t. trait_ref . path . segments . last ( )
822+ && let Some ( args) = pathsegment. args
823+ {
824+ for constraint in args. constraints {
825+ if let Some ( item) = self
826+ . tcx
827+ . associated_items ( pathsegment. res . def_id ( ) )
828+ . filter_by_name_unhygienic ( constraint. ident . name )
829+ . find ( |i| {
830+ matches ! ( i. kind, ty:: AssocKind :: Const | ty:: AssocKind :: Type )
831+ && i. ident ( self . tcx ) . normalize_to_macros_2_0 ( ) == constraint. ident
832+ } )
833+ && let Some ( local_def_id) = item. def_id . as_local ( )
834+ {
835+ self . worklist . push ( ( local_def_id, ComesFromAllowExpect :: No ) ) ;
836+ }
837+ }
838+ }
839+ intravisit:: walk_poly_trait_ref ( self , t) ;
840+ }
841+ }
842+
843+ impl < ' tcx > TypeVisitor < TyCtxt < ' tcx > > for MarkSymbolVisitor < ' tcx > {
844+ fn visit_ty ( & mut self , ty : Ty < ' tcx > ) {
845+ match ty. kind ( ) {
846+ ty:: Alias ( _, alias) => {
847+ self . check_def_id ( alias. def_id ) ;
848+ }
849+ _ => ( ) ,
850+ }
851+ ty. super_visit_with ( self ) ;
852+ }
738853}
739854
740855fn has_allow_dead_code_or_lang_attr (
0 commit comments