@@ -605,7 +605,7 @@ impl<'tcx> Visitor<'tcx> for UsePlacementFinder {
605605 ItemKind :: Use ( ..) => {
606606 // don't suggest placing a use before the prelude
607607 // import or other generated ones
608- if item. span == DUMMY_SP {
608+ if item. span . ctxt ( ) . outer ( ) . expn_info ( ) . is_none ( ) {
609609 self . span = Some ( item. span . with_hi ( item. span . lo ( ) ) ) ;
610610 self . found_use = true ;
611611 return ;
@@ -615,11 +615,22 @@ impl<'tcx> Visitor<'tcx> for UsePlacementFinder {
615615 ItemKind :: ExternCrate ( _) => { }
616616 // but place them before the first other item
617617 _ => if self . span . map_or ( true , |span| item. span < span ) {
618- self . span = Some ( item. span . with_hi ( item. span . lo ( ) ) ) ;
618+ if item. span . ctxt ( ) . outer ( ) . expn_info ( ) . is_none ( ) {
619+ // don't insert between attributes and an item
620+ if item. attrs . is_empty ( ) {
621+ self . span = Some ( item. span . with_hi ( item. span . lo ( ) ) ) ;
622+ } else {
623+ // find the first attribute on the item
624+ for attr in & item. attrs {
625+ if self . span . map_or ( true , |span| attr. span < span) {
626+ self . span = Some ( attr. span . with_hi ( attr. span . lo ( ) ) ) ;
627+ }
628+ }
629+ }
630+ }
619631 } ,
620632 }
621633 }
622- assert ! ( self . span. is_some( ) , "a file can't have no items and emit suggestions" ) ;
623634 }
624635}
625636
@@ -3553,8 +3564,7 @@ impl<'a> Resolver<'a> {
35533564 } ;
35543565 visit:: walk_crate ( & mut finder, krate) ;
35553566 if !candidates. is_empty ( ) {
3556- let span = finder. span . expect ( "did not find module" ) ;
3557- show_candidates ( & mut err, span, & candidates, better, finder. found_use ) ;
3567+ show_candidates ( & mut err, finder. span , & candidates, better, finder. found_use ) ;
35583568 }
35593569 err. emit ( ) ;
35603570 }
@@ -3748,7 +3758,8 @@ fn import_candidate_to_paths(suggestion: &ImportSuggestion) -> (Span, String, St
37483758/// entities with that name in all crates. This method allows outputting the
37493759/// results of this search in a programmer-friendly way
37503760fn show_candidates ( err : & mut DiagnosticBuilder ,
3751- span : Span ,
3761+ // This is `None` if all placement locations are inside expansions
3762+ span : Option < Span > ,
37523763 candidates : & [ ImportSuggestion ] ,
37533764 better : bool ,
37543765 found_use : bool ) {
@@ -3766,18 +3777,27 @@ fn show_candidates(err: &mut DiagnosticBuilder,
37663777 } ;
37673778 let msg = format ! ( "possible {}candidate{} into scope" , better, msg_diff) ;
37683779
3769- for candidate in & mut path_strings {
3770- // produce an additional newline to separate the new use statement
3771- // from the directly following item.
3772- let additional_newline = if found_use {
3773- ""
3774- } else {
3775- "\n "
3776- } ;
3777- * candidate = format ! ( "use {};\n {}" , candidate, additional_newline) ;
3778- }
3780+ if let Some ( span) = span {
3781+ for candidate in & mut path_strings {
3782+ // produce an additional newline to separate the new use statement
3783+ // from the directly following item.
3784+ let additional_newline = if found_use {
3785+ ""
3786+ } else {
3787+ "\n "
3788+ } ;
3789+ * candidate = format ! ( "use {};\n {}" , candidate, additional_newline) ;
3790+ }
37793791
3780- err. span_suggestions ( span, & msg, path_strings) ;
3792+ err. span_suggestions ( span, & msg, path_strings) ;
3793+ } else {
3794+ let mut msg = msg;
3795+ msg. push ( ':' ) ;
3796+ for candidate in path_strings {
3797+ msg. push ( '\n' ) ;
3798+ msg. push_str ( & candidate) ;
3799+ }
3800+ }
37813801}
37823802
37833803/// A somewhat inefficient routine to obtain the name of a module.
0 commit comments