Repository: rust-analyzer/rust-analyzer
Pull request #10739 (2021-11-10 17:27:10)

internal: Simplify
bors r+


Patch:
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index b09c0e753b..c753369bfd 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -897,13 +897,13 @@ impl<'db> SemanticsImpl<'db> {
     }
 
     fn scope(&self, node: &SyntaxNode) -> SemanticsScope<'db> {
-        let sa = self.analyze(node);
-        SemanticsScope { db: self.db, file_id: sa.file_id, resolver: sa.resolver }
+        let SourceAnalyzer { file_id, resolver, .. } = self.analyze(node);
+        SemanticsScope { db: self.db, file_id, resolver }
     }
 
     fn scope_at_offset(&self, node: &SyntaxNode, offset: TextSize) -> SemanticsScope<'db> {
-        let sa = self.analyze_with_offset(node, offset);
-        SemanticsScope { db: self.db, file_id: sa.file_id, resolver: sa.resolver }
+        let SourceAnalyzer { file_id, resolver, .. } = self.analyze_with_offset(node, offset);
+        SemanticsScope { db: self.db, file_id, resolver }
     }
 
     fn scope_for_def(&self, def: Trait) -> SemanticsScope<'db> {
@@ -924,9 +924,11 @@ impl<'db> SemanticsImpl<'db> {
     fn analyze(&self, node: &SyntaxNode) -> SourceAnalyzer {
         self.analyze_impl(node, None)
     }
+
     fn analyze_with_offset(&self, node: &SyntaxNode, offset: TextSize) -> SourceAnalyzer {
         self.analyze_impl(node, Some(offset))
     }
+
     fn analyze_impl(&self, node: &SyntaxNode, offset: Option<TextSize>) -> SourceAnalyzer {
         let _p = profile::span("Semantics::analyze_impl");
         let node = self.find_file(node.clone());
diff --git a/crates/hir_ty/src/db.rs b/crates/hir_ty/src/db.rs
index 3a787aa47f..98a5849001 100644
--- a/crates/hir_ty/src/db.rs
+++ b/crates/hir_ty/src/db.rs
@@ -77,9 +77,6 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
     #[salsa::invoke(InherentImpls::inherent_impls_in_crate_query)]
     fn inherent_impls_in_crate(&self, krate: CrateId) -> Arc<InherentImpls>;
 
-    #[salsa::invoke(InherentImpls::inherent_impls_in_block_query)]
-    fn inherent_impls_in_block(&self, block: BlockId) -> Option<Arc<InherentImpls>>;
-
     #[salsa::invoke(TraitImpls::trait_impls_in_crate_query)]
     fn trait_impls_in_crate(&self, krate: CrateId) -> Arc<TraitImpls>;
 
diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs
index cdc3e03951..eabe3acdcd 100644
--- a/crates/hir_ty/src/method_resolution.rs
+++ b/crates/hir_ty/src/method_resolution.rs
@@ -13,6 +13,7 @@ use hir_def::{
 };
 use hir_expand::name::Name;
 use rustc_hash::{FxHashMap, FxHashSet};
+use stdx::never;
 
 use crate::{
     autoderef,
@@ -261,45 +262,33 @@ impl InherentImpls {
         let mut impls = Self { map: FxHashMap::default() };
 
         let crate_def_map = db.crate_def_map(krate);
-        impls.collect_def_map(db, &crate_def_map);
+        collect_def_map(db, &crate_def_map, &mut impls);
 
         return Arc::new(impls);
-    }
-
-    pub(crate) fn inherent_impls_in_block_query(
-        db: &dyn HirDatabase,
-        block: BlockId,
-    ) -> Option<Arc<Self>> {
-        let mut impls = Self { map: FxHashMap::default() };
-        if let Some(block_def_map) = db.block_def_map(block) {
-            impls.collect_def_map(db, &block_def_map);
-            return Some(Arc::new(impls));
-        }
-        return None;
-    }
-
-    fn collect_def_map(&mut self, db: &dyn HirDatabase, def_map: &DefMap) {
-        for (_module_id, module_data) in def_map.modules() {
-            for impl_id in module_data.scope.impls() {
-                let data = db.impl_data(impl_id);
-                if data.target_trait.is_some() {
-                    continue;
-                }
 
-                let self_ty = db.impl_self_ty(impl_id);
-                let fp = TyFingerprint::for_inherent_impl(self_ty.skip_binders());
-                if let Some(fp) = fp {
-                    self.map.entry(fp).or_default().push(impl_id);
+        fn collect_def_map(db: &dyn HirDatabase, def_map: &DefMap, impls: &mut InherentImpls) {
+            for (_module_id, module_data) in def_map.modules() {
+                for impl_id in module_data.scope.impls() {
+                    let data = db.impl_data(impl_id);
+                    if data.target_trait.is_some() {
+                        continue;
+                    }
+
+                    let self_ty = db.impl_self_ty(impl_id);
+                    let fp = TyFingerprint::for_inherent_impl(self_ty.skip_binders());
+                    if let Some(fp) = fp {
+                        impls.map.entry(fp).or_default().push(impl_id);
+                    }
+                    // `fp` should only be `None` in error cases (either erroneous code or incomplete name resolution)
                 }
-                // `fp` should only be `None` in error cases (either erroneous code or incomplete name resolution)
-            }
 
-            // To better support custom derives, collect impls in all unnamed const items.
-            // const _: () = { ... };
-            for konst in module_data.scope.unnamed_consts() {
-                let body = db.body(konst.into());
-                for (_, block_def_map) in body.blocks(db.upcast()) {
-                    self.collect_def_map(db, &block_def_map);
+                // To better support custom derives, collect impls in all unnamed const items.
+                // const _: () = { ... };
+                for konst in module_data.scope.unnamed_consts() {
+                    let body = db.body(konst.into());
+                    for (_, block_def_map) in body.blocks(db.upcast()) {
+                        collect_def_map(db, &block_def_map, impls);
+                    }
                 }
             }
         }
@@ -334,7 +323,7 @@ pub fn def_crates(
             }};
         }
 
-    let mod_to_crate_ids = |module: ModuleId| Some(std::iter::once(module.krate()).collect());
+    let mod_to_crate_ids = |module: ModuleId| Some(iter::once(module.krate()).collect());
 
     let lang_item_targets = match ty.kind(&Interner) {
         TyKind::Adt(AdtId(def_id), _) => {
@@ -533,9 +522,16 @@ fn iterate_method_candidates_with_autoref(
     name: Option<&Name>,
     mut callback: &mut dyn FnMut(&Canonical<Ty>, AssocItemId) -> ControlFlow<()>,
 ) -> ControlFlow<()> {
+    let (receiver_ty, rest) = match deref_chain.split_first() {
+        Some((rec, rest)) => (rec.clone(), rest),
+        None => {
+            never!("received empty deref-chain");
+            return ControlFlow::Break(());
+        }
+    };
     iterate_method_candidates_by_receiver(
-        &deref_chain[0],
-        &deref_chain[1..],
+        &receiver_ty,
+        &rest,
         db,
         env.clone(),
         krate,
@@ -546,8 +542,8 @@ fn iterate_method_candidates_with_autoref(
     )?;
 
     let refed = Canonical {
-        binders: deref_chain[0].binders.clone(),
-        value: TyKind::Ref(Mutability::Not, static_lifetime(), deref_chain[0].value.clone())
+        binders: receiver_ty.binders.clone(),
+        value: TyKind::Ref(Mutability::Not, static_lifetime(), receiver_ty.value.clone())
             .intern(&Interner),
     };
 
@@ -564,9 +560,8 @@ fn iterate_method_candidates_with_autoref(
     )?;
 
     let ref_muted = Canonical {
-        binders: deref_chain[0].binders.clone(),
-        value: TyKind::Ref(Mutability::Mut, static_lifetime(), deref_chain[0].value.clone())
-            .intern(&Interner),
+        binders: receiver_ty.binders,
+        value: TyKind::Ref(Mutability::Mut, static_lifetime(), receiver_ty.value).intern(&Interner),
     };
 
     iterate_method_candidates_by_receiver(
@@ -596,7 +591,7 @@ fn iterate_method_candidates_by_receiver(
     // We're looking for methods with *receiver* type receiver_ty. These could
     // be found in any of the derefs of receiver_ty, so we have to go through
     // that.
-    for self_ty in std::iter::once(receiver_ty).chain(rest_of_deref_chain) {
+    for self_ty in iter::once(receiver_ty).chain(rest_of_deref_chain) {
         iterate_inherent_methods(
             self_ty,
             db,
@@ -609,7 +604,7 @@ fn iterate_method_candidates_by_receiver(
         )?
     }
 
-    for self_ty in std::iter::once(receiver_ty).chain(rest_of_deref_chain) {
+    for self_ty in iter::once(receiver_ty).chain(rest_of_deref_chain) {
         iterate_trait_method_candidates(
             self_ty,
             db,
@@ -671,8 +666,7 @@ fn iterate_trait_method_candidates(
         }
         _ => Vec::new(),
     };
-    let traits =
-        inherent_trait.chain(env_traits.into_iter()).chain(traits_in_scope.iter().copied());
+    let traits = inherent_trait.chain(env_traits).chain(traits_in_scope.iter().copied());
 
     'traits: for t in traits {
         let data = db.trait_data(t);
@@ -756,51 +750,13 @@ fn iterate_inherent_methods(
         None => return ControlFlow::Continue(()),
     };
 
-    if let Some(module_id) = visible_from_module {
-        if let Some(block_id) = module_id.containing_block() {
-            if let Some(impls) = db.inherent_impls_in_block(block_id) {
-                impls_for_self_ty(
-                    &impls,
-                    self_ty,
-                    db,
-                    env.clone(),
-                    name,
-                    receiver_ty,
-                    visible_from_module,
-                    callback,
-                )?;
-            }
-        }
-    }
-
     for krate in def_crates {
         let impls = db.inherent_impls_in_crate(krate);
-        impls_for_self_ty(
-            &impls,
-            self_ty,
-            db,
-            env.clone(),
-            name,
-            receiver_ty,
-            visible_from_module,
-            callback,
-        )?;
-    }
-    return ControlFlow::Continue(());
 
-    fn impls_for_self_ty(
-        impls: &InherentImpls,
-        self_ty: &Canonical<Ty>,
-        db: &dyn HirDatabase,
-        env: Arc<TraitEnvironment>,
-        name: Option<&Name>,
-        receiver_ty: Option<&Canonical<Ty>>,
-        visible_from_module: Option<ModuleId>,
-        callback: &mut dyn FnMut(&Canonical<Ty>, AssocItemId) -> ControlFlow<()>,
-    ) -> ControlFlow<()> {
-        let impls_for_self_ty = filter_inherent_impls_for_self_ty(impls, &self_ty.value);
+        let impls_for_self_ty = filter_inherent_impls_for_self_ty(&impls, &self_ty.value);
+
         for &impl_def in impls_for_self_ty {
-            for &item in db.impl_data(impl_def).items.iter() {
+            for &item in &db.impl_data(impl_def).items {
                 if !is_valid_candidate(
                     db,
                     env.clone(),
@@ -826,8 +782,8 @@ fn iterate_inherent_methods(
                 callback(receiver_ty, item)?;
             }
         }
-        ControlFlow::Continue(())
     }
+    ControlFlow::Continue(())
 }
 
 /// Returns the self type for the index trait call.
diff --git a/crates/ide_completion/src/context.rs b/crates/ide_completion/src/context.rs
index 3f40260d33..05ae95769b 100644
--- a/crates/ide_completion/src/context.rs
+++ b/crates/ide_completion/src/context.rs
@@ -350,29 +350,28 @@ impl<'a> CompletionContext<'a> {
 impl<'a> CompletionContext<'a> {
     pub(super) fn new(
         db: &'a RootDatabase,
-        position: FilePosition,
+        position @ FilePosition { file_id, offset }: FilePosition,
         config: &'a CompletionConfig,
     ) -> Option<CompletionContext<'a>> {
         let _p = profile::span("CompletionContext::new");
         let sema = Semantics::new(db);
 
-        let original_file = sema.parse(position.file_id);
+        let original_file = sema.parse(file_id);
 
         // Insert a fake ident to get a valid parse tree. We will use this file
         // to determine context, though the original_file will be used for
         // actual completion.
         let file_with_fake_ident = {
-            let parse = db.parse(position.file_id);
-            let edit = Indel::insert(position.offset, "intellijRulezz".to_string());
+            let parse = db.parse(file_id);
+            let edit = Indel::insert(offset, "intellijRulezz".to_string());
             parse.reparse(&edit).tree()
         };
         let fake_ident_token =
-            file_with_fake_ident.syntax().token_at_offset(position.offset).right_biased().unwrap();
+            file_with_fake_ident.syntax().token_at_offset(offset).right_biased().unwrap();
 
-        let original_token =
-            original_file.syntax().token_at_offset(position.offset).left_biased()?;
+        let original_token = original_file.syntax().token_at_offset(offset).left_biased()?;
         let token = sema.descend_into_macros_single(original_token.clone());
-        let scope = sema.scope_at_offset(&token, position.offset);
+        let scope = sema.scope_at_offset(&token, offset);
         let krate = scope.krate();
         let mut locals = vec![];
         scope.process_all_names(&mut |name, scope| {
@@ -408,7 +407,7 @@ impl<'a> CompletionContext<'a> {
         ctx.expand_and_fill(
             original_file.syntax().clone(),
             file_with_fake_ident.syntax().clone(),
-            position.offset,
+            offset,
             fake_ident_token,
         );
         Some(ctx)


Test patch:
diff --git a/crates/hir_ty/src/tests/method_resolution.rs b/crates/hir_ty/src/tests/method_resolution.rs
index 9b1f682b61..26078a4b2f 100644
--- a/crates/hir_ty/src/tests/method_resolution.rs
+++ b/crates/hir_ty/src/tests/method_resolution.rs
@@ -1386,24 +1386,3 @@ fn f<S: Sized, T, U: ?Sized>() {
         "#]],
     );
 }
-
-#[test]
-fn local_impl() {
-    check_types(
-        r#"
-fn main() {
-    struct SomeStruct(i32);
-
-    impl SomeStruct {
-        fn is_even(&self) -> bool {
-            self.0 % 2 == 0
-        }
-    }
-
-    let o = SomeStruct(3);
-    let is_even = o.is_even();
-     // ^^^^^^^ bool
-}
-    "#,
-    );
-}