@@ -43,12 +43,9 @@ pub enum ObjectSafetyViolation {
4343impl ObjectSafetyViolation {
4444 pub fn error_msg ( & self ) -> Cow < ' static , str > {
4545 match * self {
46- ObjectSafetyViolation :: SizedSelf ( _) => {
47- "traits that require `Self: Sized` cannot be made into an object" . into ( )
48- }
46+ ObjectSafetyViolation :: SizedSelf ( _) => "it requires `Self: Sized`" . into ( ) ,
4947 ObjectSafetyViolation :: SupertraitSelf => {
50- "the trait cannot use `Self` as a type parameter \
51- in the supertraits or where-clauses"
48+ "it cannot use `Self` as a type parameter in the supertraits or `where`-clauses"
5249 . into ( )
5350 }
5451 ObjectSafetyViolation :: Method ( name, MethodViolationCode :: StaticMethod , _) => {
@@ -63,19 +60,45 @@ impl ObjectSafetyViolation {
6360 name,
6461 MethodViolationCode :: WhereClauseReferencesSelf ,
6562 _,
66- ) => format ! ( "method `{}` references the `Self` type in where clauses" , name) . into ( ) ,
63+ ) => {
64+ format ! ( "method `{}` references the `Self` type in its `where` clause" , name) . into ( )
65+ }
6766 ObjectSafetyViolation :: Method ( name, MethodViolationCode :: Generic , _) => {
6867 format ! ( "method `{}` has generic type parameters" , name) . into ( )
6968 }
7069 ObjectSafetyViolation :: Method ( name, MethodViolationCode :: UndispatchableReceiver , _) => {
7170 format ! ( "method `{}`'s `self` parameter cannot be dispatched on" , name) . into ( )
7271 }
72+ ObjectSafetyViolation :: AssocConst ( _, DUMMY_SP ) => {
73+ "it cannot contain associated consts" . into ( )
74+ }
7375 ObjectSafetyViolation :: AssocConst ( name, _) => {
74- format ! ( "the trait cannot contain associated consts like `{}`" , name) . into ( )
76+ format ! ( "it cannot contain associated consts like `{}`" , name) . into ( )
7577 }
7678 }
7779 }
7880
81+ pub fn solution ( & self ) -> Option < String > {
82+ Some ( match * self {
83+ ObjectSafetyViolation :: SizedSelf ( _) | ObjectSafetyViolation :: SupertraitSelf => {
84+ return None ;
85+ }
86+ ObjectSafetyViolation :: Method ( name, MethodViolationCode :: StaticMethod , _) => format ! (
87+ "consider turning `{}` into a method by giving it a `&self` argument or \
88+ constraining it with `where Self: Sized`",
89+ name
90+ ) ,
91+ ObjectSafetyViolation :: Method ( name, MethodViolationCode :: UndispatchableReceiver , _) => {
92+ format ! ( "consider changing method `{}`'s `self` parameter to be `&self`" , name)
93+ . into ( )
94+ }
95+ ObjectSafetyViolation :: AssocConst ( name, _)
96+ | ObjectSafetyViolation :: Method ( name, ..) => {
97+ format ! ( "consider moving `{}` to another trait" , name)
98+ }
99+ } )
100+ }
101+
79102 pub fn spans ( & self ) -> SmallVec < [ Span ; 1 ] > {
80103 // When `span` comes from a separate crate, it'll be `DUMMY_SP`. Treat it as `None` so
81104 // diagnostics use a `note` instead of a `span_label`.
@@ -190,7 +213,21 @@ fn object_safety_violations_for_trait(
190213 tcx. def_path_str( trait_def_id)
191214 ) ,
192215 ) ;
193- err. span_label ( * span, violation. error_msg ( ) ) ;
216+ let node = tcx. hir ( ) . get_if_local ( trait_def_id) ;
217+ let msg = if let Some ( hir:: Node :: Item ( item) ) = node {
218+ err. span_label ( item. ident . span , "this trait cannot be made into an object..." ) ;
219+ format ! ( "...because {}" , violation. error_msg( ) )
220+ } else {
221+ format ! (
222+ "the trait cannot be made into an object because {}" ,
223+ violation. error_msg( )
224+ )
225+ } ;
226+ err. span_label ( * span, & msg) ;
227+ if let ( Some ( _) , Some ( note) ) = ( node, violation. solution ( ) ) {
228+ // Only provide the help if its a local trait, otherwise it's not actionable.
229+ err. help ( & note) ;
230+ }
194231 err. emit ( ) ;
195232 false
196233 } else {
0 commit comments