about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLukas Wirth <lukastw97@gmail.com>2022-06-03 19:48:55 +0200
committerLukas Wirth <lukastw97@gmail.com>2022-06-03 19:49:02 +0200
commit98c0578f157fbd04af6106c658886bbeb1091f1c (patch)
treea1900ebc0ca312bd970e4de153bf3844cf2a4ba7
parent2a60b8452e469f8002834a7ac14a29434d92f12b (diff)
downloadrust-98c0578f157fbd04af6106c658886bbeb1091f1c.tar.gz
rust-98c0578f157fbd04af6106c658886bbeb1091f1c.zip
Move trait_impl completion analysis into CompletionContext
-rw-r--r--crates/ide-completion/src/completions.rs1
-rw-r--r--crates/ide-completion/src/completions/item_list.rs13
-rw-r--r--crates/ide-completion/src/completions/item_list/trait_impl.rs (renamed from crates/ide-completion/src/completions/trait_impl.rs)100
-rw-r--r--crates/ide-completion/src/context.rs254
-rw-r--r--crates/ide-completion/src/lib.rs1
5 files changed, 186 insertions, 183 deletions
diff --git a/crates/ide-completion/src/completions.rs b/crates/ide-completion/src/completions.rs
index b6358d4f40c..b0763584432 100644
--- a/crates/ide-completion/src/completions.rs
+++ b/crates/ide-completion/src/completions.rs
@@ -16,7 +16,6 @@ pub(crate) mod pattern;
 pub(crate) mod postfix;
 pub(crate) mod record;
 pub(crate) mod snippet;
-pub(crate) mod trait_impl;
 pub(crate) mod r#type;
 pub(crate) mod use_;
 pub(crate) mod vis;
diff --git a/crates/ide-completion/src/completions/item_list.rs b/crates/ide-completion/src/completions/item_list.rs
index 287cf46f2e3..9b03d8bc5ff 100644
--- a/crates/ide-completion/src/completions/item_list.rs
+++ b/crates/ide-completion/src/completions/item_list.rs
@@ -6,9 +6,16 @@ use crate::{
     CompletionContext, Completions,
 };
 
