@@ -605,7 +605,7 @@ impl<'tcx> Visitor<'tcx> for UsePlacementFinder {
605
605
ItemKind :: Use ( ..) => {
606
606
// don't suggest placing a use before the prelude
607
607
// import or other generated ones
608
- if item. span == DUMMY_SP {
608
+ if item. span . ctxt . outer ( ) . expn_info ( ) . is_none ( ) {
609
609
let mut span = item. span ;
610
610
span. hi = span. lo ;
611
611
self . span = Some ( span) ;
@@ -617,13 +617,26 @@ impl<'tcx> Visitor<'tcx> for UsePlacementFinder {
617
617
ItemKind :: ExternCrate ( _) => { }
618
618
// but place them before the first other item
619
619
_ => 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
+ }
623
637
} ,
624
638
}
625
639
}
626
- assert ! ( self . span. is_some( ) , "a file can't have no items and emit suggestions" ) ;
627
640
}
628
641
}
629
642
@@ -3554,8 +3567,7 @@ impl<'a> Resolver<'a> {
3554
3567
} ;
3555
3568
visit:: walk_crate ( & mut finder, krate) ;
3556
3569
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 ) ;
3559
3571
}
3560
3572
err. emit ( ) ;
3561
3573
}
@@ -3749,7 +3761,8 @@ fn import_candidate_to_paths(suggestion: &ImportSuggestion) -> (Span, String, St
3749
3761
/// entities with that name in all crates. This method allows outputting the
3750
3762
/// results of this search in a programmer-friendly way
3751
3763
fn show_candidates ( err : & mut DiagnosticBuilder ,
3752
- span : Span ,
3764
+ // This is `None` if all placement locations are inside expansions
3765
+ span : Option < Span > ,
3753
3766
candidates : & [ ImportSuggestion ] ,
3754
3767
better : bool ,
3755
3768
found_use : bool ) {
@@ -3767,18 +3780,27 @@ fn show_candidates(err: &mut DiagnosticBuilder,
3767
3780
} ;
3768
3781
let msg = format ! ( "possible {}candidate{} into scope" , better, msg_diff) ;
3769
3782
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
+ }
3780
3794
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
+ }
3782
3804
}
3783
3805
3784
3806
/// A somewhat inefficient routine to obtain the name of a module.
0 commit comments