@@ -41,7 +41,7 @@ use rustc::ty;
4141use  rustc:: hir:: { Freevar ,  FreevarMap ,  TraitCandidate ,  TraitMap ,  GlobMap } ; 
4242use  rustc:: util:: nodemap:: { NodeMap ,  NodeSet ,  FxHashMap ,  FxHashSet ,  DefIdMap } ; 
4343
44- use  syntax:: codemap:: { dummy_spanned,  respan,  CodeMap } ; 
44+ use  syntax:: codemap:: { dummy_spanned,  respan,  BytePos ,   CodeMap } ; 
4545use  syntax:: ext:: hygiene:: { Mark ,  MarkKind ,  SyntaxContext } ; 
4646use  syntax:: ast:: { self ,  Name ,  NodeId ,  Ident ,  SpannedIdent ,  FloatTy ,  IntTy ,  UintTy } ; 
4747use  syntax:: ext:: base:: SyntaxExtension ; 
@@ -179,11 +179,12 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver,
179179                                           E0401 , 
180180                                           "can't use type parameters from outer function" ) ; 
181181            err. span_label ( span,  "use of type variable from outer function" ) ; 
182+ 
183+             let  cm = resolver. session . codemap ( ) ; 
182184            match  outer_def { 
183185                Def :: SelfTy ( _,  maybe_impl_defid)  => { 
184186                    if  let  Some ( impl_span)  = maybe_impl_defid. map_or ( None , 
185187                            |def_id| resolver. definitions . opt_span ( def_id) )  { 
186-                         let  cm = resolver. session . codemap ( ) ; 
187188                        err. span_label ( reduce_impl_span_to_impl_keyword ( cm,  impl_span) , 
188189                                    "`Self` type implicitely declared here, on the `impl`" ) ; 
189190                    } 
@@ -206,12 +207,13 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver,
206207            // Try to retrieve the span of the function signature and generate a new message with 
207208            // a local type parameter 
208209            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)  { 
211211                // Suggest the modification to the user 
212212                err. span_suggestion ( sugg_span, 
213213                                    sugg_msg, 
214214                                    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" ) ; 
215217            }  else  { 
216218                err. help ( "try using a local type parameter instead" ) ; 
217219            } 
@@ -407,6 +409,15 @@ fn reduce_impl_span_to_impl_keyword(cm: &CodeMap, impl_span: Span) -> Span {
407409    impl_span
408410} 
409411
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+ 
410421/// Take the span of a type parameter in a function signature and try to generate a span for the 
411422/// function name (with generics) and a new snippet for this span with the pointed type parameter as 
412423/// a new local type parameter. 
@@ -428,17 +439,12 @@ fn reduce_impl_span_to_impl_keyword(cm: &CodeMap, impl_span: Span) -> Span {
428439fn  generate_local_type_param_snippet ( cm :  & CodeMap ,  span :  Span )  -> Option < ( Span ,  String ) >  { 
429440    // Try to extend the span to the previous "fn" keyword to retrieve the function 
430441    // 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 ) ; 
432443    if  sugg_span != span { 
433444        if  let  Ok ( snippet)  = cm. span_to_snippet ( sugg_span)  { 
434-             use  syntax:: codemap:: BytePos ; 
435- 
436445            // 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" ) ; 
442448
443449            // Consume the generics part of the function signature 
444450            let  mut  bracket_counter = 0 ; 
0 commit comments