@@ -15,7 +15,7 @@ use rustc_hir::{Node, PatKind, TyKind};
1515use rustc_middle:: middle:: codegen_fn_attrs:: CodegenFnAttrFlags ;
1616use rustc_middle:: middle:: privacy:: Level ;
1717use rustc_middle:: query:: Providers ;
18- use rustc_middle:: ty:: { self , AssocItemContainer , TyCtxt } ;
18+ use rustc_middle:: ty:: { self , AssocItemContainer , Ty , TyCtxt , TypeSuperVisitable , TypeVisitor } ;
1919use rustc_middle:: { bug, span_bug} ;
2020use rustc_session:: lint;
2121use rustc_session:: lint:: builtin:: DEAD_CODE ;
@@ -450,7 +450,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
450450 intravisit:: walk_item ( self , item)
451451 }
452452 hir:: ItemKind :: ForeignMod { .. } => { }
453- hir:: ItemKind :: Trait ( _ , _ , _ , _ , trait_item_refs ) => {
453+ hir:: ItemKind :: Trait ( .. ) => {
454454 for impl_def_id in self . tcx . all_impls ( item. owner_id . to_def_id ( ) ) {
455455 if let Some ( local_def_id) = impl_def_id. as_local ( )
456456 && let ItemKind :: Impl ( impl_ref) =
@@ -463,12 +463,13 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
463463 intravisit:: walk_path ( self , impl_ref. of_trait . unwrap ( ) . path ) ;
464464 }
465465 }
466- // mark assoc ty live if the trait is live
467- for trait_item in trait_item_refs {
468- if let hir:: AssocItemKind :: Type = trait_item. kind {
469- self . check_def_id ( trait_item. id . owner_id . to_def_id ( ) ) ;
470- }
471- }
466+ intravisit:: walk_item ( self , item)
467+ }
468+ hir:: ItemKind :: Fn ( ..) => {
469+ // check `T::Ty` in the types of inputs and output
470+ // the result of type_of maybe different from the fn sig,
471+ // so we also check the fn sig
472+ self . visit_middle_fn_sig ( item. owner_id . def_id ) ;
472473 intravisit:: walk_item ( self , item)
473474 }
474475 _ => intravisit:: walk_item ( self , item) ,
@@ -504,6 +505,21 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
504505 }
505506 }
506507 }
508+
509+ match trait_item. kind {
510+ hir:: TraitItemKind :: Fn ( ..) => {
511+ // check `T::Ty` in the types of inputs and output
512+ // the result of type_of maybe different from the fn sig,
513+ // so we also check the fn sig
514+ self . visit_middle_fn_sig ( trait_item. owner_id . def_id )
515+ }
516+ hir:: TraitItemKind :: Type ( .., Some ( _) ) | hir:: TraitItemKind :: Const ( ..) => {
517+ // check `type X = T::Ty;` or `const X: T::Ty;`
518+ self . visit_middle_ty_by_def_id ( trait_item. owner_id . def_id )
519+ }
520+ _ => ( ) ,
521+ }
522+
507523 intravisit:: walk_trait_item ( self , trait_item) ;
508524 }
509525 Node :: ImplItem ( impl_item) => {
@@ -525,6 +541,20 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
525541 _ => { }
526542 }
527543 }
544+
545+ match impl_item. kind {
546+ hir:: ImplItemKind :: Fn ( ..) => {
547+ // check `T::Ty` in the types of inputs and output
548+ // the result of type_of maybe different from the fn sig,
549+ // so we also check the fn sig
550+ self . visit_middle_fn_sig ( impl_item. owner_id . def_id )
551+ }
552+ hir:: ImplItemKind :: Type ( ..) | hir:: ImplItemKind :: Const ( ..) => {
553+ // check `type X = T::Ty;` or `const X: T::Ty;`
554+ self . visit_middle_ty_by_def_id ( impl_item. owner_id . def_id )
555+ }
556+ }
557+
528558 intravisit:: walk_impl_item ( self , impl_item) ;
529559 }
530560 Node :: ForeignItem ( foreign_item) => {
@@ -587,6 +617,22 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
587617 false
588618 }
589619 }
620+
621+ fn visit_middle_ty ( & mut self , ty : Ty < ' tcx > ) {
622+ <Self as TypeVisitor < TyCtxt < ' tcx > > >:: visit_ty ( self , ty) ;
623+ }
624+
625+ fn visit_middle_ty_by_def_id ( & mut self , def_id : LocalDefId ) {
626+ self . visit_middle_ty ( self . tcx . type_of ( def_id) . instantiate_identity ( ) ) ;
627+ }
628+
629+ fn visit_middle_fn_sig ( & mut self , def_id : LocalDefId ) {
630+ let fn_sig = self . tcx . fn_sig ( def_id) . instantiate_identity ( ) ;
631+ for ty in fn_sig. inputs ( ) . skip_binder ( ) {
632+ self . visit_middle_ty ( ty. clone ( ) ) ;
633+ }
634+ self . visit_middle_ty ( fn_sig. output ( ) . skip_binder ( ) . clone ( ) ) ;
635+ }
590636}
591637
592638impl < ' tcx > Visitor < ' tcx > for MarkSymbolVisitor < ' tcx > {
@@ -618,6 +664,19 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
618664 intravisit:: walk_struct_def ( self , def) ;
619665 }
620666
667+ fn visit_field_def ( & mut self , s : & ' tcx rustc_hir:: FieldDef < ' tcx > ) {
668+ // check `field: T::Ty`
669+ // marks assoc types live whether the field is not used or not
670+ // there are three situations:
671+ // 1. the field is used, it's good
672+ // 2. the field is not used but marked like `#[allow(dead_code)]`,
673+ // it's annoying to mark the assoc type `#[allow(dead_code)]` again
674+ // 3. the field is not used, and will be linted
675+ // the assoc type will be linted after removing the unused field
676+ self . visit_middle_ty_by_def_id ( s. def_id ) ;
677+ intravisit:: walk_field_def ( self , s) ;
678+ }
679+
621680 fn visit_expr ( & mut self , expr : & ' tcx hir:: Expr < ' tcx > ) {
622681 match expr. kind {
623682 hir:: ExprKind :: Path ( ref qpath @ hir:: QPath :: TypeRelative ( ..) ) => {
@@ -650,6 +709,9 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
650709 _ => ( ) ,
651710 }
652711
712+ // check the expr_ty if its type is `T::Ty`
713+ self . visit_middle_ty ( self . typeck_results ( ) . expr_ty ( expr) ) ;
714+
653715 intravisit:: walk_expr ( self , expr) ;
654716 }
655717
@@ -722,6 +784,41 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
722784
723785 self . in_pat = in_pat;
724786 }
787+
788+ fn visit_poly_trait_ref ( & mut self , t : & ' tcx hir:: PolyTraitRef < ' tcx > ) {
789+ // mark the assoc type/const appears in poly-trait-ref live
790+ if let Some ( pathsegment) = t. trait_ref . path . segments . last ( )
791+ && let Some ( args) = pathsegment. args
792+ {
793+ for constraint in args. constraints {
794+ if let Some ( item) = self
795+ . tcx
796+ . associated_items ( pathsegment. res . def_id ( ) )
797+ . filter_by_name_unhygienic ( constraint. ident . name )
798+ . find ( |i| {
799+ matches ! ( i. kind, ty:: AssocKind :: Const | ty:: AssocKind :: Type )
800+ && i. ident ( self . tcx ) . normalize_to_macros_2_0 ( ) == constraint. ident
801+ } )
802+ && let Some ( local_def_id) = item. def_id . as_local ( )
803+ {
804+ self . worklist . push ( ( local_def_id, ComesFromAllowExpect :: No ) ) ;
805+ }
806+ }
807+ }
808+ intravisit:: walk_poly_trait_ref ( self , t) ;
809+ }
810+ }
811+
812+ impl < ' tcx > TypeVisitor < TyCtxt < ' tcx > > for MarkSymbolVisitor < ' tcx > {
813+ fn visit_ty ( & mut self , ty : Ty < ' tcx > ) {
814+ match ty. kind ( ) {
815+ ty:: Alias ( _, alias) => {
816+ self . check_def_id ( alias. def_id ) ;
817+ }
818+ _ => ( ) ,
819+ }
820+ ty. super_visit_with ( self ) ;
821+ }
725822}
726823
727824fn has_allow_dead_code_or_lang_attr (
0 commit comments