@@ -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
self . span = Some ( item. span . with_hi ( item. span . lo ( ) ) ) ;
610
610
self . found_use = true ;
611
611
return ;
@@ -615,11 +615,22 @@ impl<'tcx> Visitor<'tcx> for UsePlacementFinder {
615
615
ItemKind :: ExternCrate ( _) => { }
616
616
// but place them before the first other item
617
617
_ => 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
+ }
619
631
} ,
620
632
}
621
633
}
622
- assert ! ( self . span. is_some( ) , "a file can't have no items and emit suggestions" ) ;
623
634
}
624
635
}
625
636
@@ -3553,8 +3564,7 @@ impl<'a> Resolver<'a> {
3553
3564
} ;
3554
3565
visit:: walk_crate ( & mut finder, krate) ;
3555
3566
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 ) ;
3558
3568
}
3559
3569
err. emit ( ) ;
3560
3570
}
@@ -3748,7 +3758,8 @@ fn import_candidate_to_paths(suggestion: &ImportSuggestion) -> (Span, String, St
3748
3758
/// entities with that name in all crates. This method allows outputting the
3749
3759
/// results of this search in a programmer-friendly way
3750
3760
fn show_candidates ( err : & mut DiagnosticBuilder ,
3751
- span : Span ,
3761
+ // This is `None` if all placement locations are inside expansions
3762
+ span : Option < Span > ,
3752
3763
candidates : & [ ImportSuggestion ] ,
3753
3764
better : bool ,
3754
3765
found_use : bool ) {
@@ -3766,18 +3777,27 @@ fn show_candidates(err: &mut DiagnosticBuilder,
3766
3777
} ;
3767
3778
let msg = format ! ( "possible {}candidate{} into scope" , better, msg_diff) ;
3768
3779
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
+ }
3779
3791
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
+ }
3781
3801
}
3782
3802
3783
3803
/// A somewhat inefficient routine to obtain the name of a module.
0 commit comments