@@ -1623,12 +1623,17 @@ fn check_opaque_for_inheriting_lifetimes(tcx: TyCtxt<'tcx>, def_id: LocalDefId,
16231623 struct ProhibitOpaqueVisitor < ' tcx > {
16241624 opaque_identity_ty : Ty < ' tcx > ,
16251625 generics : & ' tcx ty:: Generics ,
1626+ ty : Option < Ty < ' tcx > > ,
16261627 } ;
16271628
16281629 impl < ' tcx > ty:: fold:: TypeVisitor < ' tcx > for ProhibitOpaqueVisitor < ' tcx > {
16291630 fn visit_ty ( & mut self , t : Ty < ' tcx > ) -> bool {
16301631 debug ! ( "check_opaque_for_inheriting_lifetimes: (visit_ty) t={:?}" , t) ;
1631- if t == self . opaque_identity_ty { false } else { t. super_visit_with ( self ) }
1632+ if t != self . opaque_identity_ty && t. super_visit_with ( self ) {
1633+ self . ty = Some ( t) ;
1634+ return true ;
1635+ }
1636+ false
16321637 }
16331638
16341639 fn visit_region ( & mut self , r : ty:: Region < ' tcx > ) -> bool {
@@ -1651,46 +1656,61 @@ fn check_opaque_for_inheriting_lifetimes(tcx: TyCtxt<'tcx>, def_id: LocalDefId,
16511656 }
16521657 }
16531658
1654- let prohibit_opaque = match item. kind {
1655- ItemKind :: OpaqueTy ( hir:: OpaqueTy {
1656- origin : hir:: OpaqueTyOrigin :: AsyncFn | hir:: OpaqueTyOrigin :: FnReturn ,
1657- ..
1658- } ) => {
1659- let mut visitor = ProhibitOpaqueVisitor {
1660- opaque_identity_ty : tcx. mk_opaque (
1661- def_id. to_def_id ( ) ,
1662- InternalSubsts :: identity_for_item ( tcx, def_id. to_def_id ( ) ) ,
1663- ) ,
1664- generics : tcx. generics_of ( def_id) ,
1665- } ;
1666- debug ! ( "check_opaque_for_inheriting_lifetimes: visitor={:?}" , visitor) ;
1667-
1668- tcx. predicates_of ( def_id)
1669- . predicates
1670- . iter ( )
1671- . any ( |( predicate, _) | predicate. visit_with ( & mut visitor) )
1672- }
1673- _ => false ,
1674- } ;
1675-
1676- debug ! ( "check_opaque_for_inheriting_lifetimes: prohibit_opaque={:?}" , prohibit_opaque) ;
1677- if prohibit_opaque {
1678- let is_async = match item. kind {
1679- ItemKind :: OpaqueTy ( hir:: OpaqueTy { origin, .. } ) => match origin {
1680- hir:: OpaqueTyOrigin :: AsyncFn => true ,
1681- _ => false ,
1682- } ,
1683- _ => unreachable ! ( ) ,
1659+ if let ItemKind :: OpaqueTy ( hir:: OpaqueTy {
1660+ origin : hir:: OpaqueTyOrigin :: AsyncFn | hir:: OpaqueTyOrigin :: FnReturn ,
1661+ ..
1662+ } ) = item. kind
1663+ {
1664+ let mut visitor = ProhibitOpaqueVisitor {
1665+ opaque_identity_ty : tcx. mk_opaque (
1666+ def_id. to_def_id ( ) ,
1667+ InternalSubsts :: identity_for_item ( tcx, def_id. to_def_id ( ) ) ,
1668+ ) ,
1669+ generics : tcx. generics_of ( def_id) ,
1670+ ty : None ,
16841671 } ;
1672+ let prohibit_opaque = tcx
1673+ . predicates_of ( def_id)
1674+ . predicates
1675+ . iter ( )
1676+ . any ( |( predicate, _) | predicate. visit_with ( & mut visitor) ) ;
1677+ debug ! (
1678+ "check_opaque_for_inheriting_lifetimes: prohibit_opaque={:?}, visitor={:?}" ,
1679+ prohibit_opaque, visitor
1680+ ) ;
16851681
1686- tcx. sess . span_err (
1687- span,
1688- & format ! (
1689- "`{}` return type cannot contain a projection or `Self` that references lifetimes from \
1682+ if prohibit_opaque {
1683+ let is_async = match item. kind {
1684+ ItemKind :: OpaqueTy ( hir:: OpaqueTy { origin, .. } ) => match origin {
1685+ hir:: OpaqueTyOrigin :: AsyncFn => true ,
1686+ _ => false ,
1687+ } ,
1688+ _ => unreachable ! ( ) ,
1689+ } ;
1690+
1691+ let mut err = struct_span_err ! (
1692+ tcx. sess,
1693+ span,
1694+ E0760 ,
1695+ "`{}` return type cannot contain a projection or `Self` that references lifetimes from \
16901696 a parent scope",
1691- if is_async { "async fn" } else { "impl Trait" } ,
1692- ) ,
1693- ) ;
1697+ if is_async { "async fn" } else { "impl Trait" } ,
1698+ ) ;
1699+
1700+ if let Ok ( snippet) = tcx. sess . source_map ( ) . span_to_snippet ( span) {
1701+ if snippet == "Self" {
1702+ if let Some ( ty) = visitor. ty {
1703+ err. span_suggestion (
1704+ span,
1705+ "consider spelling out the type instead" ,
1706+ format ! ( "{:?}" , ty) ,
1707+ Applicability :: MaybeIncorrect ,
1708+ ) ;
1709+ }
1710+ }
1711+ }
1712+ err. emit ( ) ;
1713+ }
16941714 }
16951715}
16961716
0 commit comments