Repository: rust-lang/rust-analyzer
Pull request #19018 (2025-01-24 14:13:38)

internal: Record the use tree index in glob imports


Patch:
diff --git a/crates/hir-def/src/import_map.rs b/crates/hir-def/src/import_map.rs
index bb780277ef..34635997bd 100644
--- a/crates/hir-def/src/import_map.rs
+++ b/crates/hir-def/src/import_map.rs
@@ -167,8 +167,8 @@ impl ImportMap {
                     let attr_id = if let Some(import) = import {
                         match import {
                             ImportOrExternCrate::ExternCrate(id) => Some(id.into()),
-                            ImportOrExternCrate::Import(id) => Some(id.import.into()),
-                            ImportOrExternCrate::Glob(id) => Some(id.into()),
+                            ImportOrExternCrate::Import(id) => Some(id.use_.into()),
+                            ImportOrExternCrate::Glob(id) => Some(id.use_.into()),
                         }
                     } else {
                         match item {
diff --git a/crates/hir-def/src/item_scope.rs b/crates/hir-def/src/item_scope.rs
index 0ece878b83..65a39c5656 100644
--- a/crates/hir-def/src/item_scope.rs
+++ b/crates/hir-def/src/item_scope.rs
@@ -31,7 +31,7 @@ pub struct PerNsGlobImports {
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
 pub enum ImportOrExternCrate {
-    Glob(UseId),
+    Glob(GlobId),
     Import(ImportId),
     ExternCrate(ExternCrateId),
 }
@@ -45,29 +45,41 @@ impl From<ImportOrGlob> for ImportOrExternCrate {
     }
 }
 
-impl From<ImportType> for ImportOrExternCrate {
-    fn from(value: ImportType) -> Self {
-        match value {
-            ImportType::Glob(it) => ImportOrExternCrate::Glob(it),
-            ImportType::Import(it) => ImportOrExternCrate::Import(it),
-            ImportType::ExternCrate(it) => ImportOrExternCrate::ExternCrate(it),
-        }
-    }
-}
-
 impl ImportOrExternCrate {
-    pub fn into_import(self) -> Option<ImportOrGlob> {
+    pub fn import_or_glob(self) -> Option<ImportOrGlob> {
         match self {
             ImportOrExternCrate::Import(it) => Some(ImportOrGlob::Import(it)),
             ImportOrExternCrate::Glob(it) => Some(ImportOrGlob::Glob(it)),
             _ => None,
         }
     }
+
+    pub fn import(self) -> Option<ImportId> {
+        match self {
+            ImportOrExternCrate::Import(it) => Some(it),
+            _ => None,
+        }
+    }
+
+    pub fn glob(self) -> Option<GlobId> {
+        match self {
+            ImportOrExternCrate::Glob(id) => Some(id),
+            _ => None,
+        }
+    }
+
+    pub fn use_(self) -> Option<UseId> {
+        match self {
+            ImportOrExternCrate::Glob(id) => Some(id.use_),
+            ImportOrExternCrate::Import(id) => Some(id.use_),
+            _ => None,
+        }
+    }
 }
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
 pub enum ImportOrGlob {
-    Glob(UseId),
+    Glob(GlobId),
     Import(ImportId),
 }
 
@@ -79,17 +91,11 @@ impl ImportOrGlob {
         }
     }
 }
-#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
-pub(crate) enum ImportType {
-    Import(ImportId),
-    Glob(UseId),
-    ExternCrate(ExternCrateId),
-}
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
 pub enum ImportOrDef {
     Import(ImportId),
-    Glob(UseId),
+    Glob(GlobId),
     ExternCrate(ExternCrateId),
     Def(ModuleDefId),
 }
@@ -115,7 +121,13 @@ impl From<ImportOrGlob> for ImportOrDef {
 
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
 pub struct ImportId {
-    pub import: UseId,
+    pub use_: UseId,
+    pub idx: Idx<ast::UseTree>,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
+pub struct GlobId {
+    pub use_: UseId,
     pub idx: Idx<ast::UseTree>,
 }
 
@@ -236,7 +248,7 @@ impl ItemScope {
         self.use_imports_types
             .keys()
             .copied()
-            .filter_map(ImportOrExternCrate::into_import)
+            .filter_map(ImportOrExternCrate::import_or_glob)
             .chain(self.use_imports_values.keys().copied())
             .chain(self.use_imports_macros.keys().copied())
             .filter_map(ImportOrGlob::into_import)
@@ -252,7 +264,7 @@ impl ItemScope {
         while let Some(&m) = scope.use_imports_macros.get(&ImportOrGlob::Import(import)) {
             match m {
                 ImportOrDef::Import(i) => {
-                    let module_id = i.import.lookup(db).container;
+                    let module_id = i.use_.lookup(db).container;
                     def_map = module_id.def_map(db);
                     scope = &def_map[module_id.local_id].scope;
                     import = i;
@@ -268,7 +280,7 @@ impl ItemScope {
         while let Some(&m) = scope.use_imports_types.get(&ImportOrExternCrate::Import(import)) {
             match m {
                 ImportOrDef::Import(i) => {
-                    let module_id = i.import.lookup(db).container;
+                    let module_id = i.use_.lookup(db).container;
                     def_map = module_id.def_map(db);
                     scope = &def_map[module_id.local_id].scope;
                     import = i;
@@ -284,7 +296,7 @@ impl ItemScope {
         while let Some(&m) = scope.use_imports_values.get(&ImportOrGlob::Import(import)) {
             match m {
                 ImportOrDef::Import(i) => {
-                    let module_id = i.import.lookup(db).container;
+                    let module_id = i.use_.lookup(db).container;
                     def_map = module_id.def_map(db);
                     scope = &def_map[module_id.local_id].scope;
                     import = i;
@@ -545,9 +557,13 @@ impl ItemScope {
         self.unnamed_trait_imports.get(&tr).map(|trait_| trait_.vis)
     }
 
-    pub(crate) fn push_unnamed_trait(&mut self, tr: TraitId, vis: Visibility) {
-        // FIXME: import
-        self.unnamed_trait_imports.insert(tr, Item { def: (), vis, import: None });
+    pub(crate) fn push_unnamed_trait(
+        &mut self,
+        tr: TraitId,
+        vis: Visibility,
+        import: Option<ImportId>,
+    ) {
+        self.unnamed_trait_imports.insert(tr, Item { def: (), vis, import });
     }
 
     pub(crate) fn push_res_with_import(
@@ -555,7 +571,7 @@ impl ItemScope {
         glob_imports: &mut PerNsGlobImports,
         lookup: (LocalModuleId, Name),
         def: PerNs,
-        import: Option<ImportType>,
+        import: Option<ImportOrExternCrate>,
     ) -> bool {
         let mut changed = false;
 
@@ -566,12 +582,11 @@ impl ItemScope {
             match existing {
                 Entry::Vacant(entry) => {
                     match import {
-                        Some(ImportType::Glob(_)) => {
+                        Some(ImportOrExternCrate::Glob(_)) => {
                             glob_imports.types.insert(lookup.clone());
                         }
                         _ => _ = glob_imports.types.remove(&lookup),
                     }
-                    let import = import.map(Into::into);
                     let prev = std::mem::replace(&mut fld.import, import);
                     if let Some(import) = import {
                         self.use_imports_types
@@ -582,7 +597,7 @@ impl ItemScope {
                 }
                 Entry::Occupied(mut entry) => {
                     match import {
-                        Some(ImportType::Glob(..)) => {
+                        Some(ImportOrExternCrate::Glob(..)) => {
                             // Multiple globs may import the same item and they may
                             // override visibility from previously resolved globs. This is
                             // currently handled by `DefCollector`, because we need to
@@ -591,7 +606,6 @@ impl ItemScope {
                         }
                         _ => {
                             if glob_imports.types.remove(&lookup) {
-                                let import = import.map(Into::into);
                                 let prev = std::mem::replace(&mut fld.import, import);
                                 if let Some(import) = import {
                                     self.use_imports_types.insert(
@@ -614,16 +628,12 @@ impl ItemScope {
             match existing {
                 Entry::Vacant(entry) => {
                     match import {
-                        Some(ImportType::Glob(_)) => {
+                        Some(ImportOrExternCrate::Glob(_)) => {
                             glob_imports.values.insert(lookup.clone());
                         }
                         _ => _ = glob_imports.values.remove(&lookup),
                     }
-                    let import = match import {
-                        Some(ImportType::Import(import)) => Some(ImportOrGlob::Import(import)),
-                        Some(ImportType::Glob(u)) => Some(ImportOrGlob::Glob(u)),
-                        _ => None,
-                    };
+                    let import = import.and_then(ImportOrExternCrate::import_or_glob);
                     let prev = std::mem::replace(&mut fld.import, import);
                     if let Some(import) = import {
                         self.use_imports_values
@@ -632,15 +642,13 @@ impl ItemScope {
                     entry.insert(fld);
                     changed = true;
                 }
-                Entry::Occupied(mut entry) if !matches!(import, Some(ImportType::Glob(..))) => {
+                Entry::Occupied(mut entry)
+                    if !matches!(import, Some(ImportOrExternCrate::Glob(..))) =>
+                {
                     if glob_imports.values.remove(&lookup) {
                         cov_mark::hit!(import_shadowed);
 
-                        let import = match import {
-                            Some(ImportType::Import(import)) => Some(ImportOrGlob::Import(import)),
-                            Some(ImportType::Glob(u)) => Some(ImportOrGlob::Glob(u)),
-                            _ => None,
-                        };
+                        let import = import.and_then(ImportOrExternCrate::import_or_glob);
                         let prev = std::mem::replace(&mut fld.import, import);
                         if let Some(import) = import {
                             self.use_imports_values
@@ -659,16 +667,12 @@ impl ItemScope {
             match existing {
                 Entry::Vacant(entry) => {
                     match import {
-                        Some(ImportType::Glob(_)) => {
+                        Some(ImportOrExternCrate::Glob(_)) => {
                             glob_imports.macros.insert(lookup.clone());
                         }
                         _ => _ = glob_imports.macros.remove(&lookup),
                     }
-                    let import = match import {
-                        Some(ImportType::Import(import)) => Some(ImportOrGlob::Import(import)),
-                        Some(ImportType::Glob(u)) => Some(ImportOrGlob::Glob(u)),
-                        _ => None,
-                    };
+                    let import = import.and_then(ImportOrExternCrate::import_or_glob);
                     let prev = std::mem::replace(&mut fld.import, import);
                     if let Some(import) = import {
                         self.use_imports_macros.insert(
@@ -679,14 +683,12 @@ impl ItemScope {
                     entry.insert(fld);
                     changed = true;
                 }
-                Entry::Occupied(mut entry) if !matches!(import, Some(ImportType::Glob(..))) => {
+                Entry::Occupied(mut entry)
+                    if !matches!(import, Some(ImportOrExternCrate::Glob(..))) =>
+                {
                     if glob_imports.macros.remove(&lookup) {
                         cov_mark::hit!(import_shadowed);
-                        let import = match import {
-                            Some(ImportType::Import(import)) => Some(ImportOrGlob::Import(import)),
-                            Some(ImportType::Glob(u)) => Some(ImportOrGlob::Glob(u)),
-                            _ => None,
-                        };
+                        let import = import.and_then(ImportOrExternCrate::import_or_glob);
                         let prev = std::mem::replace(&mut fld.import, import);
                         if let Some(import) = import {
                             self.use_imports_macros.insert(
@@ -856,7 +858,7 @@ impl PerNs {
         match def {
             ModuleDefId::ModuleId(_) => PerNs::types(def, v, import),
             ModuleDefId::FunctionId(_) => {
-                PerNs::values(def, v, import.and_then(ImportOrExternCrate::into_import))
+                PerNs::values(def, v, import.and_then(ImportOrExternCrate::import_or_glob))
             }
             ModuleDefId::AdtId(adt) => match adt {
                 AdtId::UnionId(_) => PerNs::types(def, v, import),
@@ -871,14 +873,14 @@ impl PerNs {
             },
             ModuleDefId::EnumVariantId(_) => PerNs::both(def, def, v, import),
             ModuleDefId::ConstId(_) | ModuleDefId::StaticId(_) => {
-                PerNs::values(def, v, import.and_then(ImportOrExternCrate::into_import))
+                PerNs::values(def, v, import.and_then(ImportOrExternCrate::import_or_glob))
             }
             ModuleDefId::TraitId(_) => PerNs::types(def, v, import),
             ModuleDefId::TraitAliasId(_) => PerNs::types(def, v, import),
             ModuleDefId::TypeAliasId(_) => PerNs::types(def, v, import),
             ModuleDefId::BuiltinType(_) => PerNs::types(def, v, import),
             ModuleDefId::MacroId(mac) => {
-                PerNs::macros(mac, v, import.and_then(ImportOrExternCrate::into_import))
+                PerNs::macros(mac, v, import.and_then(ImportOrExternCrate::import_or_glob))
             }
         }
     }
diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs
index 5058d15f34..06276335b7 100644
--- a/crates/hir-def/src/nameres/collector.rs
+++ b/crates/hir-def/src/nameres/collector.rs
@@ -28,7 +28,7 @@ use triomphe::Arc;
 use crate::{
     attr::Attrs,
     db::DefDatabase,
-    item_scope::{ImportId, ImportOrExternCrate, ImportOrGlob, ImportType, PerNsGlobImports},
+    item_scope::{GlobId, ImportId, ImportOrExternCrate, PerNsGlobImports},
     item_tree::{
         self, AttrOwner, FieldsShape, FileItemTreeId, ImportKind, ItemTree, ItemTreeId,
         ItemTreeNode, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, TreeId, UseTreeKind,
@@ -208,7 +208,7 @@ struct DefCollector<'a> {
     def_map: DefMap,
     // The dependencies of the current crate, including optional deps like `test`.
     deps: FxHashMap<Name, Dependency>,
-    glob_imports: FxHashMap<LocalModuleId, Vec<(LocalModuleId, Visibility, UseId)>>,
+    glob_imports: FxHashMap<LocalModuleId, Vec<(LocalModuleId, Visibility, GlobId)>>,
     unresolved_imports: Vec<ImportDirective>,
     indeterminate_imports: Vec<(ImportDirective, PerNs)>,
     unresolved_macros: Vec<MacroDirective>,
@@ -524,14 +524,7 @@ impl DefCollector<'_> {
 
         match per_ns.types {
             Some(Item { def: ModuleDefId::ModuleId(m), import, .. }) => {
-                // FIXME: This should specifically look for a glob import somehow and record that here
-                self.def_map.prelude = Some((
-                    m,
-                    import
-                        .and_then(ImportOrExternCrate::into_import)
-                        .and_then(ImportOrGlob::into_import)
-                        .map(|it| it.import),
-                ));
+                self.def_map.prelude = Some((m, import.and_then(ImportOrExternCrate::use_)));
             }
             types => {
                 tracing::debug!(
@@ -848,13 +841,14 @@ impl DefCollector<'_> {
                     def.values = None;
                     def.macros = None;
                 }
-                let imp = ImportType::Import(ImportId { import: id, idx: use_tree });
+                let imp = ImportOrExternCrate::Import(ImportId { use_: id, idx: use_tree });
                 tracing::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def);
 
                 self.update(module_id, &[(name.cloned(), def)], vis, Some(imp));
             }
-            ImportSource { kind: ImportKind::Glob, id, is_prelude, .. } => {
+            ImportSource { kind: ImportKind::Glob, id, is_prelude, use_tree } => {
                 tracing::debug!("glob import: {:?}", import);
+                let glob = GlobId { use_: id, idx: use_tree };
                 match def.take_types() {
                     Some(ModuleDefId::ModuleId(m)) => {
                         if is_prelude {
@@ -878,7 +872,12 @@ impl DefCollector<'_> {
                                 .filter(|(_, res)| !res.is_none())
                                 .collect::<Vec<_>>();
 
-                            self.update(module_id, &items, vis, Some(ImportType::Glob(id)));
+                            self.update(
+                                module_id,
+                                &items,
+                                vis,
+                                Some(ImportOrExternCrate::Glob(glob)),
+                            );
                         } else {
                             // glob import from same crate => we do an initial
                             // import, and then need to propagate any further
@@ -910,11 +909,16 @@ impl DefCollector<'_> {
                                 .filter(|(_, res)| !res.is_none())
                                 .collect::<Vec<_>>();
 
-                            self.update(module_id, &items, vis, Some(ImportType::Glob(id)));
+                            self.update(
+                                module_id,
+                                &items,
+                                vis,
+                                Some(ImportOrExternCrate::Glob(glob)),
+                            );
                             // record the glob import in case we add further items
-                            let glob = self.glob_imports.entry(m.local_id).or_default();
-                            match glob.iter_mut().find(|(mid, _, _)| *mid == module_id) {
-                                None => glob.push((module_id, vis, id)),
+                            let glob_imports = self.glob_imports.entry(m.local_id).or_default();
+                            match glob_imports.iter_mut().find(|(mid, _, _)| *mid == module_id) {
+                                None => glob_imports.push((module_id, vis, glob)),
                                 Some((_, old_vis, _)) => {
                                     if let Some(new_vis) = old_vis.max(vis, &self.def_map) {
                                         *old_vis = new_vis;
@@ -947,7 +951,12 @@ impl DefCollector<'_> {
                             (Some(name), res)
                         })
                         .collect::<Vec<_>>();
-                        self.update(module_id, &resolutions, vis, Some(ImportType::Glob(id)));
+                        self.update(
+                            module_id,
+                            &resolutions,
+                            vis,
+                            Some(ImportOrExternCrate::Glob(glob)),
+                        );
                     }
                     Some(d) => {
                         tracing::debug!("glob import {:?} from non-module/enum {:?}", import, d);
@@ -967,7 +976,7 @@ impl DefCollector<'_> {
         resolutions: &[(Option<Name>, PerNs)],
         // Visibility this import will have
         vis: Visibility,
-        import: Option<ImportType>,
+        import: Option<ImportOrExternCrate>,
     ) {
         self.db.unwind_if_cancelled();
         self.update_recursive(module_id, resolutions, vis, import, 0)
@@ -981,7 +990,7 @@ impl DefCollector<'_> {
         // All resolutions are imported with this visibility; the visibilities in
         // the `PerNs` values are ignored and overwritten
         vis: Visibility,
-        import: Option<ImportType>,
+        import: Option<ImportOrExternCrate>,
         depth: usize,
     ) {
         if GLOB_RECURSION_LIMIT.check(depth).is_err() {
@@ -997,8 +1006,10 @@ impl DefCollector<'_> {
                         self.push_res_and_update_glob_vis(module_id, name, *res, vis, import);
                 }
                 None => {
-                    let tr = match res.take_types() {
-                        Some(ModuleDefId::TraitId(tr)) => tr,
+                    let (tr, import) = match res.take_types_full() {
+                        Some(Item { def: ModuleDefId::TraitId(tr), vis: _, import }) => {
+                            (tr, import)
+                        }
                         Some(other) => {
                             tracing::debug!("non-trait `_` import of {:?}", other);
                             continue;
@@ -1024,7 +1035,11 @@ impl DefCollector<'_> {
 
                     if should_update {
                         changed = true;
-                        self.def_map.modules[module_id].scope.push_unnamed_trait(tr, vis);
+                        self.def_map.modules[module_id].scope.push_unnamed_trait(
+                            tr,
+                            vis,
+                            import.and_then(ImportOrExternCrate::import),
+                        );
                     }
                 }
             }
@@ -1046,13 +1061,13 @@ impl DefCollector<'_> {
             .cloned()
             .collect::<Vec<_>>();
 
-        for (glob_importing_module, glob_import_vis, use_) in glob_imports {
+        for (glob_importing_module, glob_import_vis, glob) in glob_imports {
             let vis = glob_import_vis.min(vis, &self.def_map).unwrap_or(glob_import_vis);
             self.update_recursive(
                 glob_importing_module,
                 resolutions,
                 vis,
-                Some(ImportType::Glob(use_)),
+                Some(ImportOrExternCrate::Glob(glob)),
                 depth + 1,
             );
         }
@@ -1064,7 +1079,7 @@ impl DefCollector<'_> {
         name: &Name,
         mut defs: PerNs,
         vis: Visibility,
-        def_import_type: Option<ImportType>,
+        def_import_type: Option<ImportOrExternCrate>,
     ) -> bool {
         // `extern crate crate_name` things can be re-exported as `pub use crate_name`.
         // But they cannot be re-exported as `pub use self::crate_name`, `pub use crate::crate_name`
@@ -1077,10 +1092,10 @@ impl DefCollector<'_> {
                 let Some(ImportOrExternCrate::ExternCrate(_)) = def.import else {
                     return false;
                 };
-                let Some(ImportType::Import(id)) = def_import_type else {
+                let Some(ImportOrExternCrate::Import(id)) = def_import_type else {
                     return false;
                 };
-                let use_id = id.import.lookup(self.db).id;
+                let use_id = id.use_.lookup(self.db).id;
                 let item_tree = use_id.item_tree(self.db);
                 let use_kind = item_tree[use_id.value].use_tree.kind();
                 let UseTreeKind::Single { path, .. } = use_kind else {
@@ -1103,7 +1118,7 @@ impl DefCollector<'_> {
 
         let mut changed = false;
 
-        if let Some(ImportType::Glob(_)) = def_import_type {
+        if let Some(ImportOrExternCrate::Glob(_)) = def_import_type {
             let prev_defs = self.def_map[module_id].scope.get(name);
 
             // Multiple globs may import the same item and they may override visibility from
@@ -1730,7 +1745,7 @@ impl ModCollector<'_, '_> {
                                 ),
                             )],
                             vis,
-                            Some(ImportType::ExternCrate(id)),
+                            Some(ImportOrExternCrate::ExternCrate(id)),
                         );
                     } else {
                         if let Some(name) = name {
diff --git a/crates/hir-def/src/per_ns.rs b/crates/hir-def/src/per_ns.rs
index 339786fc01..c2d3f67f17 100644
--- a/crates/hir-def/src/per_ns.rs
+++ b/crates/hir-def/src/per_ns.rs
@@ -78,7 +78,7 @@ impl PerNs {
             values: Some(Item {
                 def: values,
                 vis,
-                import: import.and_then(ImportOrExternCrate::into_import),
+                import: import.and_then(ImportOrExternCrate::import_or_glob),
             }),
             macros: None,
         }
diff --git a/crates/hir/src/symbols.rs b/crates/hir/src/symbols.rs
index f379a2d4d6..c1c45d8175 100644
--- a/crates/hir/src/symbols.rs
+++ b/crates/hir/src/symbols.rs
@@ -160,8 +160,8 @@ impl<'a> SymbolCollector<'a> {
 
         let mut push_import = |this: &mut Self, i: ImportId, name: &Name, def: ModuleDefId| {
             let source = import_child_source_cache
-                .entry(i.import)
-                .or_insert_with(|| i.import.child_source(this.db.upcast()));
+                .entry(i.use_)
+                .or_insert_with(|| i.use_.child_source(this.db.upcast()));
             let Some(use_tree_src) = source.value.get(i.idx) else { return };
             let Some(name_ptr) = use_tree_src
                 .rename()
diff --git a/crates/ide-completion/src/completions/dot.rs b/crates/ide-completion/src/completions/dot.rs
index 0d1765a7b7..7679d9076d 100644
--- a/crates/ide-completion/src/completions/dot.rs
+++ b/crates/ide-completion/src/completions/dot.rs
@@ -42,38 +42,31 @@ pub(crate) fn complete_dot(
         item.detail("expr.await");
         item.add_to(acc, ctx.db);
 
-        if ctx.config.enable_auto_await {
-            // Completions that skip `.await`, e.g. `.await.foo()`.
-            let dot_access_kind = match &dot_access.kind {
-                DotAccessKind::Field { receiver_is_ambiguous_float_literal: _ } => {
-                    DotAccessKind::Field { receiver_is_ambiguous_float_literal: false }
-                }
-                it @ DotAccessKind::Method { .. } => *it,
-            };
-            let dot_access = DotAccess {
-                receiver: dot_access.receiver.clone(),
-                receiver_ty: Some(hir::TypeInfo {
-                    original: future_output.clone(),
-                    adjusted: None,
-                }),
-                kind: dot_access_kind,
-                ctx: dot_access.ctx,
-            };
-            complete_fields(
-                acc,
-                ctx,
-                &future_output,
-                |acc, field, ty| {
-                    acc.add_field(ctx, &dot_access, Some(await_str.clone()), field, &ty)
-                },
-                |acc, field, ty| acc.add_tuple_field(ctx, Some(await_str.clone()), field, &ty),
-                is_field_access,
-                is_method_access_with_parens,
-            );
-            complete_methods(ctx, &future_output, &traits_in_scope, |func| {
-                acc.add_method(ctx, &dot_access, func, Some(await_str.clone()), None)
-            });
-        }
+        // Completions that skip `.await`, e.g. `.await.foo()`.
+        let dot_access_kind = match &dot_access.kind {
+            DotAccessKind::Field { receiver_is_ambiguous_float_literal: _ } => {
+                DotAccessKind::Field { receiver_is_ambiguous_float_literal: false }
+            }
+            it @ DotAccessKind::Method { .. } => *it,
+        };
+        let dot_access = DotAccess {
+            receiver: dot_access.receiver.clone(),
+            receiver_ty: Some(hir::TypeInfo { original: future_output.clone(), adjusted: None }),
+            kind: dot_access_kind,
+            ctx: dot_access.ctx,
+        };
+        complete_fields(
+            acc,
+            ctx,
+            &future_output,
+            |acc, field, ty| acc.add_field(ctx, &dot_access, Some(await_str.clone()), field, &ty),
+            |acc, field, ty| acc.add_tuple_field(ctx, Some(await_str.clone()), field, &ty),
+            is_field_access,
+            is_method_access_with_parens,
+        );
+        complete_methods(ctx, &future_output, &traits_in_scope, |func| {
+            acc.add_method(ctx, &dot_access, func, Some(await_str.clone()), None)
+        });
     }
 
     complete_fields(
@@ -89,41 +82,39 @@ pub(crate) fn complete_dot(
         acc.add_method(ctx, dot_access, func, None, None)
     });
 
-    if ctx.config.enable_auto_iter {
-        // FIXME:
-        // Checking for the existence of `iter()` is complicated in our setup, because we need to substitute
-        // its return type, so we instead check for `<&Self as IntoIterator>::IntoIter`.
-        // Does <&receiver_ty as IntoIterator>::IntoIter` exist? Assume `iter` is valid
-        let iter = receiver_ty
-            .strip_references()
-            .add_reference(hir::Mutability::Shared)
+    // FIXME:
+    // Checking for the existence of `iter()` is complicated in our setup, because we need to substitute
+    // its return type, so we instead check for `<&Self as IntoIterator>::IntoIter`.
+    // Does <&receiver_ty as IntoIterator>::IntoIter` exist? Assume `iter` is valid
+    let iter = receiver_ty
+        .strip_references()
+        .add_reference(hir::Mutability::Shared)
+        .into_iterator_iter(ctx.db)
+        .map(|ty| (ty, SmolStr::new_static("iter()")));
+    // Does <receiver_ty as IntoIterator>::IntoIter` exist?
+    let into_iter = || {
+        receiver_ty
+            .clone()
             .into_iterator_iter(ctx.db)
-            .map(|ty| (ty, SmolStr::new_static("iter()")));
-        // Does <receiver_ty as IntoIterator>::IntoIter` exist?
-        let into_iter = || {
-            receiver_ty
-                .clone()
-                .into_iterator_iter(ctx.db)
-                .map(|ty| (ty, SmolStr::new_static("into_iter()")))
+            .map(|ty| (ty, SmolStr::new_static("into_iter()")))
+    };
+    if let Some((iter, iter_sym)) = iter.or_else(into_iter) {
+        // Skip iterators, e.g. complete `.iter().filter_map()`.
+        let dot_access_kind = match &dot_access.kind {
+            DotAccessKind::Field { receiver_is_ambiguous_float_literal: _ } => {
+                DotAccessKind::Field { receiver_is_ambiguous_float_literal: false }
+            }
+            it @ DotAccessKind::Method { .. } => *it,
         };
-        if let Some((iter, iter_sym)) = iter.or_else(into_iter) {
-            // Skip iterators, e.g. complete `.iter().filter_map()`.
-            let dot_access_kind = match &dot_access.kind {
-                DotAccessKind::Field { receiver_is_ambiguous_float_literal: _ } => {
-                    DotAccessKind::Field { receiver_is_ambiguous_float_literal: false }
-                }
-                it @ DotAccessKind::Method { .. } => *it,
-            };
-            let dot_access = DotAccess {
-                receiver: dot_access.receiver.clone(),
-                receiver_ty: Some(hir::TypeInfo { original: iter.clone(), adjusted: None }),
-                kind: dot_access_kind,
-                ctx: dot_access.ctx,
-            };
-            complete_methods(ctx, &iter, &traits_in_scope, |func| {
-                acc.add_method(ctx, &dot_access, func, Some(iter_sym.clone()), None)
-            });
-        }
+        let dot_access = DotAccess {
+            receiver: dot_access.receiver.clone(),
+            receiver_ty: Some(hir::TypeInfo { original: iter.clone(), adjusted: None }),
+            kind: dot_access_kind,
+            ctx: dot_access.ctx,
+        };
+        complete_methods(ctx, &iter, &traits_in_scope, |func| {
+            acc.add_method(ctx, &dot_access, func, Some(iter_sym.clone()), None)
+        });
     }
 }
 
diff --git a/crates/ide-completion/src/config.rs b/crates/ide-completion/src/config.rs
index c641df38ff..8b1ce11e8a 100644
--- a/crates/ide-completion/src/config.rs
+++ b/crates/ide-completion/src/config.rs
@@ -14,8 +14,6 @@ pub struct CompletionConfig<'a> {
     pub enable_postfix_completions: bool,
     pub enable_imports_on_the_fly: bool,
     pub enable_self_on_the_fly: bool,
-    pub enable_auto_iter: bool,
-    pub enable_auto_await: bool,
     pub enable_private_editable: bool,
     pub enable_term_search: bool,
     pub term_search_fuel: u64,
diff --git a/crates/project-model/src/toolchain_info/rustc_cfg.rs b/crates/project-model/src/toolchain_info/rustc_cfg.rs
index e472da0c89..4bf9b59e7d 100644
--- a/crates/project-model/src/toolchain_info/rustc_cfg.rs
+++ b/crates/project-model/src/toolchain_info/rustc_cfg.rs
@@ -19,7 +19,7 @@ pub fn get(
     let rustc_cfgs = match rustc_cfgs {
         Ok(cfgs) => cfgs,
         Err(e) => {
-            tracing::warn!(?e, "failed to get rustc cfgs");
+            tracing::error!(?e, "failed to get rustc cfgs");
             return vec![];
         }
     };
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index 44325fa1a2..3dc4379258 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -453,10 +453,6 @@ config_data! {
         ///
         /// In `match` arms it completes a comma instead.
         completion_addSemicolonToUnit: bool = true,
-        /// Toggles the additional completions that automatically show method calls and field accesses with `await` prefixed to them when completing on a future.
-        completion_autoAwait_enable: bool        = true,
-        /// Toggles the additional completions that automatically show method calls with `iter()` or `into_iter()` prefixed to them when completing on a type that has them.
-        completion_autoIter_enable: bool        = true,
         /// Toggles the additional completions that automatically add imports when completed.
         /// Note that your client must specify the `additionalTextEdits` LSP client capability to truly have this feature enabled.
         completion_autoimport_enable: bool       = true,
@@ -1488,8 +1484,6 @@ impl Config {
             enable_imports_on_the_fly: self.completion_autoimport_enable(source_root).to_owned()
                 && self.caps.completion_item_edit_resolve(),
             enable_self_on_the_fly: self.completion_autoself_enable(source_root).to_owned(),
-            enable_auto_iter: *self.completion_autoIter_enable(source_root),
-            enable_auto_await: *self.completion_autoAwait_enable(source_root),
             enable_private_editable: self.completion_privateEditable_enable(source_root).to_owned(),
             full_function_signatures: self
                 .completion_fullFunctionSignatures_enable(source_root)
diff --git a/crates/rust-analyzer/src/flycheck.rs b/crates/rust-analyzer/src/flycheck.rs
index 2309f94a74..22f06d68d8 100644
--- a/crates/rust-analyzer/src/flycheck.rs
+++ b/crates/rust-analyzer/src/flycheck.rs
@@ -88,17 +88,6 @@ pub(crate) enum FlycheckConfig {
     },
 }
 
-impl FlycheckConfig {
-    pub(crate) fn invocation_strategy_once(&self) -> bool {
-        match self {
-            FlycheckConfig::CargoCommand { .. } => false,
-            FlycheckConfig::CustomCommand { invocation_strategy, .. } => {
-                *invocation_strategy == InvocationStrategy::Once
-            }
-        }
-    }
-}
-
 impl fmt::Display for FlycheckConfig {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self {
diff --git a/crates/rust-analyzer/src/handlers/notification.rs b/crates/rust-analyzer/src/handlers/notification.rs
index 84ba89d9f3..98efc637c2 100644
--- a/crates/rust-analyzer/src/handlers/notification.rs
+++ b/crates/rust-analyzer/src/handlers/notification.rs
@@ -291,15 +291,9 @@ fn run_flycheck(state: &mut GlobalState, vfs_path: VfsPath) -> bool {
     let file_id = state.vfs.read().0.file_id(&vfs_path);
     if let Some(file_id) = file_id {
         let world = state.snapshot();
-        let invocation_strategy_once = state.config.flycheck(None).invocation_strategy_once();
         let may_flycheck_workspace = state.config.flycheck_workspace(None);
         let mut updated = false;
         let task = move || -> std::result::Result<(), ide::Cancelled> {
-            if invocation_strategy_once {
-                let saved_file = vfs_path.as_path().map(|p| p.to_owned());
-                world.flycheck[0].restart_workspace(saved_file.clone());
-            }
-
             let target = TargetSpec::for_file(&world, file_id)?.and_then(|it| {
                 let tgt_kind = it.target_kind();
                 let (tgt_name, root, package) = match it {
@@ -326,15 +320,16 @@ fn run_flycheck(state: &mut GlobalState, vfs_path: VfsPath) -> bool {
                 // the user opted into package checks then
                 let package_check_allowed = target.is_some() || !may_flycheck_workspace;
                 if package_check_allowed {
-                    let workspace = world.workspaces.iter().position(|ws| match &ws.kind {
-                        project_model::ProjectWorkspaceKind::Cargo { cargo, .. }
-                        | project_model::ProjectWorkspaceKind::DetachedFile {
-                            cargo: Some((cargo, _, _)),
-                            ..
-                        } => *cargo.workspace_root() == root,
-                        _ => false,
-                    });
-                    if let Some(idx) = workspace {
+                    let workspace =
+                        world.workspaces.iter().enumerate().find(|(_, ws)| match &ws.kind {
+                            project_model::ProjectWorkspaceKind::Cargo { cargo, .. }
+                            | project_model::ProjectWorkspaceKind::DetachedFile {
+                                cargo: Some((cargo, _, _)),
+                                ..
+                            } => *cargo.workspace_root() == root,
+                            _ => false,
+                        });
+                    if let Some((idx, _)) = workspace {
                         world.flycheck[idx].restart_for_package(package, target);
                     }
                 }
diff --git a/crates/rust-analyzer/src/integrated_benchmarks.rs b/crates/rust-analyzer/src/integrated_benchmarks.rs
index 5cdc51a1c1..fcfd06679b 100644
--- a/crates/rust-analyzer/src/integrated_benchmarks.rs
+++ b/crates/rust-analyzer/src/integrated_benchmarks.rs
@@ -176,8 +176,6 @@ fn integrated_completion_benchmark() {
             fields_to_resolve: CompletionFieldsToResolve::empty(),
             exclude_flyimport: vec![],
             exclude_traits: &[],
-            enable_auto_await: true,
-            enable_auto_iter: true,
         };
         let position =
             FilePosition { file_id, offset: TextSize::try_from(completion_offset).unwrap() };
@@ -228,8 +226,6 @@ fn integrated_completion_benchmark() {
             fields_to_resolve: CompletionFieldsToResolve::empty(),
             exclude_flyimport: vec![],
             exclude_traits: &[],
-            enable_auto_await: true,
-            enable_auto_iter: true,
         };
         let position =
             FilePosition { file_id, offset: TextSize::try_from(completion_offset).unwrap() };
@@ -278,8 +274,6 @@ fn integrated_completion_benchmark() {
             fields_to_resolve: CompletionFieldsToResolve::empty(),
             exclude_flyimport: vec![],
             exclude_traits: &[],
-            enable_auto_await: true,
-            enable_auto_iter: true,
         };
         let position =
             FilePosition { file_id, offset: TextSize::try_from(completion_offset).unwrap() };
diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc
index b33de1956b..bd091db58d 100644
--- a/docs/user/generated_config.adoc
+++ b/docs/user/generated_config.adoc
@@ -274,16 +274,6 @@ Whether to automatically add a semicolon when completing unit-returning function
 
 In `match` arms it completes a comma instead.
 --
-[[rust-analyzer.completion.autoAwait.enable]]rust-analyzer.completion.autoAwait.enable (default: `true`)::
-+
---
-Toggles the additional completions that automatically show method calls and field accesses with `await` prefixed to them when completing on a future.
---
-[[rust-analyzer.completion.autoIter.enable]]rust-analyzer.completion.autoIter.enable (default: `true`)::
-+
---
-Toggles the additional completions that automatically show method calls with `iter()` or `into_iter()` prefixed to them when completing on a type that has them.
---
 [[rust-analyzer.completion.autoimport.enable]]rust-analyzer.completion.autoimport.enable (default: `true`)::
 +
 --
diff --git a/editors/code/package.json b/editors/code/package.json
index f148041ac3..8b066377f2 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -1143,26 +1143,6 @@
                     }
                 }
             },
-            {
-                "title": "completion",
-                "properties": {
-                    "rust-analyzer.completion.autoAwait.enable": {
-                        "markdownDescription": "Toggles the additional completions that automatically show method calls and field accesses with `await` prefixed to them when completing on a future.",
-                        "default": true,
-                        "type": "boolean"
-                    }
-                }
-            },
-            {
-                "title": "completion",
-                "properties": {
-                    "rust-analyzer.completion.autoIter.enable": {
-                        "markdownDescription": "Toggles the additional completions that automatically show method calls with `iter()` or `into_iter()` prefixed to them when completing on a type that has them.",
-                        "default": true,
-                        "type": "boolean"
-                    }
-                }
-            },
             {
                 "title": "completion",
                 "properties": {


Test patch:
diff --git a/crates/ide-completion/src/tests.rs b/crates/ide-completion/src/tests.rs
index 9d91f95eb6..b7dbf0a630 100644
--- a/crates/ide-completion/src/tests.rs
+++ b/crates/ide-completion/src/tests.rs
@@ -87,8 +87,6 @@ pub(crate) const TEST_CONFIG: CompletionConfig<'_> = CompletionConfig {
     fields_to_resolve: CompletionFieldsToResolve::empty(),
     exclude_flyimport: vec![],
     exclude_traits: &[],
-    enable_auto_await: true,
-    enable_auto_iter: true,
 };
 
 pub(crate) fn completion_list(#[rust_analyzer::rust_fixture] ra_fixture: &str) -> String {