@@ -7,6 +7,7 @@ use crate::{PathResult, PathSource, Segment};
7
7
8
8
use rustc_ast:: ast:: { self , Expr , ExprKind , Item , ItemKind , NodeId , Path , Ty , TyKind } ;
9
9
use rustc_ast:: util:: lev_distance:: find_best_match_for_name;
10
+ use rustc_ast:: visit:: FnKind ;
10
11
use rustc_data_structures:: fx:: FxHashSet ;
11
12
use rustc_errors:: { pluralize, struct_span_err, Applicability , DiagnosticBuilder } ;
12
13
use rustc_hir as hir;
@@ -175,16 +176,40 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
175
176
let code = source. error_code ( res. is_some ( ) ) ;
176
177
let mut err = self . r . session . struct_span_err_with_code ( base_span, & base_msg, code) ;
177
178
179
+ let is_assoc_fn = self . self_type_is_available ( span) ;
178
180
// 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 {
182
182
err. span_suggestion_short (
183
183
span,
184
184
"you might have meant to use `self` here instead" ,
185
185
"self" . to_string ( ) ,
186
186
Applicability :: MaybeIncorrect ,
187
187
) ;
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
+ }
188
213
}
189
214
190
215
// Emit special messages for unresolved `Self` and `self`.
@@ -213,7 +238,38 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
213
238
if fn_kind. decl ( ) . inputs . get ( 0 ) . map ( |p| p. is_self ( ) ) . unwrap_or ( false ) {
214
239
err. span_label ( * span, "this function has a `self` parameter, but a macro invocation can only access identifiers it receives from parameters" ) ;
215
240
} 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
+ }
217
273
}
218
274
}
219
275
return ( err, Vec :: new ( ) ) ;
0 commit comments