diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index c2b68a85301..58964176026 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -2496,6 +2496,18 @@ impl ScopeDef {
 
         items
     }
+
+    pub fn is_value_def(&self) -> bool {
+        matches!(
+            self,
+            ScopeDef::ModuleDef(ModuleDef::Function(_))
+                | ScopeDef::ModuleDef(ModuleDef::Variant(_))
+                | ScopeDef::ModuleDef(ModuleDef::Const(_))
+                | ScopeDef::ModuleDef(ModuleDef::Static(_))
+                | ScopeDef::GenericParam(GenericParam::ConstParam(_))
+                | ScopeDef::Local(_)
+        )
+    }
 }
 
 impl From<ItemInNs> for ScopeDef {
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index 2d08a7704fa..827e23e2bd0 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -35,8 +35,9 @@ pub enum PathResolution {
     Def(ModuleDef),
     /// A local binding (only value namespace)
     Local(Local),
-    /// A generic parameter
+    /// A type parameter
     TypeParam(TypeParam),
+    /// A const parameter
     ConstParam(ConstParam),
     SelfType(Impl),
     Macro(MacroDef),
diff --git a/crates/ide_completion/src/completions.rs b/crates/ide_completion/src/completions.rs
index 7a4d71e9182..e07a4c403f3 100644
--- a/crates/ide_completion/src/completions.rs
+++ b/crates/ide_completion/src/completions.rs
@@ -56,10 +56,16 @@ impl Builder {
 }
 
 impl Completions {
-    pub(crate) fn add(&mut self, item: CompletionItem) {
+    fn add(&mut self, item: CompletionItem) {
         self.buf.push(item)
     }
 
+    fn add_opt(&mut self, item: Option<CompletionItem>) {
+        if let Some(item) = item {
+            self.buf.push(item)
+        }
+    }
+
     pub(crate) fn add_all<I>(&mut self, items: I)
     where
         I: IntoIterator,
@@ -103,9 +109,10 @@ impl Completions {
         local_name: hir::Name,
         resolution: &hir::ScopeDef,
     ) {
-        if let Some(item) = render_resolution(RenderContext::new(ctx), local_name, resolution) {
-            self.add(item);
+        if ctx.expects_type() && resolution.is_value_def() {
+            return;
         }
+        self.add_opt(render_resolution(RenderContext::new(ctx), local_name, resolution));
     }
 
     pub(crate) fn add_macro(
@@ -118,9 +125,7 @@ impl Completions {
             Some(it) => it,
             None => return,
         };
-        if let Some(item) = render_macro(RenderContext::new(ctx), None, name, macro_) {
-            self.add(item);
-        }
+        self.add_opt(render_macro(RenderContext::new(ctx), None, name, macro_));
     }
 
     pub(crate) fn add_function(
@@ -129,9 +134,10 @@ impl Completions {
         func: hir::Function,
         local_name: Option<hir::Name>,
     ) {
-        if let Some(item) = render_fn(RenderContext::new(ctx), None, local_name, func) {
-            self.add(item)
+        if ctx.expects_type() {
+            return;
         }
+        self.add_opt(render_fn(RenderContext::new(ctx), None, local_name, func));
     }
 
     pub(crate) fn add_method(
@@ -141,10 +147,7 @@ impl Completions {
         receiver: Option<hir::Name>,
         local_name: Option<hir::Name>,
     ) {
-        if let Some(item) = render_method(RenderContext::new(ctx), None, receiver, local_name, func)
-        {
-            self.add(item)
-        }
+        self.add_opt(render_method(RenderContext::new(ctx), None, receiver, local_name, func));
     }
 
     pub(crate) fn add_variant_pat(
@@ -153,9 +156,7 @@ impl Completions {
         variant: hir::Variant,
         local_name: Option<hir::Name>,
     ) {
-        if let Some(item) = render_variant_pat(RenderContext::new(ctx), variant, local_name, None) {
-            self.add(item);
-        }
+        self.add_opt(render_variant_pat(RenderContext::new(ctx), variant, local_name, None));
     }
 
     pub(crate) fn add_qualified_variant_pat(
@@ -164,9 +165,7 @@ impl Completions {
         variant: hir::Variant,
         path: hir::ModPath,
     ) {
-        if let Some(item) = render_variant_pat(RenderContext::new(ctx), variant, None, Some(path)) {
-            self.add(item);
-        }
+        self.add_opt(render_variant_pat(RenderContext::new(ctx), variant, None, Some(path)));
     }
 
     pub(crate) fn add_struct_pat(
@@ -175,21 +174,18 @@ impl Completions {
         strukt: hir::Struct,
         local_name: Option<hir::Name>,
     ) {
-        if let Some(item) = render_struct_pat(RenderContext::new(ctx), strukt, local_name) {
-            self.add(item);
-        }
+        self.add_opt(render_struct_pat(RenderContext::new(ctx), strukt, local_name));
     }
 
     pub(crate) fn add_const(&mut self, ctx: &CompletionContext, constant: hir::Const) {
-        if let Some(item) = render_const(RenderContext::new(ctx), constant) {
-            self.add(item);
+        if ctx.expects_type() {
+            return;
         }
+        self.add_opt(render_const(RenderContext::new(ctx), constant));
     }
 
     pub(crate) fn add_type_alias(&mut self, ctx: &CompletionContext, type_alias: hir::TypeAlias) {
-        if let Some(item) = render_type_alias(RenderContext::new(ctx), type_alias) {
-            self.add(item)
-        }
+        self.add_opt(render_type_alias(RenderContext::new(ctx), type_alias));
     }
 
     pub(crate) fn add_qualified_enum_variant(
diff --git a/crates/ide_completion/src/completions/attribute.rs b/crates/ide_completion/src/completions/attribute.rs
index d3392100d90..7f76e357ec3 100644
--- a/crates/ide_completion/src/completions/attribute.rs
+++ b/crates/ide_completion/src/completions/attribute.rs
@@ -69,7 +69,7 @@ fn complete_new_attribute(acc: &mut Completions, ctx: &CompletionContext, attrib
         }
 
         if is_inner || !attr_completion.prefer_inner {
-            acc.add(item.build());
+            item.add_to(acc);
         }
     };
 
@@ -96,7 +96,7 @@ fn complete_new_attribute(acc: &mut Completions, ctx: &CompletionContext, attrib
                 if let Some(docs) = mac.docs(ctx.sema.db) {
                     item.documentation(docs);
                 }
-                acc.add(item.build());
+                item.add_to(acc);
             }
         }
     });
diff --git a/crates/ide_completion/src/completions/flyimport.rs b/crates/ide_completion/src/completions/flyimport.rs
index 7bf47bf7571..c010cbbca64 100644
--- a/crates/ide_completion/src/completions/flyimport.rs
+++ b/crates/ide_completion/src/completions/flyimport.rs
@@ -90,7 +90,6 @@
 //! Note that having this flag set to `true` does not guarantee that the feature is enabled: your client needs to have the corredponding
 //! capability enabled.
 
-use hir::ModPath;
 use ide_db::helpers::{
     import_assets::{ImportAssets, ImportCandidate},
     insert_use::ImportScope,
@@ -208,7 +207,7 @@ fn import_assets(ctx: &CompletionContext, fuzzy_name: String) -> Option<ImportAs
 }
 
 fn compute_fuzzy_completion_order_key(
-    proposed_mod_path: &ModPath,
+    proposed_mod_path: &hir::ModPath,
     user_input_lowercased: &str,
 ) -> usize {
     cov_mark::hit!(certain_fuzzy_order_test);
diff --git a/crates/ide_completion/src/completions/unqualified_path.rs b/crates/ide_completion/src/completions/unqualified_path.rs
index 8b22933e0a2..f370dbdf0bb 100644
--- a/crates/ide_completion/src/completions/unqualified_path.rs
+++ b/crates/ide_completion/src/completions/unqualified_path.rs
@@ -339,7 +339,6 @@ fn x() -> $0
 "#,
             expect![[r#"
                 st Foo
-                fn x() fn()
             "#]],
         );
     }
@@ -391,7 +390,6 @@ pub mod prelude {
 }
 "#,
             expect![[r#"
-                fn foo()  fn()
                 md std
                 st Option
             "#]],
@@ -448,7 +446,6 @@ pub mod prelude {
 }
 "#,
             expect![[r#"
-                fn foo()  fn()
                 md std
                 md core
                 st String
@@ -509,7 +506,6 @@ macro_rules! foo { () => {} }
 fn main() { let x: $0 }
 "#,
             expect![[r#"
-                fn main()  fn()
                 ma foo!(…) macro_rules! foo
             "#]],
         );
diff --git a/crates/ide_completion/src/context.rs b/crates/ide_completion/src/context.rs
index 6177caa12bb..2c2a4aa6bf1 100644
--- a/crates/ide_completion/src/context.rs
+++ b/crates/ide_completion/src/context.rs
@@ -29,6 +29,12 @@ pub(crate) enum PatternRefutability {
     Irrefutable,
 }
 
+#[derive(Debug)]
+pub(super) enum PathKind {
+    Expr,
+    Type,
+}
+
 #[derive(Debug)]
 pub(crate) struct PathCompletionContext {
     /// If this is a call with () already there
@@ -36,13 +42,12 @@ pub(crate) struct PathCompletionContext {
     /// A single-indent path, like `foo`. `::foo` should not be considered a trivial path.
     pub(super) is_trivial_path: bool,
     /// If not a trivial path, the prefix (qualifier).
-    pub(super) path_qual: Option<ast::Path>,
-    pub(super) is_path_type: bool,
+    pub(super) qualifier: Option<ast::Path>,
+    pub(super) kind: Option<PathKind>,
+    /// Whether the path segment has type args or not.
     pub(super) has_type_args: bool,
     /// `true` if we are a statement or a last expr in the block.
     pub(super) can_be_stmt: bool,
-    /// `true` if we expect an expression at the cursor position.
-    pub(super) is_expr: bool,
     pub(super) in_loop_body: bool,
 }
 
@@ -308,7 +313,11 @@ impl<'a> CompletionContext<'a> {
     }
 
     pub(crate) fn expects_expression(&self) -> bool {
-        self.path_context.as_ref().map_or(false, |it| it.is_expr)
+        matches!(self.path_context, Some(PathCompletionContext { kind: Some(PathKind::Expr), .. }))
+    }
+
+    pub(crate) fn expects_type(&self) -> bool {
+        matches!(self.path_context, Some(PathCompletionContext { kind: Some(PathKind::Type), .. }))
     }
 
     pub(crate) fn path_call_kind(&self) -> Option<CallKind> {
@@ -316,11 +325,11 @@ impl<'a> CompletionContext<'a> {
     }
 
     pub(crate) fn is_trivial_path(&self) -> bool {
-        self.path_context.as_ref().map_or(false, |it| it.is_trivial_path)
+        matches!(self.path_context, Some(PathCompletionContext { is_trivial_path: true, .. }))
     }
 
     pub(crate) fn path_qual(&self) -> Option<&ast::Path> {
-        self.path_context.as_ref().and_then(|it| it.path_qual.as_ref())
+        self.path_context.as_ref().and_then(|it| it.qualifier.as_ref())
     }
 
     fn fill_impl_def(&mut self) {
@@ -573,12 +582,11 @@ impl<'a> CompletionContext<'a> {
             let path_ctx = self.path_context.get_or_insert(PathCompletionContext {
                 call_kind: None,
                 is_trivial_path: false,
-                path_qual: None,
+                qualifier: None,
                 has_type_args: false,
-                is_path_type: false,
                 can_be_stmt: false,
-                is_expr: false,
                 in_loop_body: false,
+                kind: None,
             });
             path_ctx.in_loop_body = is_in_loop_body(name_ref.syntax());
             let path = segment.parent_path();
@@ -593,11 +601,20 @@ impl<'a> CompletionContext<'a> {
                     }
                 };
             }
-            path_ctx.is_path_type = path.syntax().parent().and_then(ast::PathType::cast).is_some();
+
+            if let Some(parent) = path.syntax().parent() {
+                path_ctx.kind = match_ast! {
+                    match parent {
+                        ast::PathType(_it) => Some(PathKind::Type),
+                        ast::PathExpr(_it) => Some(PathKind::Expr),
+                        _ => None,
+                    }
+                };
+            }
             path_ctx.has_type_args = segment.generic_arg_list().is_some();
 
             if let Some(path) = path_or_use_tree_qualifier(&path) {
-                path_ctx.path_qual = path
+                path_ctx.qualifier = path
                     .segment()
                     .and_then(|it| {
                         find_node_with_range::<ast::PathSegment>(
@@ -635,7 +652,6 @@ impl<'a> CompletionContext<'a> {
                     None
                 })
                 .unwrap_or(false);
-            path_ctx.is_expr = path.syntax().parent().and_then(ast::PathExpr::cast).is_some();
         }
     }
 }
diff --git a/crates/ide_completion/src/render.rs b/crates/ide_completion/src/render.rs
index 750694432ea..7118183fe06 100644
--- a/crates/ide_completion/src/render.rs
+++ b/crates/ide_completion/src/render.rs
@@ -18,6 +18,7 @@ use ide_db::{
 use syntax::TextRange;
 
 use crate::{
+    context::{PathCompletionContext, PathKind},
     item::{CompletionRelevanceTypeMatch, ImportEdit},
     render::{enum_variant::render_variant, function::render_fn, macro_::render_macro},
     CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, CompletionRelevance,
@@ -54,6 +55,9 @@ pub(crate) fn render_resolution_with_import<'a>(
     import_edit: ImportEdit,
 ) -> Option<CompletionItem> {
     let resolution = hir::ScopeDef::from(import_edit.import.original_item);
+    if ctx.completion.expects_type() && resolution.is_value_def() {
+        return None;
+    }
     let local_name = match resolution {
         hir::ScopeDef::ModuleDef(hir::ModuleDef::Function(f)) => f.name(ctx.completion.db),
         hir::ScopeDef::ModuleDef(hir::ModuleDef::Const(c)) => c.name(ctx.completion.db)?,
@@ -275,13 +279,10 @@ impl<'a> Render<'a> {
         };
 
         // Add `<>` for generic types
-        if self
-            .ctx
-            .completion
-            .path_context
-            .as_ref()
-            .map_or(false, |it| it.is_path_type && !it.has_type_args)
-            && self.ctx.completion.config.add_call_parenthesis
+        if matches!(
+            self.ctx.completion.path_context,
+            Some(PathCompletionContext { kind: Some(PathKind::Type), has_type_args: false, .. })
+        ) && self.ctx.completion.config.add_call_parenthesis
         {
             if let Some(cap) = self.ctx.snippet_cap() {
                 let has_non_default_type_params = match resolution {