@@ -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