@@ -7,6 +7,7 @@ use crate::{PathResult, PathSource, Segment};
77
88use rustc_ast:: ast:: { self , Expr , ExprKind , Item , ItemKind , NodeId , Path , Ty , TyKind } ;
99use rustc_ast:: util:: lev_distance:: find_best_match_for_name;
10+ use rustc_ast:: visit:: FnKind ;
1011use rustc_data_structures:: fx:: FxHashSet ;
1112use rustc_errors:: { pluralize, struct_span_err, Applicability , DiagnosticBuilder } ;
1213use rustc_hir as hir;
@@ -175,16 +176,40 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
175176 let code = source. error_code ( res. is_some ( ) ) ;
176177 let mut err = self . r . session . struct_span_err_with_code ( base_span, & base_msg, code) ;
177178
179+ let is_assoc_fn = self . self_type_is_available ( span) ;
178180 // Emit help message for fake-self from other languages (e.g., `this` in Javascript).
179- if [ "this" , "my" ] . contains ( & & * item_str. as_str ( ) )
180- && self . self_value_is_available ( path[ 0 ] . ident . span , span)
181- {
181+ if [ "this" , "my" ] . contains ( & & * item_str. as_str ( ) ) && is_assoc_fn {
182182 err. span_suggestion_short (
183183 span,
184184 "you might have meant to use `self` here instead" ,
185185 "self" . to_string ( ) ,
186186 Applicability :: MaybeIncorrect ,
187187 ) ;
188+ if !self . self_value_is_available ( path[ 0 ] . ident . span , span) {
189+ if let Some ( ( FnKind :: Fn ( _, _, sig, ..) , fn_span) ) =
190+ & self . diagnostic_metadata . current_function
191+ {
192+ let ( span, sugg) = if let Some ( param) = sig. decl . inputs . get ( 0 ) {
193+ ( param. span . shrink_to_lo ( ) , "&self, " )
194+ } else {
195+ (
196+ self . r
197+ . session
198+ . source_map ( )
199+ . span_through_char ( * fn_span, '(' )
200+ . shrink_to_hi ( ) ,
201+ "&self" ,
202+ )
203+ } ;
204+ err. span_suggestion_verbose (
205+ span,
206+ "if you meant to use `self`, you are also missing a `self` receiver \
207+ argument",
208+ sugg. to_string ( ) ,
209+ Applicability :: MaybeIncorrect ,
210+ ) ;
211+ }
212+ }
188213 }
189214
190215 // Emit special messages for unresolved `Self` and `self`.
@@ -213,7 +238,38 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
213238 if fn_kind. decl ( ) . inputs . get ( 0 ) . map ( |p| p. is_self ( ) ) . unwrap_or ( false ) {
214239 err. span_label ( * span, "this function has a `self` parameter, but a macro invocation can only access identifiers it receives from parameters" ) ;
215240 } else {
216- err. span_label ( * span, "this function doesn't have a `self` parameter" ) ;
241+ let doesnt = if is_assoc_fn {
242+ let ( span, sugg) = fn_kind
243+ . decl ( )
244+ . inputs
245+ . get ( 0 )
246+ . map ( |p| ( p. span . shrink_to_lo ( ) , "&self, " ) )
247+ . unwrap_or_else ( || {
248+ (
249+ self . r
250+ . session
251+ . source_map ( )
252+ . span_through_char ( * span, '(' )
253+ . shrink_to_hi ( ) ,
254+ "&self" ,
255+ )
256+ } ) ;
257+ err. span_suggestion_verbose (
258+ span,
259+ "add a `self` receiver parameter to make the associated `fn` a method" ,
260+ sugg. to_string ( ) ,
261+ Applicability :: MaybeIncorrect ,
262+ ) ;
263+ "doesn't"
264+ } else {
265+ "can't"
266+ } ;
267+ if let Some ( ident) = fn_kind. ident ( ) {
268+ err. span_label (
269+ ident. span ,
270+ & format ! ( "this function {} have a `self` parameter" , doesnt) ,
271+ ) ;
272+ }
217273 }
218274 }
219275 return ( err, Vec :: new ( ) ) ;
0 commit comments