@@ -7,8 +7,9 @@ use rustc_attr as attr;
77use rustc_errors:: { Applicability , ErrorReported } ;
88use rustc_hir as hir;
99use rustc_hir:: def_id:: { DefId , LocalDefId , LOCAL_CRATE } ;
10+ use rustc_hir:: intravisit:: Visitor ;
1011use rustc_hir:: lang_items:: LangItem ;
11- use rustc_hir:: { ItemKind , Node } ;
12+ use rustc_hir:: { def :: Res , ItemKind , Node , PathSegment } ;
1213use rustc_infer:: infer:: type_variable:: { TypeVariableOrigin , TypeVariableOriginKind } ;
1314use rustc_infer:: infer:: { RegionVariableOrigin , TyCtxtInferExt } ;
1415use rustc_middle:: ty:: fold:: TypeFoldable ;
@@ -513,10 +514,11 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
513514 }
514515 }
515516
516- #[ derive( Debug ) ]
517517 struct ProhibitOpaqueVisitor < ' tcx > {
518518 opaque_identity_ty : Ty < ' tcx > ,
519519 generics : & ' tcx ty:: Generics ,
520+ tcx : TyCtxt < ' tcx > ,
521+ selftys : Vec < ( Span , Option < String > ) > ,
520522 }
521523
522524 impl < ' tcx > ty:: fold:: TypeVisitor < ' tcx > for ProhibitOpaqueVisitor < ' tcx > {
@@ -533,6 +535,29 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
533535 }
534536 }
535537
538+ impl Visitor < ' tcx > for ProhibitOpaqueVisitor < ' tcx > {
539+ type Map = rustc_middle:: hir:: map:: Map < ' tcx > ;
540+
541+ fn nested_visit_map ( & mut self ) -> hir:: intravisit:: NestedVisitorMap < Self :: Map > {
542+ hir:: intravisit:: NestedVisitorMap :: OnlyBodies ( self . tcx . hir ( ) )
543+ }
544+
545+ fn visit_ty ( & mut self , arg : & ' tcx hir:: Ty < ' tcx > ) {
546+ match arg. kind {
547+ hir:: TyKind :: Path ( hir:: QPath :: Resolved ( None , path) ) => match & path. segments {
548+ [ PathSegment { res : Some ( Res :: SelfTy ( _, impl_ref) ) , .. } ] => {
549+ let impl_ty_name =
550+ impl_ref. map ( |( def_id, _) | self . tcx . def_path_str ( def_id) ) ;
551+ self . selftys . push ( ( path. span , impl_ty_name) ) ;
552+ }
553+ _ => { }
554+ } ,
555+ _ => { }
556+ }
557+ hir:: intravisit:: walk_ty ( self , arg) ;
558+ }
559+ }
560+
536561 if let ItemKind :: OpaqueTy ( hir:: OpaqueTy {
537562 origin : hir:: OpaqueTyOrigin :: AsyncFn | hir:: OpaqueTyOrigin :: FnReturn ,
538563 ..
@@ -544,17 +569,20 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
544569 InternalSubsts :: identity_for_item ( tcx, def_id. to_def_id ( ) ) ,
545570 ) ,
546571 generics : tcx. generics_of ( def_id) ,
572+ tcx,
573+ selftys : vec ! [ ] ,
547574 } ;
548575 let prohibit_opaque = tcx
549576 . explicit_item_bounds ( def_id)
550577 . iter ( )
551578 . try_for_each ( |( predicate, _) | predicate. visit_with ( & mut visitor) ) ;
552579 debug ! (
553- "check_opaque_for_inheriting_lifetimes: prohibit_opaque={:?}, visitor={:?}" ,
554- prohibit_opaque, visitor
580+ "check_opaque_for_inheriting_lifetimes: prohibit_opaque={:?}, visitor.opaque_identity_ty={:?}, visitor.generics ={:?}" ,
581+ prohibit_opaque, visitor. opaque_identity_ty , visitor . generics
555582 ) ;
556583
557584 if let Some ( ty) = prohibit_opaque. break_value ( ) {
585+ visitor. visit_item ( & item) ;
558586 let is_async = match item. kind {
559587 ItemKind :: OpaqueTy ( hir:: OpaqueTy { origin, .. } ) => {
560588 matches ! ( origin, hir:: OpaqueTyOrigin :: AsyncFn )
@@ -571,15 +599,13 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
571599 if is_async { "async fn" } else { "impl Trait" } ,
572600 ) ;
573601
574- if let Ok ( snippet) = tcx. sess . source_map ( ) . span_to_snippet ( span) {
575- if snippet == "Self" {
576- err. span_suggestion (
577- span,
578- "consider spelling out the type instead" ,
579- format ! ( "{:?}" , ty) ,
580- Applicability :: MaybeIncorrect ,
581- ) ;
582- }
602+ for ( span, name) in visitor. selftys {
603+ err. span_suggestion (
604+ span,
605+ "consider spelling out the type instead" ,
606+ name. unwrap_or_else ( || format ! ( "{:?}" , ty) ) ,
607+ Applicability :: MaybeIncorrect ,
608+ ) ;
583609 }
584610 err. emit ( ) ;
585611 }
0 commit comments