@@ -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 let mut span = item. span ;
610610 span. hi = span. lo ;
611611 self . span = Some ( span) ;
@@ -617,13 +617,26 @@ impl<'tcx> Visitor<'tcx> for UsePlacementFinder {
617617 ItemKind :: ExternCrate ( _) => { }
618618 // but place them before the first other item
619619 _ => if self . span . map_or ( true , |span| item. span < span ) {
620- let mut span = item. span ;
621- span. hi = span. lo ;
622- self . span = Some ( span) ;
620+ if item. span . ctxt . outer ( ) . expn_info ( ) . is_none ( ) {
621+ // don't insert between attributes and an item
622+ if item. attrs . is_empty ( ) {
623+ let mut span = item. span ;
624+ span. hi = span. lo ;
625+ self . span = Some ( span) ;
626+ } else {
627+ // find the first attribute on the item
628+ for attr in & item. attrs {
629+ if self . span . map_or ( true , |span| attr. span < span) {
630+ let mut span = attr. span ;
631+ span. hi = span. lo ;
632+ self . span = Some ( span) ;
633+ }
634+ }
635+ }
636+ }
623637 } ,
624638 }
625639 }
626- assert ! ( self . span. is_some( ) , "a file can't have no items and emit suggestions" ) ;
627640 }
628641}
629642
@@ -3554,8 +3567,7 @@ impl<'a> Resolver<'a> {
35543567 } ;
35553568 visit:: walk_crate ( & mut finder, krate) ;
35563569 if !candidates. is_empty ( ) {
3557- let span = finder. span . expect ( "did not find module" ) ;
3558- show_candidates ( & mut err, span, & candidates, better, finder. found_use ) ;
3570+ show_candidates ( & mut err, finder. span , & candidates, better, finder. found_use ) ;
35593571 }
35603572 err. emit ( ) ;
35613573 }
@@ -3749,7 +3761,8 @@ fn import_candidate_to_paths(suggestion: &ImportSuggestion) -> (Span, String, St
37493761/// entities with that name in all crates. This method allows outputting the
37503762/// results of this search in a programmer-friendly way
37513763fn show_candidates ( err : & mut DiagnosticBuilder ,
3752- span : Span ,
3764+ // This is `None` if all placement locations are inside expansions
3765+ span : Option < Span > ,
37533766 candidates : & [ ImportSuggestion ] ,
37543767 better : bool ,
37553768 found_use : bool ) {
@@ -3767,18 +3780,27 @@ fn show_candidates(err: &mut DiagnosticBuilder,
37673780 } ;
37683781 let msg = format ! ( "possible {}candidate{} into scope" , better, msg_diff) ;
37693782
3770- for candidate in & mut path_strings {
3771- // produce an additional newline to separate the new use statement
3772- // from the directly following item.
3773- let additional_newline = if found_use {
3774- ""
3775- } else {
3776- "\n "
3777- } ;
3778- * candidate = format ! ( "use {};\n {}" , candidate, additional_newline) ;
3779- }
3783+ if let Some ( span) = span {
3784+ for candidate in & mut path_strings {
3785+ // produce an additional newline to separate the new use statement
3786+ // from the directly following item.
3787+ let additional_newline = if found_use {
3788+ ""
3789+ } else {
3790+ "\n "
3791+ } ;
3792+ * candidate = format ! ( "use {};\n {}" , candidate, additional_newline) ;
3793+ }
37803794
3781- err. span_suggestions ( span, & msg, path_strings) ;
3795+ err. span_suggestions ( span, & msg, path_strings) ;
3796+ } else {
3797+ let mut msg = msg;
3798+ msg. push ( ':' ) ;
3799+ for candidate in path_strings {
3800+ msg. push ( '\n' ) ;
3801+ msg. push_str ( & candidate) ;
3802+ }
3803+ }
37823804}
37833805
37843806/// A somewhat inefficient routine to obtain the name of a module.
0 commit comments