diff --git a/crates/ide-completion/src/completions.rs b/crates/ide-completion/src/completions.rs
index f8b1ff73109..b22124cc695 100644
--- a/crates/ide-completion/src/completions.rs
+++ b/crates/ide-completion/src/completions.rs
@@ -2,6 +2,7 @@
 
 pub(crate) mod attribute;
 pub(crate) mod dot;
+pub(crate) mod expr;
 pub(crate) mod extern_abi;
 pub(crate) mod flyimport;
 pub(crate) mod fn_param;
@@ -16,7 +17,7 @@ pub(crate) mod qualified_path;
 pub(crate) mod record;
 pub(crate) mod snippet;
 pub(crate) mod trait_impl;
-pub(crate) mod unqualified_path;
+pub(crate) mod r#type;
 pub(crate) mod use_;
 pub(crate) mod vis;
 
diff --git a/crates/ide-completion/src/completions/expr.rs b/crates/ide-completion/src/completions/expr.rs
new file mode 100644
index 00000000000..f9717f1c2c1
--- /dev/null
+++ b/crates/ide-completion/src/completions/expr.rs
@@ -0,0 +1,49 @@
+//! Completion of names from the current scope in expression position.
+
+use hir::ScopeDef;
+
+use crate::{
+    context::{PathCompletionCtx, PathKind, PathQualifierCtx},
+    CompletionContext, Completions,
+};
+
+pub(crate) fn complete_expr_path(acc: &mut Completions, ctx: &CompletionContext) {
+    let _p = profile::span("complete_expr_path");
+    if ctx.is_path_disallowed() {
+        return;
+    }
+
+    let (&is_absolute_path, qualifier) = match &ctx.path_context {
+        Some(PathCompletionCtx {
+            kind: Some(PathKind::Expr), is_absolute_path, qualifier, ..
+        }) => (is_absolute_path, qualifier),
+        _ => return,
+    };
+
+    match qualifier {
+        Some(PathQualifierCtx { .. }) => return,
+        None if is_absolute_path => acc.add_crate_roots(ctx),
+        None => {
+            acc.add_nameref_keywords_with_colon(ctx);
+            if let Some(hir::Adt::Enum(e)) =
+                ctx.expected_type.as_ref().and_then(|ty| ty.strip_references().as_adt())
+            {
+                super::enum_variants_with_paths(acc, ctx, e, |acc, ctx, variant, path| {
+                    acc.add_qualified_enum_variant(ctx, variant, path)
+                });
+            }
+            ctx.process_all_names(&mut |name, def| {
+                use hir::{GenericParam::*, ModuleDef::*};
+                let add_resolution = match def {
+                    ScopeDef::GenericParam(LifetimeParam(_)) | ScopeDef::Label(_) => false,
+                    // Don't suggest attribute macros and derives.
+                    ScopeDef::ModuleDef(Macro(mac)) => mac.is_fn_like(ctx.db),
+                    _ => true,
+                };
+                if add_resolution {
+                    acc.add_resolution(ctx, name, def);
+                }
+            });
+        }
+    }
+}
diff --git a/crates/ide-completion/src/completions/item_list.rs b/crates/ide-completion/src/completions/item_list.rs
index 5ae119c534a..ff1abd715dc 100644
--- a/crates/ide-completion/src/completions/item_list.rs
+++ b/crates/ide-completion/src/completions/item_list.rs
@@ -7,7 +7,7 @@ use crate::{
 };
 
 pub(crate) fn complete_item_list(acc: &mut Completions, ctx: &CompletionContext) {
-    let _p = profile::span("complete_unqualified_path");
+    let _p = profile::span("complete_item_list");
     if ctx.is_path_disallowed() || ctx.has_unfinished_impl_or_trait_prev_sibling() {
         return;
     }
diff --git a/crates/ide-completion/src/completions/type.rs b/crates/ide-completion/src/completions/type.rs
new file mode 100644
index 00000000000..4d0e2fb59ac
--- /dev/null
+++ b/crates/ide-completion/src/completions/type.rs
@@ -0,0 +1,90 @@
+//! Completion of names from the current scope in type position.
+
+use hir::ScopeDef;
+use syntax::{ast, AstNode};
+
+use crate::{
+    context::{PathCompletionCtx, PathKind, PathQualifierCtx},
+    patterns::ImmediateLocation,
+    CompletionContext, Completions,
+};
+
+pub(crate) fn complete_type_path(acc: &mut Completions, ctx: &CompletionContext) {
+    let _p = profile::span("complete_type_path");
+    if ctx.is_path_disallowed() {
+        return;
+    }
+
+    let (&is_absolute_path, qualifier) = match &ctx.path_context {
+        Some(PathCompletionCtx {
+            kind: Some(PathKind::Type), is_absolute_path, qualifier, ..
+        }) => (is_absolute_path, qualifier),
+        _ => return,
+    };
+
+    match qualifier {
+        Some(PathQualifierCtx { .. }) => return,
+        None if is_absolute_path => acc.add_crate_roots(ctx),
+        None => {
+            acc.add_nameref_keywords_with_colon(ctx);
+            if let Some(ImmediateLocation::TypeBound) = &ctx.completion_location {
+                ctx.process_all_names(&mut |name, res| {
+                    let add_resolution = match res {
+                        ScopeDef::ModuleDef(hir::ModuleDef::Macro(mac)) => mac.is_fn_like(ctx.db),
+                        ScopeDef::ModuleDef(
+                            hir::ModuleDef::Trait(_) | hir::ModuleDef::Module(_),
+                        ) => true,
+                        _ => false,
+                    };
+                    if add_resolution {
+                        acc.add_resolution(ctx, name, res);
+                    }
+                });
+                return;
+            }
+            if let Some(ImmediateLocation::GenericArgList(arg_list)) = &ctx.completion_location {
+                if let Some(path_seg) = arg_list.syntax().parent().and_then(ast::PathSegment::cast)
+                {
+                    if let Some(hir::PathResolution::Def(hir::ModuleDef::Trait(trait_))) =
+                        ctx.sema.resolve_path(&path_seg.parent_path())
+                    {
+                        trait_.items(ctx.sema.db).into_iter().for_each(|it| {
+                            if let hir::AssocItem::TypeAlias(alias) = it {
+                                acc.add_type_alias_with_eq(ctx, alias)
+                            }
+                        });
+                    }
+                }
+            }
+            ctx.process_all_names(&mut |name, def| {
+                use hir::{GenericParam::*, ModuleDef::*};
+                let add_resolution = match def {
+                    ScopeDef::GenericParam(LifetimeParam(_)) | ScopeDef::Label(_) => false,
+                    // no values in type places
+                    ScopeDef::ModuleDef(Function(_) | Variant(_) | Static(_))
+                    | ScopeDef::Local(_) => false,
+                    // unless its a constant in a generic arg list position
+                    ScopeDef::ModuleDef(Const(_)) | ScopeDef::GenericParam(ConstParam(_)) => {
+                        ctx.expects_generic_arg()
+                    }
+                    ScopeDef::ImplSelfType(_) => {
+                        !ctx.previous_token_is(syntax::T![impl])
+                            && !ctx.previous_token_is(syntax::T![for])
+                    }
+                    // Don't suggest attribute macros and derives.
+                    ScopeDef::ModuleDef(Macro(mac)) => mac.is_fn_like(ctx.db),
+                    // Type things are fine
+                    ScopeDef::ModuleDef(
+                        BuiltinType(_) | Adt(_) | Module(_) | Trait(_) | TypeAlias(_),
+                    )
+                    | ScopeDef::AdtSelfType(_)
+                    | ScopeDef::Unknown
+                    | ScopeDef::GenericParam(TypeParam(_)) => true,
+                };
+                if add_resolution {
+                    acc.add_resolution(ctx, name, def);
+                }
+            });
+        }
+    }
+}
diff --git a/crates/ide-completion/src/completions/unqualified_path.rs b/crates/ide-completion/src/completions/unqualified_path.rs
deleted file mode 100644
index 5de602e6138..00000000000
--- a/crates/ide-completion/src/completions/unqualified_path.rs
+++ /dev/null
@@ -1,289 +0,0 @@
-//! Completion of names from the current scope, e.g. locals and imported items.
-
-use hir::ScopeDef;
-use syntax::{ast, AstNode};
-
-use crate::{
-    context::{PathCompletionCtx, PathKind},
-    patterns::ImmediateLocation,
-    CompletionContext, Completions,
-};
-
-pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionContext) {
-    let _p = profile::span("complete_unqualified_path");
-    if ctx.is_path_disallowed() || ctx.has_unfinished_impl_or_trait_prev_sibling() {
-        return;
-    }
-
-    match &ctx.path_context {
-        Some(PathCompletionCtx {
-            is_absolute_path: false,
-            qualifier: None,
-            kind: None | Some(PathKind::Expr | PathKind::Type),
-            ..
-        }) => (),
-        _ => return,
-    }
-
-    acc.add_nameref_keywords(ctx);
-
-    match &ctx.completion_location {
-        Some(ImmediateLocation::TypeBound) => {
-            ctx.process_all_names(&mut |name, res| {
-                let add_resolution = match res {
-                    ScopeDef::ModuleDef(hir::ModuleDef::Macro(mac)) => mac.is_fn_like(ctx.db),
-                    ScopeDef::ModuleDef(hir::ModuleDef::Trait(_) | hir::ModuleDef::Module(_)) => {
-                        true
-                    }
-                    _ => false,
-                };
-                if add_resolution {
-                    acc.add_resolution(ctx, name, res);
-                }
-            });
-            return;
-        }
-        _ => (),
-    }
-
-    if !ctx.expects_type() {
-        if let Some(hir::Adt::Enum(e)) =
-            ctx.expected_type.as_ref().and_then(|ty| ty.strip_references().as_adt())
-        {
-            super::enum_variants_with_paths(acc, ctx, e, |acc, ctx, variant, path| {
-                acc.add_qualified_enum_variant(ctx, variant, path)
-            });
-        }
-    }
-
-    if let Some(ImmediateLocation::GenericArgList(arg_list)) = &ctx.completion_location {
-        if let Some(path_seg) = arg_list.syntax().parent().and_then(ast::PathSegment::cast) {
-            if let Some(hir::PathResolution::Def(hir::ModuleDef::Trait(trait_))) =
-                ctx.sema.resolve_path(&path_seg.parent_path())
-            {
-                trait_.items(ctx.sema.db).into_iter().for_each(|it| {
-                    if let hir::AssocItem::TypeAlias(alias) = it {
-                        acc.add_type_alias_with_eq(ctx, alias)
-                    }
-                });
-            }
-        }
-    }
-
-    ctx.process_all_names(&mut |name, res| {
-        let add_resolution = match res {
-            ScopeDef::GenericParam(hir::GenericParam::LifetimeParam(_)) | ScopeDef::Label(_) => {
-                cov_mark::hit!(unqualified_skip_lifetime_completion);
-                return;
-            }
-            ScopeDef::ImplSelfType(_) => {
-                !ctx.previous_token_is(syntax::T![impl]) && !ctx.previous_token_is(syntax::T![for])
-            }
-            // Don't suggest attribute macros and derives.
-            ScopeDef::ModuleDef(hir::ModuleDef::Macro(mac)) => mac.is_fn_like(ctx.db),
-            // no values in type places
-            ScopeDef::ModuleDef(
-                hir::ModuleDef::Function(_)
-                | hir::ModuleDef::Variant(_)
-                | hir::ModuleDef::Static(_),
-            )
-            | ScopeDef::Local(_) => !ctx.expects_type(),
-            // unless its a constant in a generic arg list position
-            ScopeDef::ModuleDef(hir::ModuleDef::Const(_))
-            | ScopeDef::GenericParam(hir::GenericParam::ConstParam(_)) => {
-                !ctx.expects_type() || ctx.expects_generic_arg()
-            }
-            _ => true,
-        };
-        if add_resolution {
-            acc.add_resolution(ctx, name, res);
-        }
-    });
-}
-
-#[cfg(test)]
-mod tests {
-    use expect_test::{expect, Expect};
-
-    use crate::tests::{check_edit, completion_list_no_kw};
-
-    fn check(ra_fixture: &str, expect: Expect) {
-        let actual = completion_list_no_kw(ra_fixture);
-        expect.assert_eq(&actual)
-    }
-
-    #[test]
-    fn completes_if_prefix_is_keyword() {
-        check_edit(
-            "wherewolf",
-            r#"
-fn main() {
-    let wherewolf = 92;
-    drop(where$0)
-}
-"#,
-            r#"
-fn main() {
-    let wherewolf = 92;
-    drop(wherewolf)
-}
-"#,
-        )
-    }
-
-    /// Regression test for issue #6091.
-    #[test]
-    fn correctly_completes_module_items_prefixed_with_underscore() {
-        check_edit(
-            "_alpha",
-            r#"
-fn main() {
-    _$0
-}
-fn _alpha() {}
-"#,
-            r#"
-fn main() {
-    _alpha()$0
-}
-fn _alpha() {}
-"#,
-        )
-    }
-
-    #[test]
-    fn completes_prelude() {
-        check(
-            r#"
-//- /main.rs crate:main deps:std
-fn foo() { let x: $0 }
-
-//- /std/lib.rs crate:std
-pub mod prelude {
-    pub mod rust_2018 {
-        pub struct Option;
-    }
-}
-"#,
-            expect![[r#"
-                md std
-                st Option
-                bt u32
-            "#]],
-        );
-    }
-
-    #[test]
-    fn completes_prelude_macros() {
-        check(
-            r#"
-//- /main.rs crate:main deps:std
-fn f() {$0}
-
-//- /std/lib.rs crate:std
-pub mod prelude {
-    pub mod rust_2018 {
-        pub use crate::concat;
-    }
-}
-
-mod macros {
-    #[rustc_builtin_macro]
-    #[macro_export]
-    macro_rules! concat { }
-}
-"#,
-            expect![[r#"
-                fn f()        fn()
-                ma concat!(…) macro_rules! concat
-                md std
-                bt u32
-            "#]],
-        );
-    }
-
-    #[test]
-    fn completes_std_prelude_if_core_is_defined() {
-        check(
-            r#"
-//- /main.rs crate:main deps:core,std
-fn foo() { let x: $0 }
-
-//- /core/lib.rs crate:core
-pub mod prelude {
-    pub mod rust_2018 {
-        pub struct Option;
-    }
-}
-
-//- /std/lib.rs crate:std deps:core
-pub mod prelude {
-    pub mod rust_2018 {
-        pub struct String;
-    }
-}
-"#,
-            expect![[r#"
-                md core
-                md std
-                st String
-                bt u32
-            "#]],
-        );
-    }
-
-    #[test]
-    fn respects_doc_hidden() {
-        check(
-            r#"
-//- /lib.rs crate:lib deps:std
-fn f() {
-    format_$0
-}
-
-//- /std.rs crate:std
-#[doc(hidden)]
-#[macro_export]
-macro_rules! format_args_nl {
-    () => {}
-}
-
-pub mod prelude {
-    pub mod rust_2018 {}
-}
-            "#,
-            expect![[r#"
-                fn f() fn()
-                md std
-                bt u32
-            "#]],
-        );
-    }
-
-    #[test]
-    fn respects_doc_hidden_in_assoc_item_list() {
-        check(
-            r#"
-//- /lib.rs crate:lib deps:std
-struct S;
-impl S {
-    format_$0
-}
-
-//- /std.rs crate:std
-#[doc(hidden)]
-#[macro_export]
-macro_rules! format_args_nl {
-    () => {}
-}
-
-pub mod prelude {
-    pub mod rust_2018 {}
-}
-            "#,
-            expect![[r#"
-                md std
-            "#]],
-        );
-    }
-}
diff --git a/crates/ide-completion/src/context.rs b/crates/ide-completion/src/context.rs
index 6682bc56d18..87677e28e85 100644
--- a/crates/ide-completion/src/context.rs
+++ b/crates/ide-completion/src/context.rs
@@ -71,6 +71,10 @@ 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: Option<PathKind>,
     /// Whether the path segment has type args or not.
     pub(super) has_type_args: bool,
@@ -949,13 +953,14 @@ impl<'a> CompletionContext<'a> {
 
         let mut path_ctx = PathCompletionCtx {
             has_call_parens: false,
+            has_macro_bang: false,
             is_absolute_path: false,
             qualifier: None,
+            parent: path.parent_path(),
+            kind: None,
             has_type_args: false,
             can_be_stmt: false,
             in_loop_body: false,
-            has_macro_bang: false,
-            kind: None,
         };
         let mut pat_ctx = None;
         path_ctx.in_loop_body = is_in_loop_body(name_ref.syntax());
diff --git a/crates/ide-completion/src/lib.rs b/crates/ide-completion/src/lib.rs
index 473900397ae..3a0bd042daf 100644
--- a/crates/ide-completion/src/lib.rs
+++ b/crates/ide-completion/src/lib.rs
@@ -144,34 +144,38 @@ pub fn completions(
     config: &CompletionConfig,
     position: FilePosition,
 ) -> Option<Completions> {
-    let ctx = CompletionContext::new(db, position, config)?;
-
+    let ctx = &CompletionContext::new(db, position, config)?;
     let mut acc = Completions::default();
-    completions::attribute::complete_attribute(&mut acc, &ctx);
-    completions::attribute::complete_derive(&mut acc, &ctx);
-    completions::attribute::complete_known_attribute_input(&mut acc, &ctx);
-    completions::dot::complete_dot(&mut acc, &ctx);
-    completions::extern_abi::complete_extern_abi(&mut acc, &ctx);
-    completions::flyimport::import_on_the_fly(&mut acc, &ctx);
-    completions::fn_param::complete_fn_param(&mut acc, &ctx);
-    completions::format_string::format_string(&mut acc, &ctx);
-    completions::item_list::complete_item_list(&mut acc, &ctx);
-    completions::inferred_type(&mut acc, &ctx);
-    completions::keyword::complete_expr_keyword(&mut acc, &ctx);
-    completions::lifetime::complete_label(&mut acc, &ctx);
-    completions::lifetime::complete_lifetime(&mut acc, &ctx);
-    completions::mod_::complete_mod(&mut acc, &ctx);
-    completions::pattern::complete_pattern(&mut acc, &ctx);
-    completions::postfix::complete_postfix(&mut acc, &ctx);
-    completions::qualified_path::complete_qualified_path(&mut acc, &ctx);
-    completions::record::complete_record_literal(&mut acc, &ctx);
-    completions::record::complete_record(&mut acc, &ctx);
-    completions::snippet::complete_expr_snippet(&mut acc, &ctx);
-    completions::snippet::complete_item_snippet(&mut acc, &ctx);
-    completions::trait_impl::complete_trait_impl(&mut acc, &ctx);
-    completions::unqualified_path::complete_unqualified_path(&mut acc, &ctx);
-    completions::use_::complete_use_tree(&mut acc, &ctx);
-    completions::vis::complete_vis(&mut acc, &ctx);
+
+    {
+        let acc = &mut acc;
+        completions::attribute::complete_attribute(acc, ctx);
+        completions::attribute::complete_derive(acc, ctx);
+        completions::attribute::complete_known_attribute_input(acc, ctx);
+        completions::dot::complete_dot(acc, ctx);
+        completions::expr::complete_expr_path(acc, ctx);
+        completions::extern_abi::complete_extern_abi(acc, ctx);
+        completions::flyimport::import_on_the_fly(acc, ctx);
+        completions::fn_param::complete_fn_param(acc, ctx);
+        completions::format_string::format_string(acc, ctx);
+        completions::item_list::complete_item_list(acc, ctx);
+        completions::inferred_type(acc, ctx);
+        completions::keyword::complete_expr_keyword(acc, ctx);
+        completions::lifetime::complete_label(acc, ctx);
+        completions::lifetime::complete_lifetime(acc, ctx);
+        completions::mod_::complete_mod(acc, ctx);
+        completions::pattern::complete_pattern(acc, ctx);
+        completions::postfix::complete_postfix(acc, ctx);
+        completions::qualified_path::complete_qualified_path(acc, ctx);
+        completions::record::complete_record_literal(acc, ctx);
+        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::use_::complete_use_tree(acc, ctx);
+        completions::vis::complete_vis(acc, ctx);
+    }
 
     Some(acc)
 }
diff --git a/crates/ide-completion/src/tests.rs b/crates/ide-completion/src/tests.rs
index 5387b455f03..8d9d1bc4b95 100644
--- a/crates/ide-completion/src/tests.rs
+++ b/crates/ide-completion/src/tests.rs
@@ -10,6 +10,7 @@
 
 mod attribute;
 mod expression;
+mod flyimport;
 mod fn_param;
 mod item_list;
 mod item;
@@ -17,10 +18,10 @@ mod pattern;
 mod predicate;
 mod proc_macros;
 mod record;
+mod special;
 mod type_pos;
 mod use_tree;
 mod visibility;
-mod flyimport;
 
 use std::mem;
 
diff --git a/crates/ide-completion/src/tests/expression.rs b/crates/ide-completion/src/tests/expression.rs
index a068d5bf7af..61246b963e1 100644
--- a/crates/ide-completion/src/tests/expression.rs
+++ b/crates/ide-completion/src/tests/expression.rs
@@ -48,7 +48,7 @@ fn baz() {
             un Union
             ev TupleV(…)     TupleV(u32)
             bt u32
-            kw crate
+            kw crate::
             kw false
             kw for
             kw if
@@ -57,8 +57,8 @@ fn baz() {
             kw match
             kw mut
             kw return
-            kw self
-            kw super
+            kw self::
+            kw super::
             kw true
             kw unsafe
             kw while
@@ -91,7 +91,7 @@ fn func(param0 @ (param1, param2): (i32, i32)) {
             lc param1     i32
             lc param2     i32
             bt u32
-            kw crate
+            kw crate::
             kw false
             kw for
             kw if
@@ -99,8 +99,8 @@ fn func(param0 @ (param1, param2): (i32, i32)) {
             kw loop
             kw match
             kw return
-            kw self
-            kw super
+            kw self::
+            kw super::
             kw true
             kw unsafe
             kw while
@@ -111,7 +111,6 @@ fn func(param0 @ (param1, param2): (i32, i32)) {
 
 #[test]
 fn completes_all_the_things_in_fn_body() {
-    cov_mark::check!(unqualified_skip_lifetime_completion);
     check(
         r#"
 use non_existant::Unresolved;
@@ -146,7 +145,7 @@ impl Unit {
             ev TupleV(…)    TupleV(u32)
             bt u32
             kw const
-            kw crate
+            kw crate::
             kw enum
             kw extern
             kw false
@@ -160,10 +159,10 @@ impl Unit {
             kw match
             kw mod
             kw return
-            kw self
+            kw self::
             kw static
             kw struct
-            kw super
+            kw super::
             kw trait
             kw true
             kw type
@@ -224,7 +223,7 @@ fn complete_in_block() {
             fn foo()       fn()
             bt u32
             kw const
-            kw crate
+            kw crate::
             kw enum
             kw extern
             kw false
@@ -238,10 +237,10 @@ fn complete_in_block() {
             kw match
             kw mod
             kw return
-            kw self
+            kw self::
             kw static
             kw struct
-            kw super
+            kw super::
             kw trait
             kw true
             kw type
@@ -270,7 +269,7 @@ fn complete_after_if_expr() {
             fn foo()       fn()
             bt u32
             kw const
-            kw crate
+            kw crate::
             kw else
             kw else if
             kw enum
@@ -286,10 +285,10 @@ fn complete_after_if_expr() {
             kw match
             kw mod
             kw return
-            kw self
+            kw self::
             kw static
             kw struct
-            kw super
+            kw super::
             kw trait
             kw true
             kw type
@@ -318,7 +317,7 @@ fn complete_in_match_arm() {
         expect![[r#"
             fn foo()     fn()
             bt u32
-            kw crate
+            kw crate::
             kw false
             kw for
             kw if
@@ -326,8 +325,8 @@ fn complete_in_match_arm() {
             kw loop
             kw match
             kw return
-            kw self
-            kw super
+            kw self::
+            kw super::
             kw true
             kw unsafe
             kw while
@@ -346,7 +345,7 @@ fn completes_in_loop_ctx() {
             kw break
             kw const
             kw continue
-            kw crate
+            kw crate::
             kw enum
             kw extern
             kw false
@@ -360,10 +359,10 @@ fn completes_in_loop_ctx() {
             kw match
             kw mod
             kw return
-            kw self
+            kw self::
             kw static
             kw struct
-            kw super
+            kw super::
             kw trait
             kw true
             kw type
@@ -386,7 +385,7 @@ fn completes_in_let_initializer() {
         expect![[r#"
             fn main()    fn()
             bt u32
-            kw crate
+            kw crate::
             kw false
             kw for
             kw if
@@ -394,8 +393,8 @@ fn completes_in_let_initializer() {
             kw loop
             kw match
             kw return
-            kw self
-            kw super
+            kw self::
+            kw super::
             kw true
             kw unsafe
             kw while
@@ -421,7 +420,7 @@ fn foo() {
             fn foo()     fn()
             st Foo
             bt u32
-            kw crate
+            kw crate::
             kw false
             kw for
             kw if
@@ -429,8 +428,8 @@ fn foo() {
             kw loop
             kw match
             kw return
-            kw self
-            kw super
+            kw self::
+            kw super::
             kw true
             kw unsafe
             kw while
@@ -457,7 +456,7 @@ fn foo() {
             fn foo()     fn()
             lc bar       i32
             bt u32
-            kw crate
+            kw crate::
             kw false
             kw for
             kw if
@@ -465,8 +464,8 @@ fn foo() {
             kw loop
             kw match
             kw return
-            kw self
-            kw super
+            kw self::
+            kw super::
             kw true
             kw unsafe
             kw while
@@ -489,7 +488,7 @@ fn quux(x: i32) {
             lc x         i32
             ma m!(…)     macro_rules! m
             bt u32
-            kw crate
+            kw crate::
             kw false
             kw for
             kw if
@@ -497,8 +496,8 @@ fn quux(x: i32) {
             kw loop
             kw match
             kw return
-            kw self
-            kw super
+            kw self::
+            kw super::
             kw true
             kw unsafe
             kw while
@@ -517,7 +516,7 @@ fn quux(x: i32) {
             lc x         i32
             ma m!(…)     macro_rules! m
             bt u32
-            kw crate
+            kw crate::
             kw false
             kw for
             kw if
@@ -525,8 +524,8 @@ fn quux(x: i32) {
             kw loop
             kw match
             kw return
-            kw self
-            kw super
+            kw self::
+            kw super::
             kw true
             kw unsafe
             kw while
diff --git a/crates/ide-completion/src/tests/item.rs b/crates/ide-completion/src/tests/item.rs
index 5d324f0965f..e4b70f97e31 100644
--- a/crates/ide-completion/src/tests/item.rs
+++ b/crates/ide-completion/src/tests/item.rs
@@ -27,9 +27,9 @@ impl Tra$0
             tt Trait
             un Union
             bt u32
-            kw crate
-            kw self
-            kw super
+            kw crate::
+            kw self::
+            kw super::
         "#]],
     )
 }
@@ -50,9 +50,9 @@ impl Trait for Str$0
             tt Trait
             un Union
             bt u32
-            kw crate
-            kw self
-            kw super
+            kw crate::
+            kw self::
+            kw super::
         "#]],
     )
 }
diff --git a/crates/ide-completion/src/tests/predicate.rs b/crates/ide-completion/src/tests/predicate.rs
index cc18bf44536..f2b9c061dc5 100644
--- a/crates/ide-completion/src/tests/predicate.rs
+++ b/crates/ide-completion/src/tests/predicate.rs
@@ -26,9 +26,9 @@ struct Foo<'lt, T, const C: usize> where $0 {}
             tt Trait
             un Union
             bt u32
-            kw crate
-            kw self
-            kw super
+            kw crate::
+            kw self::
+            kw super::
         "#]],
     );
 }
@@ -43,9 +43,9 @@ struct Foo<'lt, T, const C: usize> where T: $0 {}
             ma makro!(…) macro_rules! makro
             md module
             tt Trait
-            kw crate
-            kw self
-            kw super
+            kw crate::
+            kw self::
+            kw super::
         "#]],
     );
 }
@@ -62,9 +62,9 @@ struct Foo<'lt, T, const C: usize> where 'lt: $0 {}
             ma makro!(…) macro_rules! makro
             md module
             tt Trait
-            kw crate
-            kw self
-            kw super
+            kw crate::
+            kw self::
+            kw super::
         "#]],
     );
 }
@@ -79,9 +79,9 @@ struct Foo<'lt, T, const C: usize> where for<'a> T: $0 {}
             ma makro!(…) macro_rules! makro
             md module
             tt Trait
-            kw crate
-            kw self
-            kw super
+            kw crate::
+            kw self::
+            kw super::
         "#]],
     );
 }
@@ -103,9 +103,9 @@ struct Foo<'lt, T, const C: usize> where for<'a> $0 {}
             tt Trait
             un Union
             bt u32
-            kw crate
-            kw self
-            kw super
+            kw crate::
+            kw self::
+            kw super::
         "#]],
     );
 }
@@ -129,9 +129,9 @@ impl Record {
             tt Trait
             un Union
             bt u32
-            kw crate
-            kw self
-            kw super
+            kw crate::
+            kw self::
+            kw super::
         "#]],
     );
 }
diff --git a/crates/ide-completion/src/tests/record.rs b/crates/ide-completion/src/tests/record.rs
index bae5ddb5394..a0f8b248672 100644
--- a/crates/ide-completion/src/tests/record.rs
+++ b/crates/ide-completion/src/tests/record.rs
@@ -167,7 +167,7 @@ fn main() {
             tt Default
             tt Sized
             bt u32
-            kw crate
+            kw crate::
             kw false
             kw for
             kw if
@@ -175,8 +175,8 @@ fn main() {
             kw loop
             kw match
             kw return
-            kw self
-            kw super
+            kw self::
+            kw super::
             kw true
             kw unsafe
             kw while
diff --git a/crates/ide-completion/src/tests/special.rs b/crates/ide-completion/src/tests/special.rs
new file mode 100644
index 00000000000..79235e5ca01
--- /dev/null
+++ b/crates/ide-completion/src/tests/special.rs
@@ -0,0 +1,183 @@
+use expect_test::{expect, Expect};
+
+use crate::tests::{check_edit, completion_list_no_kw};
+
+fn check(ra_fixture: &str, expect: Expect) {
+    let actual = completion_list_no_kw(ra_fixture);
+    expect.assert_eq(&actual)
+}
+
+#[test]
+fn completes_if_prefix_is_keyword() {
+    check_edit(
+        "wherewolf",
+        r#"
+fn main() {
+    let wherewolf = 92;
+    drop(where$0)
+}
+"#,
+        r#"
+fn main() {
+    let wherewolf = 92;
+    drop(wherewolf)
+}
+"#,
+    )
+}
+
+/// Regression test for issue #6091.
+#[test]
+fn correctly_completes_module_items_prefixed_with_underscore() {
+    check_edit(
+        "_alpha",
+        r#"
+fn main() {
+    _$0
+}
+fn _alpha() {}
+"#,
+        r#"
+fn main() {
+    _alpha()$0
+}
+fn _alpha() {}
+"#,
+    )
+}
+
+#[test]
+fn completes_prelude() {
+    check(
+        r#"
+//- /main.rs crate:main deps:std
+fn foo() { let x: $0 }
+
+//- /std/lib.rs crate:std
+pub mod prelude {
+    pub mod rust_2018 {
+        pub struct Option;
+    }
+}
+"#,
+        expect![[r#"
+                md std
+                st Option
+                bt u32
+            "#]],
+    );
+}
+
+#[test]
+fn completes_prelude_macros() {
+    check(
+        r#"
+//- /main.rs crate:main deps:std
+fn f() {$0}
+
+//- /std/lib.rs crate:std
+pub mod prelude {
+    pub mod rust_2018 {
+        pub use crate::concat;
+    }
+}
+
+mod macros {
+    #[rustc_builtin_macro]
+    #[macro_export]
+    macro_rules! concat { }
+}
+"#,
+        expect![[r#"
+                fn f()        fn()
+                ma concat!(…) macro_rules! concat
+                md std
+                bt u32
+            "#]],
+    );
+}
+
+#[test]
+fn completes_std_prelude_if_core_is_defined() {
+    check(
+        r#"
+//- /main.rs crate:main deps:core,std
+fn foo() { let x: $0 }
+
+//- /core/lib.rs crate:core
+pub mod prelude {
+    pub mod rust_2018 {
+        pub struct Option;
+    }
+}
+
+//- /std/lib.rs crate:std deps:core
+pub mod prelude {
+    pub mod rust_2018 {
+        pub struct String;
+    }
+}
+"#,
+        expect![[r#"
+                md core
+                md std
+                st String
+                bt u32
+            "#]],
+    );
+}
+
+#[test]
+fn respects_doc_hidden() {
+    check(
+        r#"
+//- /lib.rs crate:lib deps:std
+fn f() {
+    format_$0
+}
+
+//- /std.rs crate:std
+#[doc(hidden)]
+#[macro_export]
+macro_rules! format_args_nl {
+    () => {}
+}
+
+pub mod prelude {
+    pub mod rust_2018 {}
+}
+            "#,
+        expect![[r#"
+                fn f() fn()
+                md std
+                bt u32
+            "#]],
+    );
+}
+
+#[test]
+fn respects_doc_hidden_in_assoc_item_list() {
+    check(
+        r#"
+//- /lib.rs crate:lib deps:std
+struct S;
+impl S {
+    format_$0
+}
+
+//- /std.rs crate:std
+#[doc(hidden)]
+#[macro_export]
+macro_rules! format_args_nl {
+    () => {}
+}
+
+pub mod prelude {
+    pub mod rust_2018 {}
+}
+            "#,
+        expect![[r#"
+                md std
+            "#]],
+    );
+}
diff --git a/crates/ide-completion/src/tests/type_pos.rs b/crates/ide-completion/src/tests/type_pos.rs
index fcbb2e05a79..5224bc4b488 100644
--- a/crates/ide-completion/src/tests/type_pos.rs
+++ b/crates/ide-completion/src/tests/type_pos.rs
@@ -29,9 +29,9 @@ struct Foo<'lt, T, const C: usize> {
             tp T
             un Union
             bt u32
-            kw crate
-            kw self
-            kw super
+            kw crate::
+            kw self::
+            kw super::
         "#]],
     )
 }
@@ -55,12 +55,12 @@ struct Foo<'lt, T, const C: usize>(f$0);
             tp T
             un Union
             bt u32
-            kw crate
+            kw crate::
             kw pub
             kw pub(crate)
             kw pub(super)
-            kw self
-            kw super
+            kw self::
+            kw super::
         "#]],
     )
 }
@@ -82,9 +82,9 @@ fn x<'lt, T, const C: usize>() -> $0
             tp T
             un Union
             bt u32
-            kw crate
-            kw self
-            kw super
+            kw crate::
+            kw self::
+            kw super::
         "#]],
     );
 }
@@ -108,9 +108,9 @@ const FOO: $0 = Foo(2);
             un Union
             bt u32
             it Foo<i32>
-            kw crate
-            kw self
-            kw super
+            kw crate::
+            kw self::
+            kw super::
         "#]],
     );
 }
@@ -135,9 +135,9 @@ fn f2() {
             un Union
             bt u32
             it i32
-            kw crate
-            kw self
-            kw super
+            kw crate::
+            kw self::
+            kw super::
         "#]],
     );
 }
@@ -164,9 +164,9 @@ fn f2() {
             un Union
             bt u32
             it u64
-            kw crate
-            kw self
-            kw super
+            kw crate::
+            kw self::
+            kw super::
         "#]],
     );
 }
@@ -190,9 +190,9 @@ fn f2(x: u64) -> $0 {
             un Union
             bt u32
             it u64
-            kw crate
-            kw self
-            kw super
+            kw crate::
+            kw self::
+            kw super::
         "#]],
     );
 }
@@ -217,9 +217,9 @@ fn f2(x: $0) {
             un Union
             bt u32
             it i32
-            kw crate
-            kw self
-            kw super
+            kw crate::
+            kw self::
+            kw super::
         "#]],
     );
 }
@@ -252,9 +252,9 @@ fn foo<'lt, T, const C: usize>() {
             un Union
             bt u32
             it a::Foo<a::Foo<i32>>
-            kw crate
-            kw self
-            kw super
+            kw crate::
+            kw self::
+            kw super::
         "#]],
     );
 }
@@ -282,9 +282,9 @@ fn foo<'lt, T, const C: usize>() {
             un Union
             bt u32
             it Foo<i32>
-            kw crate
-            kw self
-            kw super
+            kw crate::
+            kw self::
+            kw super::
         "#]],
     );
 }
@@ -309,9 +309,9 @@ fn foo<'lt, T, const C: usize>() {
             tp T
             un Union
             bt u32
-            kw crate
-            kw self
-            kw super
+            kw crate::
+            kw self::
+            kw super::
         "#]],
     );
     check(
@@ -359,9 +359,9 @@ fn foo<'lt, T: Trait2<$0>, const CONST_PARAM: usize>(_: T) {}
             tp T
             un Union
             bt u32
-            kw crate
-            kw self
-            kw super
+            kw crate::
+            kw self::
+            kw super::
         "#]],
     );
     check(