+mod trait_impl;
+
 pub(crate) fn complete_item_list(acc: &mut Completions, ctx: &CompletionContext) {
     let _p = profile::span("complete_item_list");
 
+    if let Some(_) = ctx.name_ctx() {
+        trait_impl::complete_trait_impl(acc, ctx);
+        return;
+    }
+
     let (&is_absolute_path, path_qualifier, kind) = match ctx.path_context() {
         Some(PathCompletionCtx {
             kind: PathKind::Item { kind },
@@ -24,7 +31,6 @@ pub(crate) fn complete_item_list(acc: &mut Completions, ctx: &CompletionContext)
         }) => (is_absolute_path, qualifier, None),
         _ => return,
     };
-    let mut add_keyword = |kw, snippet| acc.add_keyword_snippet(ctx, kw, snippet);
 
     let in_item_list = matches!(kind, Some(ItemListKind::SourceFile | ItemListKind::Module) | None);
     let in_assoc_non_trait_impl = matches!(kind, Some(ItemListKind::Impl | ItemListKind::Trait));
@@ -35,6 +41,11 @@ pub(crate) fn complete_item_list(acc: &mut Completions, ctx: &CompletionContext)
     let no_qualifiers = ctx.qualifier_ctx.vis_node.is_none();
     let in_block = matches!(kind, None);
 
+    if in_trait_impl {
+        trait_impl::complete_trait_impl(acc, ctx);
+    }
+    let mut add_keyword = |kw, snippet| acc.add_keyword_snippet(ctx, kw, snippet);
+
     'block: loop {
         if ctx.is_non_trivial_path() {
             break 'block;
diff --git a/crates/ide-completion/src/completions/trait_impl.rs b/crates/ide-completion/src/completions/item_list/trait_impl.rs
index 54bd77526e9..627752b1cdc 100644
--- a/crates/ide-completion/src/completions/trait_impl.rs
+++ b/crates/ide-completion/src/completions/item_list/trait_impl.rs
@@ -43,6 +43,7 @@ use syntax::{
 use text_edit::TextEdit;
 
 use crate::{
+    context::{ItemListKind, NameContext, NameKind, NameRefContext, PathCompletionCtx, PathKind},
     CompletionContext, CompletionItem, CompletionItemKind, CompletionRelevance, Completions,
 };
 
@@ -54,7 +55,6 @@ enum ImplCompletionKind {
     Const,
 }
 
-// FIXME: Make this a submodule of [`item_list`]
 pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext) {
     if let Some((kind, replacement_range, impl_def)) = completion_match(ctx) {
         if let Some(hir_impl) = ctx.sema.to_def(&impl_def) {
@@ -77,74 +77,48 @@ pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext
     }
 }
 
-// FIXME: This should be lifted out so that we can do proper smart item keyword completions
 fn completion_match(ctx: &CompletionContext) -> Option<(ImplCompletionKind, TextRange, ast::Impl)> {
     let token = ctx.token.clone();
 
-    // For keyword without name like `impl .. { fn $0 }`, the current position is inside
-    // the whitespace token, which is outside `FN` syntax node.
-    // We need to follow the previous token in this case.
-    let mut token_before_ws = token.clone();
-    if token.kind() == SyntaxKind::WHITESPACE {
-        token_before_ws = token.prev_token()?;
-    }
-
-    let parent_kind = token_before_ws.parent().map_or(SyntaxKind::EOF, |it| it.kind());
-    if token.parent().map(|n| n.kind()) == Some(SyntaxKind::ASSOC_ITEM_LIST)
-        && matches!(
-            token_before_ws.kind(),
-            SyntaxKind::SEMICOLON | SyntaxKind::R_CURLY | SyntaxKind::L_CURLY
-        )
-    {
-        let impl_def = ast::Impl::cast(token.parent()?.parent()?)?;
-        let kind = ImplCompletionKind::All;
-        let replacement_range = TextRange::empty(ctx.position.offset);
-        Some((kind, replacement_range, impl_def))
-    } else {
-        let impl_item_offset = match token_before_ws.kind() {
-            // `impl .. { const $0 }`
-            // ERROR      0
-            //   CONST_KW <- *
-            T![const] => 0,
-            // `impl .. { fn/type $0 }`
-            // FN/TYPE_ALIAS  0
-            //   FN_KW        <- *
-            T![fn] | T![type] => 0,
-            // `impl .. { fn/type/const foo$0 }`
-            // FN/TYPE_ALIAS/CONST  1
-            //  NAME                0
-            //    IDENT             <- *
-            SyntaxKind::IDENT if parent_kind == SyntaxKind::NAME => 1,
-            // `impl .. { foo$0 }`
-            // MACRO_CALL       3
-            //  PATH            2
-            //    PATH_SEGMENT  1
-            //      NAME_REF    0
-            //        IDENT     <- *
-            SyntaxKind::IDENT if parent_kind == SyntaxKind::NAME_REF => 3,
+    if let Some(NameContext { name, kind, .. }) = ctx.name_ctx() {
+        let kind = match kind {
+            NameKind::Const => ImplCompletionKind::Const,
+            NameKind::Function => ImplCompletionKind::Fn,
+            NameKind::TypeAlias => ImplCompletionKind::TypeAlias,
             _ => return None,
         };
-
-        let impl_item = token_before_ws.ancestors().nth(impl_item_offset)?;
-        // Must directly belong to an impl block.
-        // IMPL
-        //   ASSOC_ITEM_LIST
-        //     <item>
-        let impl_def = ast::Impl::cast(impl_item.parent()?.parent()?)?;
-        let kind = match impl_item.kind() {
-            // `impl ... { const $0 fn/type/const }`
-            _ if token_before_ws.kind() == T![const] => ImplCompletionKind::Const,
-            SyntaxKind::CONST | SyntaxKind::ERROR => ImplCompletionKind::Const,
-            SyntaxKind::TYPE_ALIAS => ImplCompletionKind::TypeAlias,
-            SyntaxKind::FN => ImplCompletionKind::Fn,
-            SyntaxKind::MACRO_CALL => ImplCompletionKind::All,
-            _ => return None,
-        };
-
-        let replacement_range = replacement_range(ctx, &impl_item);
-
-        Some((kind, replacement_range, impl_def))
+        let item = match name {
+            Some(name) => name.syntax().parent(),
+            None => {
+                if token.kind() == SyntaxKind::WHITESPACE { token.prev_token()? } else { token }
+                    .parent()
+            }
+        }?;
+        return Some((
+            kind,
+            replacement_range(ctx, &item),
+            // item -> ASSOC_ITEM_LIST -> IMPL
+            ast::Impl::cast(item.parent()?.parent()?)?,
+        ));
+    } else if let Some(NameRefContext {
+        nameref,
+        path_ctx:
+            Some(PathCompletionCtx { kind: PathKind::Item { kind: ItemListKind::TraitImpl }, .. }),
+        ..
+    }) = ctx.nameref_ctx()
+    {
+        if !ctx.is_non_trivial_path() {
+            return Some((
+                ImplCompletionKind::All,
+                match nameref {
+                    Some(name) => name.syntax().text_range(),
+                    None => TextRange::empty(ctx.position.offset),
+                },
+                ctx.impl_def.clone()?,
+            ));
+        }
     }
+    None
 }
 
 fn add_function_impl(
diff --git a/crates/ide-completion/src/context.rs b/crates/ide-completion/src/context.rs
index 6068a9eb32c..83815f6d5dc 100644
--- a/crates/ide-completion/src/context.rs
+++ b/crates/ide-completion/src/context.rs
@@ -101,8 +101,6 @@ pub(crate) struct PathCompletionCtx {
     pub(super) is_absolute_path: bool,
     /// The qualifier of the current path if it exists.
     pub(super) qualifier: Option<PathQualifierCtx>,
-    #[allow(dead_code)]
-    // FIXME: use this
     /// The parent of the path we are completing.
     pub(super) parent: Option<ast::Path>,
     pub(super) kind: PathKind,
@@ -110,6 +108,23 @@ pub(crate) struct PathCompletionCtx {
     pub(super) has_type_args: bool,
 }
 
+impl PathCompletionCtx {
+    fn is_trivial_path(&self) -> bool {
+        matches!(
+            self,
+            PathCompletionCtx {
+                has_call_parens: false,
+                has_macro_bang: false,
+                is_absolute_path: false,
+                qualifier: None,
+                parent: None,
+                has_type_args: false,
+                ..
+            }
+        )
+    }
+}
+
 #[derive(Debug)]
 pub(crate) struct PathQualifierCtx {
     pub(crate) path: ast::Path,
@@ -365,13 +380,7 @@ impl<'a> CompletionContext<'a> {
     }
 
     pub(crate) fn is_non_trivial_path(&self) -> bool {
-        matches!(
-            self.path_context(),
-            Some(
-                PathCompletionCtx { is_absolute_path: true, .. }
-                    | PathCompletionCtx { qualifier: Some(_), .. }
-            )
-        )
+        self.path_context().as_ref().map_or(false, |it| !it.is_trivial_path())
     }
 
     pub(crate) fn path_qual(&self) -> Option<&ast::Path> {
@@ -872,7 +881,7 @@ impl<'a> CompletionContext<'a> {
                 find_node_at_offset(&file_with_fake_ident, offset)
             {
                 let parent = name_ref.syntax().parent()?;
-                let (mut nameref_ctx, _) =
+                let (mut nameref_ctx, _, _) =
                     Self::classify_name_ref(&self.sema, &original_file, name_ref, parent);
                 if let Some(path_ctx) = &mut nameref_ctx.path_ctx {
                     path_ctx.kind = PathKind::Derive;
@@ -920,13 +929,23 @@ impl<'a> CompletionContext<'a> {
         self.impl_def = self
             .sema
             .token_ancestors_with_macros(self.token.clone())
-            .take_while(|it| it.kind() != SOURCE_FILE && it.kind() != MODULE)
-            .find_map(ast::Impl::cast);
+            .take_while(|it| it.kind() != SOURCE_FILE)
+            .filter_map(ast::Item::cast)
+            .take(2)
+            .find_map(|it| match it {
+                ast::Item::Impl(impl_) => Some(impl_),
+                _ => None,
+            });
         self.function_def = self
             .sema
             .token_ancestors_with_macros(self.token.clone())
             .take_while(|it| it.kind() != SOURCE_FILE && it.kind() != MODULE)
-            .find_map(ast::Fn::cast);
+            .filter_map(ast::Item::cast)
+            .take(2)
+            .find_map(|it| match it {
+                ast::Item::Fn(fn_) => Some(fn_),
+                _ => None,
+            });
 
         match name_like {
             ast::NameLike::Lifetime(lifetime) => {
@@ -938,50 +957,10 @@ impl<'a> CompletionContext<'a> {
             }
             ast::NameLike::NameRef(name_ref) => {
                 let parent = name_ref.syntax().parent()?;
-                let (nameref_ctx, pat_ctx) =
+                let (nameref_ctx, pat_ctx, qualifier_ctx) =
                     Self::classify_name_ref(&self.sema, &original_file, name_ref, parent.clone());
 
-                // Extract qualifiers
-                if let Some(path_ctx) = &nameref_ctx.path_ctx {
-                    if path_ctx.qualifier.is_none() {
-                        let top = match path_ctx.kind {
-                            PathKind::Expr { in_block_expr: true, .. } => parent
-                                .ancestors()
-                                .find(|it| ast::PathExpr::can_cast(it.kind()))
-                                .and_then(|p| {
-                                    let parent = p.parent()?;
-                                    if ast::StmtList::can_cast(parent.kind()) {
-                                        Some(p)
-                                    } else if ast::ExprStmt::can_cast(parent.kind()) {
-                                        Some(parent)
-                                    } else {
-                                        None
-                                    }
-                                }),
-                            PathKind::Item { .. } => {
-                                parent.ancestors().find(|it| ast::MacroCall::can_cast(it.kind()))
-                            }
-                            _ => None,
-                        };
-                        if let Some(top) = top {
-                            if let Some(NodeOrToken::Node(error_node)) =
-                                syntax::algo::non_trivia_sibling(
-                                    top.into(),
-                                    syntax::Direction::Prev,
-                                )
-                            {
-                                if error_node.kind() == SyntaxKind::ERROR {
-                                    self.qualifier_ctx.unsafe_tok = error_node
-                                        .children_with_tokens()
-                                        .filter_map(NodeOrToken::into_token)
-                                        .find(|it| it.kind() == T![unsafe]);
-                                    self.qualifier_ctx.vis_node =
-                                        error_node.children().find_map(ast::Visibility::cast);
-                                }
-                            }
-                        }
-                    }
-                }
+                self.qualifier_ctx = qualifier_ctx;
                 self.ident_ctx = IdentContext::NameRef(nameref_ctx);
                 self.pattern_ctx = pat_ctx;
             }
@@ -1070,40 +1049,44 @@ impl<'a> CompletionContext<'a> {
         original_file: &SyntaxNode,
         name_ref: ast::NameRef,
         parent: SyntaxNode,
-    ) -> (NameRefContext, Option<PatternContext>) {
+    ) -> (NameRefContext, Option<PatternContext>, QualifierCtx) {
         let nameref = find_node_at_offset(&original_file, name_ref.syntax().text_range().start());
 
-        let mut nameref_ctx = NameRefContext {
-            dot_access: None,
-            path_ctx: None,
-            nameref,
-            record_expr: None,
-            keyword: None,
-        };
+        let mut res = (
+            NameRefContext {
+                dot_access: None,
+                path_ctx: None,
+                nameref,
+                record_expr: None,
+                keyword: None,
+            },
+            None,
+            QualifierCtx::default(),
+        );
+        let (nameref_ctx, pattern_ctx, qualifier_ctx) = &mut res;
 
         if let Some(record_field) = ast::RecordExprField::for_field_name(&name_ref) {
             nameref_ctx.record_expr =
                 find_node_in_file_compensated(original_file, &record_field.parent_record_lit())
                     .zip(Some(false));
-            return (nameref_ctx, None);
+            return res;
         }
         if let Some(record_field) = ast::RecordPatField::for_field_name_ref(&name_ref) {
-            let pat_ctx =
-                pattern_context_for(original_file, record_field.parent_record_pat().clone().into());
-            return (
-                nameref_ctx,
-                Some(PatternContext {
-                    param_ctx: None,
-                    has_type_ascription: false,
-                    ref_token: None,
-                    mut_token: None,
-                    record_pat: find_node_in_file_compensated(
-                        original_file,
-                        &record_field.parent_record_pat(),
-                    ),
-                    ..pat_ctx
-                }),
-            );
+            *pattern_ctx = Some(PatternContext {
+                param_ctx: None,
+                has_type_ascription: false,
+                ref_token: None,
+                mut_token: None,
+                record_pat: find_node_in_file_compensated(
+                    original_file,
+                    &record_field.parent_record_pat(),
+                ),
+                ..pattern_context_for(
+                    original_file,
+                    record_field.parent_record_pat().clone().into(),
+                )
+            });
+            return res;
         }
 
         let segment = match_ast! {
@@ -1123,7 +1106,7 @@ impl<'a> CompletionContext<'a> {
                         kind: DotAccessKind::Field { receiver_is_ambiguous_float_literal },
                         receiver
                     });
-                    return (nameref_ctx, None);
+                    return res;
                 },
                 ast::MethodCallExpr(method) => {
                     let receiver = find_in_original_file(method.receiver(), original_file);
@@ -1132,9 +1115,9 @@ impl<'a> CompletionContext<'a> {
                         kind: DotAccessKind::Method { has_parens: method.arg_list().map_or(false, |it| it.l_paren_token().is_some()) },
                         receiver
                     });
-                    return (nameref_ctx, None);
+                    return res;
                 },
-                _ => return (nameref_ctx, None),
+                _ => return res,
             }
         };
 
@@ -1148,7 +1131,6 @@ impl<'a> CompletionContext<'a> {
             kind: PathKind::Item { kind: ItemListKind::SourceFile },
             has_type_args: false,
         };
-        let mut pat_ctx = None;
 
         let is_in_block = |it: &SyntaxNode| {
             it.parent()
@@ -1205,9 +1187,9 @@ impl<'a> CompletionContext<'a> {
             None
         };
 
-        let kind = path.syntax().ancestors().find_map(|it| {
-            // using Option<Option<PathKind>> as extra controlflow
-            let kind = match_ast! {
+        // Infer the path kind
+        let kind = path.syntax().parent().and_then(|it| {
+            match_ast! {
                 match it {
                     ast::PathType(it) => Some(PathKind::Type {
                         in_tuple_struct: it.syntax().parent().map_or(false, |it| ast::TupleField::can_cast(it.kind()))
@@ -1217,7 +1199,7 @@ impl<'a> CompletionContext<'a> {
                             if ast::ExprStmt::can_cast(p.kind()) {
                                 if let Some(kind) = inbetween_body_and_decl_check(p) {
                                     nameref_ctx.keyword = Some(kind);
-                                    return Some(None);
+                                    return None;
                                 }
                             }
                         }
@@ -1233,22 +1215,22 @@ impl<'a> CompletionContext<'a> {
                     },
                     ast::TupleStructPat(it) => {
                         path_ctx.has_call_parens = true;
-                        pat_ctx = Some(pattern_context_for(original_file, it.into()));
+                        *pattern_ctx = Some(pattern_context_for(original_file, it.into()));
                         Some(PathKind::Pat)
                     },
                     ast::RecordPat(it) => {
                         path_ctx.has_call_parens = true;
-                        pat_ctx = Some(pattern_context_for(original_file, it.into()));
+                        *pattern_ctx = Some(pattern_context_for(original_file, it.into()));
                         Some(PathKind::Pat)
                     },
                     ast::PathPat(it) => {
-                        pat_ctx = Some(pattern_context_for(original_file, it.into()));
+                        *pattern_ctx = Some(pattern_context_for(original_file, it.into()));
                         Some(PathKind::Pat)
                     },
                     ast::MacroCall(it) => {
                         if let Some(kind) = inbetween_body_and_decl_check(it.syntax().clone()) {
                             nameref_ctx.keyword = Some(kind);
-                            return Some(None);
+                            return None;
                         }
 
                         path_ctx.has_macro_bang = it.excl_token().is_some();
@@ -1266,21 +1248,21 @@ impl<'a> CompletionContext<'a> {
                                         } else {
                                             ItemListKind::Impl
                                         },
-                                        _ => return Some(None)
+                                        _ => return None
                                     }
                                 },
-                                None => return Some(None),
+                                None => return None,
                             } }),
                             Some(SyntaxKind::EXTERN_ITEM_LIST) => Some(PathKind::Item { kind: ItemListKind::ExternBlock }),
                             Some(SyntaxKind::SOURCE_FILE) => Some(PathKind::Item { kind: ItemListKind::SourceFile }),
                             _ => {
-                               return Some(parent.and_then(ast::MacroExpr::cast).map(|it| {
+                               return parent.and_then(ast::MacroExpr::cast).map(|it| {
                                     let in_loop_body = is_in_loop_body(it.syntax());
                                     let in_block_expr = is_in_block(it.syntax());
                                     let after_if_expr = after_if_expr(it.syntax().clone());
                                     fill_record_expr(it.syntax());
                                     PathKind::Expr { in_block_expr, in_loop_body, after_if_expr }
-                                }));
+                                });
                             },
                         }
                     },
@@ -1302,30 +1284,14 @@ impl<'a> CompletionContext<'a> {
                     })(),
                     ast::Visibility(it) => Some(PathKind::Vis { has_in_token: it.in_token().is_some() }),
                     ast::UseTree(_) => Some(PathKind::Use),
-                    ast::ItemList(_) => Some(PathKind::Item { kind: ItemListKind::Module }),
-                    ast::AssocItemList(it) => Some(PathKind::Item { kind: {
-                        match_ast! {
-                            match (it.syntax().parent()?) {
-                                ast::Trait(_) => ItemListKind::Trait,
-                                ast::Impl(it) => if it.trait_().is_some() {
-                                    ItemListKind::TraitImpl
-                                } else {
-                                    ItemListKind::Impl
-                                },
-                                _ => return None
-                            }
-                        }
-                    }}),
-                    ast::ExternItemList(_) => Some(PathKind::Item { kind: ItemListKind::ExternBlock }),
-                    ast::SourceFile(_) => Some(PathKind::Item { kind: ItemListKind::SourceFile }),
                     _ => return None,
                 }
-            };
-            Some(kind)
-        }).flatten();
+            }
+        });
+
         match kind {
             Some(kind) => path_ctx.kind = kind,
-            None => return (nameref_ctx, pat_ctx),
+            None => return res,
         }
         path_ctx.has_type_args = segment.generic_arg_list().is_some();
 
@@ -1367,8 +1333,62 @@ impl<'a> CompletionContext<'a> {
                 path_ctx.is_absolute_path = true;
             }
         }
+
+        if path_ctx.is_trivial_path() {
+            // fetch the full expression that may have qualifiers attached to it
+            let top_node = match path_ctx.kind {
+                PathKind::Expr { in_block_expr: true, .. } => {
+                    parent.ancestors().find(|it| ast::PathExpr::can_cast(it.kind())).and_then(|p| {
+                        let parent = p.parent()?;
+                        if ast::StmtList::can_cast(parent.kind()) {
+                            Some(p)
+                        } else if ast::ExprStmt::can_cast(parent.kind()) {
+                            Some(parent)
+                        } else {
+                            None
+                        }
+                    })
+                }
+                PathKind::Item { .. } => {
+                    parent.ancestors().find(|it| ast::MacroCall::can_cast(it.kind()))
+                }
+                _ => None,
+            };
+            if let Some(top) = top_node {
+                if let Some(NodeOrToken::Node(error_node)) =
+                    syntax::algo::non_trivia_sibling(top.clone().into(), syntax::Direction::Prev)
+                {
+                    if error_node.kind() == SyntaxKind::ERROR {
+                        qualifier_ctx.unsafe_tok = error_node
+                            .children_with_tokens()
+                            .filter_map(NodeOrToken::into_token)
+                            .find(|it| it.kind() == T![unsafe]);
+                        qualifier_ctx.vis_node =
+                            error_node.children().find_map(ast::Visibility::cast);
+                    }
+                }
+
+                if let Some(PathKind::Item { .. }) = kind {
+                    if qualifier_ctx.none() {
+                        if let Some(t) = top.first_token() {
+                            if let Some(prev) = t
+                                .prev_token()
+                                .and_then(|t| syntax::algo::skip_trivia_token(t, Direction::Prev))
+                            {
+                                if ![T![;], T!['}'], T!['{']].contains(&prev.kind()) {
+                                    // This was inferred to be an item position path, but it seems
+                                    // to be part of some other broken node which leaked into an item
+                                    // list, so return without setting the path context
+                                    return res;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
         nameref_ctx.path_ctx = Some(path_ctx);
-        (nameref_ctx, pat_ctx)
+        res
     }
 }
 
diff --git a/crates/ide-completion/src/lib.rs b/crates/ide-completion/src/lib.rs
index c100dd63eac..3269e4926a7 100644
--- a/crates/ide-completion/src/lib.rs
+++ b/crates/ide-completion/src/lib.rs
@@ -173,7 +173,6 @@ pub fn completions(
             completions::record::complete_record(acc, ctx);
             completions::snippet::complete_expr_snippet(acc, ctx);
             completions::snippet::complete_item_snippet(acc, ctx);
-            completions::trait_impl::complete_trait_impl(acc, ctx);
             completions::r#type::complete_type_path(acc, ctx);
             completions::r#type::complete_inferred_type(acc, ctx);
             completions::use_::complete_use_tree(acc, ctx);