]> git.lizzy.rs Git - rust.git/blobdiff - crates/ide_completion/src/completions/qualified_path.rs
Merge #11393
[rust.git] / crates / ide_completion / src / completions / qualified_path.rs
index 656d46b10bec04793c56a1efca065587c82ed695..85df19f1dd49253830598131dbf17130ba27d3a5 100644 (file)
@@ -2,7 +2,7 @@
 
 use std::iter;
 
-use hir::ScopeDef;
+use hir::{ScopeDef, Trait};
 use rustc_hash::FxHashSet;
 use syntax::{ast, AstNode};
 
@@ -27,12 +27,31 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
         _ => return,
     };
 
+    // special case `<_>::$0` as this doesn't resolve to anything.
+    if path.qualifier().is_none() {
+        if matches!(
+            path.segment().and_then(|it| it.kind()),
+            Some(ast::PathSegmentKind::Type {
+                type_ref: Some(ast::Type::InferType(_)),
+                trait_ref: None,
+            })
+        ) {
+            cov_mark::hit!(completion_type_anchor_empty);
+            ctx.scope
+                .visible_traits()
+                .into_iter()
+                .flat_map(|it| Trait::from(it).items(ctx.sema.db))
+                .for_each(|item| add_assoc_item(acc, ctx, item));
+            return;
+        }
+    }
+
     let resolution = match ctx.sema.resolve_path(path) {
         Some(res) => res,
         None => return,
     };
 
-    let context_module = ctx.scope.module();
+    let context_module = ctx.module;
 
     match ctx.completion_location {
         Some(ImmediateLocation::ItemList | ImmediateLocation::Trait | ImmediateLocation::Impl) => {
@@ -56,7 +75,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
     match kind {
         Some(PathKind::Vis { .. }) => {
             if let hir::PathResolution::Def(hir::ModuleDef::Module(module)) = resolution {
-                if let Some(current_module) = ctx.scope.module() {
+                if let Some(current_module) = ctx.module {
                     if let Some(next) = current_module
                         .path_to_root(ctx.db)
                         .into_iter()
@@ -152,9 +171,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
             }
         }
         hir::PathResolution::Def(
-            def
-            @
-            (hir::ModuleDef::Adt(_)
+            def @ (hir::ModuleDef::Adt(_)
             | hir::ModuleDef::TypeAlias(_)
             | hir::ModuleDef::BuiltinType(_)),
         ) => {
@@ -172,7 +189,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
                     ty
                 }
                 hir::ModuleDef::BuiltinType(builtin) => {
-                    let module = match ctx.scope.module() {
+                    let module = match ctx.module {
                         Some(it) => it,
                         None => return,
                     };
@@ -188,10 +205,17 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
             let krate = ctx.krate;
             if let Some(krate) = krate {
                 let traits_in_scope = ctx.scope.visible_traits();
-                ty.iterate_path_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, item| {
-                    add_assoc_item(acc, ctx, item);
-                    None::<()>
-                });
+                ty.iterate_path_candidates(
+                    ctx.db,
+                    krate,
+                    &traits_in_scope,
+                    ctx.module,
+                    None,
+                    |_ty, item| {
+                        add_assoc_item(acc, ctx, item);
+                        None::<()>
+                    },
+                );
 
                 // Iterate assoc types separately
                 ty.iterate_assoc_items(ctx.db, krate, |item| {
@@ -222,14 +246,21 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
 
                 let traits_in_scope = ctx.scope.visible_traits();
                 let mut seen = FxHashSet::default();
-                ty.iterate_path_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, item| {
-                    // We might iterate candidates of a trait multiple times here, so deduplicate
-                    // them.
-                    if seen.insert(item) {
-                        add_assoc_item(acc, ctx, item);
-                    }
-                    None::<()>
-                });
+                ty.iterate_path_candidates(
+                    ctx.db,
+                    krate,
+                    &traits_in_scope,
+                    ctx.module,
+                    None,
+                    |_ty, item| {
+                        // We might iterate candidates of a trait multiple times here, so deduplicate
+                        // them.
+                        if seen.insert(item) {
+                            add_assoc_item(acc, ctx, item);
+                        }
+                        None::<()>
+                    },
+                );
             }
         }
         hir::PathResolution::Macro(mac) => acc.add_macro(ctx, None, mac),
@@ -287,8 +318,8 @@ fn foo() { let _ = lib::S::$0 }
 "#,
             expect![[r#"
                 fn public_method() fn()
-                ct PUBLIC_CONST    pub const PUBLIC_CONST: u32;
-                ta PublicType      pub type PublicType;
+                ct PUBLIC_CONST    pub const PUBLIC_CONST: u32
+                ta PublicType      pub type PublicType = u32
             "#]],
         );
     }
@@ -377,12 +408,12 @@ fn submethod(&self) {}
 fn foo<T: Sub>() { T::$0 }
 "#,
             expect![[r#"
-                ta SubTy (as Sub)        type SubTy;
-                ta Ty (as Super)         type Ty;
-                ct C2 (as Sub)           const C2: ();
+                ta SubTy (as Sub)        type SubTy
+                ta Ty (as Super)         type Ty
+                ct C2 (as Sub)           const C2: ()
                 fn subfunc() (as Sub)    fn()
                 me submethod(…) (as Sub) fn(&self)
-                ct CONST (as Super)      const CONST: u8;
+                ct CONST (as Super)      const CONST: u8
                 fn func() (as Super)     fn()
                 me method(…) (as Super)  fn(&self)
             "#]],
@@ -417,12 +448,12 @@ fn subfunc() {
 }
 "#,
             expect![[r#"
-                ta SubTy (as Sub)        type SubTy;
-                ta Ty (as Super)         type Ty;
-                ct CONST (as Super)      const CONST: u8;
+                ta SubTy (as Sub)        type SubTy
+                ta Ty (as Super)         type Ty
+                ct CONST (as Super)      const CONST: u8
                 fn func() (as Super)     fn()
                 me method(…) (as Super)  fn(&self)
-                ct C2 (as Sub)           const C2: ();
+                ct C2 (as Sub)           const C2: ()
                 fn subfunc() (as Sub)    fn()
                 me submethod(…) (as Sub) fn(&self)
             "#]],
@@ -653,7 +684,7 @@ pub fn func(self) {}
 }
 "#,
             expect![[r#"
-                ct MAX     pub const MAX: Self;
+                ct MAX     pub const MAX: Self
                 me func(…) fn(self)
             "#]],
         );
@@ -707,4 +738,28 @@ pub mod m {}
             expect![[r#""#]],
         )
     }
+
+    #[test]
+    fn type_anchor_empty() {
+        cov_mark::check!(completion_type_anchor_empty);
+        check(
+            r#"
+trait Foo {
+    fn foo() -> Self;
+}
+struct Bar;
+impl Foo for Bar {
+    fn foo() -> {
+        Bar
+    }
+}
+fn bar() -> Bar {
+    <_>::$0
+}
+"#,
+            expect![[r#"
+                fn foo() (as Foo) fn() -> Self
+            "#]],
+        )
+    }
 }