@@ -8,7 +8,7 @@ use rustc_errors::{
88 MultiSpan ,
99} ;
1010use rustc_hir as hir;
11- use rustc_hir:: def_id:: { DefId , LocalDefId } ;
11+ use rustc_hir:: def_id:: DefId ;
1212use rustc_hir:: lang_items:: LangItem ;
1313use rustc_hir:: { ExprKind , Node , QPath } ;
1414use rustc_infer:: infer:: type_variable:: { TypeVariableOrigin , TypeVariableOriginKind } ;
@@ -1473,12 +1473,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14731473 }
14741474 }
14751475
1476- fn suggest_use_candidates (
1477- & self ,
1478- err : & mut Diagnostic ,
1479- mut msg : String ,
1480- candidates : Vec < DefId > ,
1481- ) {
1476+ fn suggest_use_candidates ( & self , err : & mut Diagnostic , msg : String , candidates : Vec < DefId > ) {
14821477 let parent_map = self . tcx . visible_parent_map ( ( ) ) ;
14831478
14841479 // Separate out candidates that must be imported with a glob, because they are named `_`
@@ -1502,80 +1497,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
15021497 } ) ;
15031498
15041499 let module_did = self . tcx . parent_module ( self . body_id ) ;
1505- let ( span, found_use) = find_use_placement ( self . tcx , module_did) ;
1506- if let Some ( span) = span {
1507- let path_strings = candidates. iter ( ) . map ( |trait_did| {
1508- // Produce an additional newline to separate the new use statement
1509- // from the directly following item.
1510- let additional_newline = if found_use { "" } else { "\n " } ;
1511- format ! (
1512- "use {};\n {}" ,
1513- with_crate_prefix!( self . tcx. def_path_str( * trait_did) ) ,
1514- additional_newline
1515- )
1516- } ) ;
1500+ let ( module, _, _) = self . tcx . hir ( ) . get_module ( module_did) ;
1501+ let span = module. spans . inject_use_span ;
15171502
1518- let glob_path_strings = globs. iter ( ) . map ( |trait_did| {
1519- let parent_did = parent_map. get ( trait_did) . unwrap ( ) ;
1503+ let path_strings = candidates. iter ( ) . map ( |trait_did| {
1504+ format ! ( "use {};\n " , with_crate_prefix!( self . tcx. def_path_str( * trait_did) ) , )
1505+ } ) ;
15201506
1521- // Produce an additional newline to separate the new use statement
1522- // from the directly following item.
1523- let additional_newline = if found_use { "" } else { "\n " } ;
1524- format ! (
1525- "use {}::*; // trait {}\n {}" ,
1526- with_crate_prefix!( self . tcx. def_path_str( * parent_did) ) ,
1527- self . tcx. item_name( * trait_did) ,
1528- additional_newline
1529- )
1530- } ) ;
1507+ let glob_path_strings = globs. iter ( ) . map ( |trait_did| {
1508+ let parent_did = parent_map. get ( trait_did) . unwrap ( ) ;
1509+ format ! (
1510+ "use {}::*; // trait {}\n " ,
1511+ with_crate_prefix!( self . tcx. def_path_str( * parent_did) ) ,
1512+ self . tcx. item_name( * trait_did) ,
1513+ )
1514+ } ) ;
15311515
1532- err. span_suggestions (
1533- span,
1534- & msg,
1535- path_strings. chain ( glob_path_strings) ,
1536- Applicability :: MaybeIncorrect ,
1537- ) ;
1538- } else {
1539- let limit = if candidates. len ( ) + globs. len ( ) == 5 { 5 } else { 4 } ;
1540- for ( i, trait_did) in candidates. iter ( ) . take ( limit) . enumerate ( ) {
1541- if candidates. len ( ) + globs. len ( ) > 1 {
1542- msg. push_str ( & format ! (
1543- "\n candidate #{}: `use {};`" ,
1544- i + 1 ,
1545- with_crate_prefix!( self . tcx. def_path_str( * trait_did) )
1546- ) ) ;
1547- } else {
1548- msg. push_str ( & format ! (
1549- "\n `use {};`" ,
1550- with_crate_prefix!( self . tcx. def_path_str( * trait_did) )
1551- ) ) ;
1552- }
1553- }
1554- for ( i, trait_did) in
1555- globs. iter ( ) . take ( limit. saturating_sub ( candidates. len ( ) ) ) . enumerate ( )
1556- {
1557- let parent_did = parent_map. get ( trait_did) . unwrap ( ) ;
1558-
1559- if candidates. len ( ) + globs. len ( ) > 1 {
1560- msg. push_str ( & format ! (
1561- "\n candidate #{}: `use {}::*; // trait {}`" ,
1562- candidates. len( ) + i + 1 ,
1563- with_crate_prefix!( self . tcx. def_path_str( * parent_did) ) ,
1564- self . tcx. item_name( * trait_did) ,
1565- ) ) ;
1566- } else {
1567- msg. push_str ( & format ! (
1568- "\n `use {}::*; // trait {}`" ,
1569- with_crate_prefix!( self . tcx. def_path_str( * parent_did) ) ,
1570- self . tcx. item_name( * trait_did) ,
1571- ) ) ;
1572- }
1573- }
1574- if candidates. len ( ) > limit {
1575- msg. push_str ( & format ! ( "\n and {} others" , candidates. len( ) + globs. len( ) - limit) ) ;
1576- }
1577- err. note ( & msg) ;
1578- }
1516+ err. span_suggestions (
1517+ span,
1518+ & msg,
1519+ path_strings. chain ( glob_path_strings) ,
1520+ Applicability :: MaybeIncorrect ,
1521+ ) ;
15791522 }
15801523
15811524 fn suggest_valid_traits (
@@ -2106,53 +2049,6 @@ pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
21062049 tcx. all_traits ( ) . map ( |def_id| TraitInfo { def_id } ) . collect ( )
21072050}
21082051
2109- fn find_use_placement < ' tcx > ( tcx : TyCtxt < ' tcx > , target_module : LocalDefId ) -> ( Option < Span > , bool ) {
2110- // FIXME(#94854): this code uses an out-of-date method for inferring a span
2111- // to suggest. It would be better to thread the ModSpans from the AST into
2112- // the HIR, and then use that to drive the suggestion here.
2113-
2114- let mut span = None ;
2115- let mut found_use = false ;
2116- let ( module, _, _) = tcx. hir ( ) . get_module ( target_module) ;
2117-
2118- // Find a `use` statement.
2119- for & item_id in module. item_ids {
2120- let item = tcx. hir ( ) . item ( item_id) ;
2121- match item. kind {
2122- hir:: ItemKind :: Use ( ..) => {
2123- // Don't suggest placing a `use` before the prelude
2124- // import or other generated ones.
2125- if !item. span . from_expansion ( ) {
2126- span = Some ( item. span . shrink_to_lo ( ) ) ;
2127- found_use = true ;
2128- break ;
2129- }
2130- }
2131- // Don't place `use` before `extern crate`...
2132- hir:: ItemKind :: ExternCrate ( _) => { }
2133- // ...but do place them before the first other item.
2134- _ => {
2135- if span. map_or ( true , |span| item. span < span) {
2136- if !item. span . from_expansion ( ) {
2137- span = Some ( item. span . shrink_to_lo ( ) ) ;
2138- // Don't insert between attributes and an item.
2139- let attrs = tcx. hir ( ) . attrs ( item. hir_id ( ) ) ;
2140- // Find the first attribute on the item.
2141- // FIXME: This is broken for active attributes.
2142- for attr in attrs {
2143- if !attr. span . is_dummy ( ) && span. map_or ( true , |span| attr. span < span) {
2144- span = Some ( attr. span . shrink_to_lo ( ) ) ;
2145- }
2146- }
2147- }
2148- }
2149- }
2150- }
2151- }
2152-
2153- ( span, found_use)
2154- }
2155-
21562052fn print_disambiguation_help < ' tcx > (
21572053 item_name : Ident ,
21582054 args : Option < & ' tcx [ hir:: Expr < ' tcx > ] > ,
0 commit comments