From fa2bc4f40005c7b318ec91dac3222141bf8e9833 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Thu, 26 Aug 2021 19:16:33 +0200 Subject: [PATCH] Directly access the module for use suggestions. --- .../rustc_typeck/src/check/method/suggest.rs | 94 +++++++------------ 1 file changed, 33 insertions(+), 61 deletions(-) diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index 04a2dafcf1f..c60d82d0cab 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -6,8 +6,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Namespace, Res}; -use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX}; -use rustc_hir::intravisit; +use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_INDEX}; use rustc_hir::lang_items::LangItem; use rustc_hir::{ExprKind, Node, QPath}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; @@ -1011,8 +1010,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { candidates: Vec, ) { let module_did = self.tcx.parent_module(self.body_id); - let module_id = self.tcx.hir().local_def_id_to_hir_id(module_did); - let (span, found_use) = UsePlacementFinder::check(self.tcx, module_id); + let (span, found_use) = find_use_placement(self.tcx, module_did); if let Some(span) = span { let path_strings = candidates.iter().map(|did| { // Produce an additional newline to separate the new use statement @@ -1605,60 +1603,38 @@ pub fn provide(providers: &mut ty::query::Providers) { providers.all_traits = compute_all_traits; } -struct UsePlacementFinder<'tcx> { - target_module: hir::HirId, - span: Option, - found_use: bool, - tcx: TyCtxt<'tcx>, -} +fn find_use_placement<'tcx>(tcx: TyCtxt<'tcx>, target_module: LocalDefId) -> (Option, bool) { + let mut span = None; + let mut found_use = false; + let (module, _, _) = tcx.hir().get_module(target_module); -impl UsePlacementFinder<'tcx> { - fn check(tcx: TyCtxt<'tcx>, target_module: hir::HirId) -> (Option, bool) { - let mut finder = UsePlacementFinder { target_module, span: None, found_use: false, tcx }; - tcx.hir().walk_crate(&mut finder); - (finder.span, finder.found_use) - } -} - -impl intravisit::Visitor<'tcx> for UsePlacementFinder<'tcx> { - fn visit_mod(&mut self, module: &'tcx hir::Mod<'tcx>, _: Span, hir_id: hir::HirId) { - if self.span.is_some() { - return; - } - if hir_id != self.target_module { - intravisit::walk_mod(self, module, hir_id); - return; - } - // Find a `use` statement. - for &item_id in module.item_ids { - let item = self.tcx.hir().item(item_id); - match item.kind { - hir::ItemKind::Use(..) => { - // Don't suggest placing a `use` before the prelude - // import or other generated ones. - if !item.span.from_expansion() { - self.span = Some(item.span.shrink_to_lo()); - self.found_use = true; - return; - } + // Find a `use` statement. + for &item_id in module.item_ids { + let item = tcx.hir().item(item_id); + match item.kind { + hir::ItemKind::Use(..) => { + // Don't suggest placing a `use` before the prelude + // import or other generated ones. + if !item.span.from_expansion() { + span = Some(item.span.shrink_to_lo()); + found_use = true; + break; } - // Don't place `use` before `extern crate`... - hir::ItemKind::ExternCrate(_) => {} - // ...but do place them before the first other item. - _ => { - if self.span.map_or(true, |span| item.span < span) { - if !item.span.from_expansion() { - self.span = Some(item.span.shrink_to_lo()); - // Don't insert between attributes and an item. - let attrs = self.tcx.hir().attrs(item.hir_id()); - // Find the first attribute on the item. - // FIXME: This is broken for active attributes. - for attr in attrs { - if !attr.span.is_dummy() - && self.span.map_or(true, |span| attr.span < span) - { - self.span = Some(attr.span.shrink_to_lo()); - } + } + // Don't place `use` before `extern crate`... + hir::ItemKind::ExternCrate(_) => {} + // ...but do place them before the first other item. + _ => { + if span.map_or(true, |span| item.span < span) { + if !item.span.from_expansion() { + span = Some(item.span.shrink_to_lo()); + // Don't insert between attributes and an item. + let attrs = tcx.hir().attrs(item.hir_id()); + // Find the first attribute on the item. + // FIXME: This is broken for active attributes. + for attr in attrs { + if !attr.span.is_dummy() && span.map_or(true, |span| attr.span < span) { + span = Some(attr.span.shrink_to_lo()); } } } @@ -1667,11 +1643,7 @@ impl intravisit::Visitor<'tcx> for UsePlacementFinder<'tcx> { } } - type Map = intravisit::ErasedMap<'tcx>; - - fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap { - intravisit::NestedVisitorMap::None - } + (span, found_use) } fn print_disambiguation_help(