@@ -41,7 +41,7 @@ use rustc::ty;
41
41
use rustc:: hir:: { Freevar , FreevarMap , TraitCandidate , TraitMap , GlobMap } ;
42
42
use rustc:: util:: nodemap:: { NodeMap , NodeSet , FxHashMap , FxHashSet , DefIdMap } ;
43
43
44
- use syntax:: codemap:: { dummy_spanned, respan, CodeMap } ;
44
+ use syntax:: codemap:: { dummy_spanned, respan, BytePos , CodeMap } ;
45
45
use syntax:: ext:: hygiene:: { Mark , MarkKind , SyntaxContext } ;
46
46
use syntax:: ast:: { self , Name , NodeId , Ident , SpannedIdent , FloatTy , IntTy , UintTy } ;
47
47
use syntax:: ext:: base:: SyntaxExtension ;
@@ -179,11 +179,12 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver,
179
179
E0401 ,
180
180
"can't use type parameters from outer function" ) ;
181
181
err. span_label ( span, "use of type variable from outer function" ) ;
182
+
183
+ let cm = resolver. session . codemap ( ) ;
182
184
match outer_def {
183
185
Def :: SelfTy ( _, maybe_impl_defid) => {
184
186
if let Some ( impl_span) = maybe_impl_defid. map_or ( None ,
185
187
|def_id| resolver. definitions . opt_span ( def_id) ) {
186
- let cm = resolver. session . codemap ( ) ;
187
188
err. span_label ( reduce_impl_span_to_impl_keyword ( cm, impl_span) ,
188
189
"`Self` type implicitely declared here, on the `impl`" ) ;
189
190
}
@@ -206,12 +207,13 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver,
206
207
// Try to retrieve the span of the function signature and generate a new message with
207
208
// a local type parameter
208
209
let sugg_msg = "try using a local type parameter instead" ;
209
- if let Some ( ( sugg_span, new_snippet) ) = generate_local_type_param_snippet (
210
- resolver. session . codemap ( ) , span) {
210
+ if let Some ( ( sugg_span, new_snippet) ) = generate_local_type_param_snippet ( cm, span) {
211
211
// Suggest the modification to the user
212
212
err. span_suggestion ( sugg_span,
213
213
sugg_msg,
214
214
new_snippet) ;
215
+ } else if let Some ( sp) = generate_fn_name_span ( cm, span) {
216
+ err. span_label ( sp, "try adding a local type parameter in this method instead" ) ;
215
217
} else {
216
218
err. help ( "try using a local type parameter instead" ) ;
217
219
}
@@ -407,6 +409,15 @@ fn reduce_impl_span_to_impl_keyword(cm: &CodeMap, impl_span: Span) -> Span {
407
409
impl_span
408
410
}
409
411
412
+ fn generate_fn_name_span ( cm : & CodeMap , span : Span ) -> Option < Span > {
413
+ let prev_span = cm. span_extend_to_prev_str ( span, "fn" , true ) ;
414
+ cm. span_to_snippet ( prev_span) . map ( |snippet| {
415
+ let len = snippet. find ( |c : char | !c. is_alphanumeric ( ) && c != '_' )
416
+ . expect ( "no label after fn" ) ;
417
+ prev_span. with_hi ( BytePos ( prev_span. lo ( ) . 0 + len as u32 ) )
418
+ } ) . ok ( )
419
+ }
420
+
410
421
/// Take the span of a type parameter in a function signature and try to generate a span for the
411
422
/// function name (with generics) and a new snippet for this span with the pointed type parameter as
412
423
/// a new local type parameter.
@@ -428,17 +439,12 @@ fn reduce_impl_span_to_impl_keyword(cm: &CodeMap, impl_span: Span) -> Span {
428
439
fn generate_local_type_param_snippet ( cm : & CodeMap , span : Span ) -> Option < ( Span , String ) > {
429
440
// Try to extend the span to the previous "fn" keyword to retrieve the function
430
441
// signature
431
- let sugg_span = cm. span_extend_to_prev_str ( span, "fn" ) ;
442
+ let sugg_span = cm. span_extend_to_prev_str ( span, "fn" , false ) ;
432
443
if sugg_span != span {
433
444
if let Ok ( snippet) = cm. span_to_snippet ( sugg_span) {
434
- use syntax:: codemap:: BytePos ;
435
-
436
445
// Consume the function name
437
- let mut offset = 0 ;
438
- for c in snippet. chars ( ) . take_while ( |c| c. is_ascii_alphanumeric ( ) ||
439
- * c == '_' ) {
440
- offset += c. len_utf8 ( ) ;
441
- }
446
+ let mut offset = snippet. find ( |c : char | !c. is_alphanumeric ( ) && c != '_' )
447
+ . expect ( "no label after fn" ) ;
442
448
443
449
// Consume the generics part of the function signature
444
450
let mut bracket_counter = 0 ;
0 commit comments