@@ -26,7 +26,7 @@ use rustc_middle::ty::{
2626    TypeFoldable ,  WithConstness , 
2727} ; 
2828use  rustc_session:: DiagnosticMessageId ; 
29- use  rustc_span:: { ExpnKind ,  Span ,  DUMMY_SP } ; 
29+ use  rustc_span:: { ExpnKind ,  MultiSpan ,   Span ,  DUMMY_SP } ; 
3030use  std:: fmt; 
3131
3232use  crate :: traits:: query:: evaluate_obligation:: InferCtxtExt  as  _; 
@@ -1740,10 +1740,36 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
17401740                    // Suggesting `T: ?Sized` is only valid in an ADT if `T` is only used in a 
17411741                    // borrow. `struct S<'a, T: ?Sized>(&'a T);` is valid, `struct S<T: ?Sized>(T);` 
17421742                    // is not. 
1743-                     let  mut  visitor = FindTypeParam  {  param :  param. name . ident ( ) . name ,  valid :  true  } ; 
1743+                     let  mut  visitor = FindTypeParam  { 
1744+                         param :  param. name . ident ( ) . name , 
1745+                         invalid_spans :  vec ! [ ] , 
1746+                         nested :  false , 
1747+                     } ; 
17441748                    visitor. visit_item ( item) ; 
1745-                     if  !visitor. valid  { 
1746-                         continue ; 
1749+                     if  !visitor. invalid_spans . is_empty ( )  { 
1750+                         let  mut  multispan:  MultiSpan  = param. span . into ( ) ; 
1751+                         multispan. push_span_label ( 
1752+                             param. span , 
1753+                             format ! ( "this could be changed to `{}: ?Sized`..." ,  param. name. ident( ) ) , 
1754+                         ) ; 
1755+                         for  sp in  visitor. invalid_spans  { 
1756+                             multispan. push_span_label ( 
1757+                                 sp, 
1758+                                 format ! ( 
1759+                                     "...if indirection was used here: `Box<{}>`" , 
1760+                                     param. name. ident( ) , 
1761+                                 ) , 
1762+                             ) ; 
1763+                         } 
1764+                         err. span_help ( 
1765+                             multispan, 
1766+                             & format ! ( 
1767+                                 "you could relax the implicit `Sized` bound on `{T}` if it were \  
1768+                                   used through indirection like `&{T}` or `Box<{T}>`", 
1769+                                 T  = param. name. ident( ) , 
1770+                             ) , 
1771+                         ) ; 
1772+                         return ; 
17471773                    } 
17481774                } 
17491775                _ => { } 
@@ -1782,7 +1808,8 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
17821808/// `param: ?Sized` would be a valid constraint. 
17831809struct  FindTypeParam  { 
17841810    param :  rustc_span:: Symbol , 
1785-     valid :  bool , 
1811+     invalid_spans :  Vec < Span > , 
1812+     nested :  bool , 
17861813} 
17871814
17881815impl < ' v >  Visitor < ' v >  for  FindTypeParam  { 
@@ -1794,15 +1821,24 @@ impl<'v> Visitor<'v> for FindTypeParam {
17941821
17951822    fn  visit_ty ( & mut  self ,  ty :  & hir:: Ty < ' _ > )  { 
17961823        match  ty. kind  { 
1797-             hir:: TyKind :: Ptr ( _)  | hir:: TyKind :: Rptr ( ..)  | hir:: TyKind :: TraitObject ( ..)  => return , 
1824+             hir:: TyKind :: Ptr ( _)  | hir:: TyKind :: Rptr ( ..)  | hir:: TyKind :: TraitObject ( ..)  => { } 
17981825            hir:: TyKind :: Path ( hir:: QPath :: Resolved ( None ,  path) ) 
17991826                if  path. segments . len ( )  == 1  && path. segments [ 0 ] . ident . name  == self . param  =>
18001827            { 
1801-                 self . valid  = false ; 
1828+                 if  !self . nested  { 
1829+                     self . invalid_spans . push ( ty. span ) ; 
1830+                 } 
1831+             } 
1832+             hir:: TyKind :: Path ( _)  => { 
1833+                 let  prev = self . nested ; 
1834+                 self . nested  = true ; 
1835+                 hir:: intravisit:: walk_ty ( self ,  ty) ; 
1836+                 self . nested  = prev; 
1837+             } 
1838+             _ => { 
1839+                 hir:: intravisit:: walk_ty ( self ,  ty) ; 
18021840            } 
1803-             _ => { } 
18041841        } 
1805-         hir:: intravisit:: walk_ty ( self ,  ty) ; 
18061842    } 
18071843} 
18081844
0 commit comments