@@ -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