@@ -1632,12 +1632,17 @@ fn check_opaque_for_inheriting_lifetimes(tcx: TyCtxt<'tcx>, def_id: LocalDefId,
16321632 struct ProhibitOpaqueVisitor < ' tcx > {
16331633 opaque_identity_ty : Ty < ' tcx > ,
16341634 generics : & ' tcx ty:: Generics ,
1635+ ty : Option < Ty < ' tcx > > ,
16351636 } ;
16361637
16371638 impl < ' tcx > ty:: fold:: TypeVisitor < ' tcx > for ProhibitOpaqueVisitor < ' tcx > {
16381639 fn visit_ty ( & mut self , t : Ty < ' tcx > ) -> bool {
16391640 debug ! ( "check_opaque_for_inheriting_lifetimes: (visit_ty) t={:?}" , t) ;
1640- if t == self . opaque_identity_ty { false } else { t. super_visit_with ( self ) }
1641+ if t != self . opaque_identity_ty && t. super_visit_with ( self ) {
1642+ self . ty = Some ( t) ;
1643+ return true ;
1644+ }
1645+ false
16411646 }
16421647
16431648 fn visit_region ( & mut self , r : ty:: Region < ' tcx > ) -> bool {
@@ -1660,46 +1665,61 @@ fn check_opaque_for_inheriting_lifetimes(tcx: TyCtxt<'tcx>, def_id: LocalDefId,
16601665 }
16611666 }
16621667
1663- let prohibit_opaque = match item. kind {
1664- ItemKind :: OpaqueTy ( hir:: OpaqueTy {
1665- origin : hir:: OpaqueTyOrigin :: AsyncFn | hir:: OpaqueTyOrigin :: FnReturn ,
1666- ..
1667- } ) => {
1668- let mut visitor = ProhibitOpaqueVisitor {
1669- opaque_identity_ty : tcx. mk_opaque (
1670- def_id. to_def_id ( ) ,
1671- InternalSubsts :: identity_for_item ( tcx, def_id. to_def_id ( ) ) ,
1672- ) ,
1673- generics : tcx. generics_of ( def_id) ,
1674- } ;
1675- debug ! ( "check_opaque_for_inheriting_lifetimes: visitor={:?}" , visitor) ;
1676-
1677- tcx. predicates_of ( def_id)
1678- . predicates
1679- . iter ( )
1680- . any ( |( predicate, _) | predicate. visit_with ( & mut visitor) )
1681- }
1682- _ => false ,
1683- } ;
1684-
1685- debug ! ( "check_opaque_for_inheriting_lifetimes: prohibit_opaque={:?}" , prohibit_opaque) ;
1686- if prohibit_opaque {
1687- let is_async = match item. kind {
1688- ItemKind :: OpaqueTy ( hir:: OpaqueTy { origin, .. } ) => match origin {
1689- hir:: OpaqueTyOrigin :: AsyncFn => true ,
1690- _ => false ,
1691- } ,
1692- _ => unreachable ! ( ) ,
1668+ if let ItemKind :: OpaqueTy ( hir:: OpaqueTy {
1669+ origin : hir:: OpaqueTyOrigin :: AsyncFn | hir:: OpaqueTyOrigin :: FnReturn ,
1670+ ..
1671+ } ) = item. kind
1672+ {
1673+ let mut visitor = ProhibitOpaqueVisitor {
1674+ opaque_identity_ty : tcx. mk_opaque (
1675+ def_id. to_def_id ( ) ,
1676+ InternalSubsts :: identity_for_item ( tcx, def_id. to_def_id ( ) ) ,
1677+ ) ,
1678+ generics : tcx. generics_of ( def_id) ,
1679+ ty : None ,
16931680 } ;
1681+ let prohibit_opaque = tcx
1682+ . predicates_of ( def_id)
1683+ . predicates
1684+ . iter ( )
1685+ . any ( |( predicate, _) | predicate. visit_with ( & mut visitor) ) ;
1686+ debug ! (
1687+ "check_opaque_for_inheriting_lifetimes: prohibit_opaque={:?}, visitor={:?}" ,
1688+ prohibit_opaque, visitor
1689+ ) ;
16941690
1695- tcx. sess . span_err (
1696- span,
1697- & format ! (
1698- "`{}` return type cannot contain a projection or `Self` that references lifetimes from \
1691+ if prohibit_opaque {
1692+ let is_async = match item. kind {
1693+ ItemKind :: OpaqueTy ( hir:: OpaqueTy { origin, .. } ) => match origin {
1694+ hir:: OpaqueTyOrigin :: AsyncFn => true ,
1695+ _ => false ,
1696+ } ,
1697+ _ => unreachable ! ( ) ,
1698+ } ;
1699+
1700+ let mut err = struct_span_err ! (
1701+ tcx. sess,
1702+ span,
1703+ E0755 ,
1704+ "`{}` return type cannot contain a projection or `Self` that references lifetimes from \
16991705 a parent scope",
1700- if is_async { "async fn" } else { "impl Trait" } ,
1701- ) ,
1702- ) ;
1706+ if is_async { "async fn" } else { "impl Trait" } ,
1707+ ) ;
1708+
1709+ if let Ok ( snippet) = tcx. sess . source_map ( ) . span_to_snippet ( span) {
1710+ if snippet == "Self" {
1711+ if let Some ( ty) = visitor. ty {
1712+ err. span_suggestion (
1713+ span,
1714+ "consider spelling out the type instead" ,
1715+ format ! ( "{:?}" , ty) ,
1716+ Applicability :: MaybeIncorrect ,
1717+ ) ;
1718+ }
1719+ }
1720+ }
1721+ err. emit ( ) ;
1722+ }
17031723 }
17041724}
17051725
0 commit comments