diff --git a/crates/base-db/src/fixture.rs b/crates/base-db/src/fixture.rs
index e89d3ae4bb3..5b11343173b 100644
--- a/crates/base-db/src/fixture.rs
+++ b/crates/base-db/src/fixture.rs
@@ -21,6 +21,7 @@ use crate::{
 pub const WORKSPACE: SourceRootId = SourceRootId(0);
 
 pub trait WithFixture: Default + SourceDatabaseExt + 'static {
+    #[track_caller]
     fn with_single_file(ra_fixture: &str) -> (Self, FileId) {
         let fixture = ChangeFixture::parse(ra_fixture);
         let mut db = Self::default();
@@ -29,6 +30,7 @@ pub trait WithFixture: Default + SourceDatabaseExt + 'static {
         (db, fixture.files[0])
     }
 
+    #[track_caller]
     fn with_many_files(ra_fixture: &str) -> (Self, Vec<FileId>) {
         let fixture = ChangeFixture::parse(ra_fixture);
         let mut db = Self::default();
@@ -37,6 +39,7 @@ pub trait WithFixture: Default + SourceDatabaseExt + 'static {
         (db, fixture.files)
     }
 
+    #[track_caller]
     fn with_files(ra_fixture: &str) -> Self {
         let fixture = ChangeFixture::parse(ra_fixture);
         let mut db = Self::default();
@@ -45,6 +48,7 @@ pub trait WithFixture: Default + SourceDatabaseExt + 'static {
         db
     }
 
+    #[track_caller]
     fn with_files_extra_proc_macros(
         ra_fixture: &str,
         proc_macros: Vec<(String, ProcMacro)>,
@@ -56,18 +60,21 @@ pub trait WithFixture: Default + SourceDatabaseExt + 'static {
         db
     }
 
+    #[track_caller]
     fn with_position(ra_fixture: &str) -> (Self, FilePosition) {
         let (db, file_id, range_or_offset) = Self::with_range_or_offset(ra_fixture);
         let offset = range_or_offset.expect_offset();
         (db, FilePosition { file_id, offset })
     }
 
+    #[track_caller]
     fn with_range(ra_fixture: &str) -> (Self, FileRange) {
         let (db, file_id, range_or_offset) = Self::with_range_or_offset(ra_fixture);
         let range = range_or_offset.expect_range();
         (db, FileRange { file_id, range })
     }
 
+    #[track_caller]
     fn with_range_or_offset(ra_fixture: &str) -> (Self, FileId, RangeOrOffset) {
         let fixture = ChangeFixture::parse(ra_fixture);
         let mut db = Self::default();
diff --git a/crates/hir-def/src/resolver.rs b/crates/hir-def/src/resolver.rs
index afa3b33cc9f..3eaff61b154 100644
--- a/crates/hir-def/src/resolver.rs
+++ b/crates/hir-def/src/resolver.rs
@@ -1046,6 +1046,12 @@ impl HasResolver for GenericDefId {
     }
 }
 
+impl HasResolver for EnumVariantId {
+    fn resolver(self, db: &dyn DefDatabase) -> Resolver {
+        self.parent.resolver(db)
+    }
+}
+
 impl HasResolver for VariantId {
     fn resolver(self, db: &dyn DefDatabase) -> Resolver {
         match self {
diff --git a/crates/hir-ty/src/builder.rs b/crates/hir-ty/src/builder.rs
index 2362b08f79a..eec57ba3f80 100644
--- a/crates/hir-ty/src/builder.rs
+++ b/crates/hir-ty/src/builder.rs
@@ -194,6 +194,19 @@ impl TyBuilder<()> {
         params.placeholder_subst(db)
     }
 
+    pub fn unknown_subst(db: &dyn HirDatabase, def: impl Into<GenericDefId>) -> Substitution {
+        let params = generics(db.upcast(), def.into());
+        Substitution::from_iter(
+            Interner,
+            params.iter_id().map(|id| match id {
+                either::Either::Left(_) => TyKind::Error.intern(Interner).cast(Interner),
+                either::Either::Right(id) => {
+                    unknown_const_as_generic(db.const_param_ty(id)).cast(Interner)
+                }
+            }),
+        )
+    }
+
     pub fn subst_for_def(
         db: &dyn HirDatabase,
         def: impl Into<GenericDefId>,
diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs
index f01ee1b4e60..11c0ccf547d 100644
--- a/crates/hir-ty/src/infer.rs
+++ b/crates/hir-ty/src/infer.rs
@@ -215,6 +215,10 @@ pub enum InferenceDiagnostic {
         call_expr: ExprId,
         found: Ty,
     },
+    TypedHole {
+        expr: ExprId,
+        expected: Ty,
+    },
 }
 
 /// A mismatch between an expected and an inferred type.
@@ -600,29 +604,30 @@ impl<'a> InferenceContext<'a> {
             mismatch.actual = table.resolve_completely(mismatch.actual.clone());
         }
         result.diagnostics.retain_mut(|diagnostic| {
-            if let InferenceDiagnostic::ExpectedFunction { found: ty, .. }
-            | InferenceDiagnostic::UnresolvedField { receiver: ty, .. }
-            | InferenceDiagnostic::UnresolvedMethodCall { receiver: ty, .. } = diagnostic
-            {
-                *ty = table.resolve_completely(ty.clone());
-                // FIXME: Remove this when we are on par with rustc in terms of inference
-                if ty.contains_unknown() {
-                    return false;
-                }
+            use InferenceDiagnostic::*;
+            match diagnostic {
+                ExpectedFunction { found: ty, .. }
+                | UnresolvedField { receiver: ty, .. }
+                | UnresolvedMethodCall { receiver: ty, .. } => {
+                    *ty = table.resolve_completely(ty.clone());
+                    // FIXME: Remove this when we are on par with rustc in terms of inference
+                    if ty.contains_unknown() {
+                        return false;
+                    }
 
-                if let InferenceDiagnostic::UnresolvedMethodCall { field_with_same_name, .. } =
-                    diagnostic
-                {
-                    let clear = if let Some(ty) = field_with_same_name {
-                        *ty = table.resolve_completely(ty.clone());
-                        ty.contains_unknown()
-                    } else {
-                        false
-                    };
-                    if clear {
-                        *field_with_same_name = None;
+                    if let UnresolvedMethodCall { field_with_same_name, .. } = diagnostic {
+                        if let Some(ty) = field_with_same_name {
+                            *ty = table.resolve_completely(ty.clone());
+                            if ty.contains_unknown() {
+                                *field_with_same_name = None;
+                            }
+                        }
                     }
                 }
+                TypedHole { expected: ty, .. } => {
+                    *ty = table.resolve_completely(ty.clone());
+                }
+                _ => (),
             }
             true
         });
diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs
index f3075848430..d7c6691ea0c 100644
--- a/crates/hir-ty/src/infer/expr.rs
+++ b/crates/hir-ty/src/infer/expr.rs
@@ -874,9 +874,15 @@ impl<'a> InferenceContext<'a> {
             },
             Expr::Underscore => {
                 // Underscore expressions may only appear in assignee expressions,
-                // which are handled by `infer_assignee_expr()`, so any underscore
-                // expression reaching this branch is an error.
-                self.err_ty()
+                // which are handled by `infer_assignee_expr()`.
+                // Any other underscore expression is an error, we render a specialized diagnostic
+                // to let the user know what type is expected though.
+                let expected = expected.to_option(&mut self.table).unwrap_or_else(|| self.err_ty());
+                self.push_diagnostic(InferenceDiagnostic::TypedHole {
+                    expr: tgt_expr,
+                    expected: expected.clone(),
+                });
+                expected
             }
         };
         // use a new type variable if we got unknown here
@@ -1001,12 +1007,13 @@ impl<'a> InferenceContext<'a> {
             }
             &Array::Repeat { initializer, repeat } => {
                 self.infer_expr_coerce(initializer, &Expectation::has_type(elem_ty.clone()));
-                self.infer_expr(
-                    repeat,
-                    &Expectation::HasType(
-                        TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(Interner),
-                    ),
-                );
+                let usize = TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(Interner);
+                match self.body[repeat] {
+                    Expr::Underscore => {
+                        self.write_expr_ty(repeat, usize);
+                    }
+                    _ => _ = self.infer_expr(repeat, &Expectation::HasType(usize)),
+                }
 
                 (
                     elem_ty,
diff --git a/crates/hir/src/diagnostics.rs b/crates/hir/src/diagnostics.rs
index 10893b62bfb..b64d81490bb 100644
--- a/crates/hir/src/diagnostics.rs
+++ b/crates/hir/src/diagnostics.rs
@@ -52,6 +52,7 @@ diagnostics![
     PrivateAssocItem,
     PrivateField,
     ReplaceFilterMapNextWithFindMap,
+    TypedHole,
     TypeMismatch,
     UndeclaredLabel,
     UnimplementedBuiltinMacro,
@@ -73,6 +74,12 @@ pub struct BreakOutsideOfLoop {
     pub bad_value_break: bool,
 }
 
+#[derive(Debug)]
+pub struct TypedHole {
+    pub expr: InFile<AstPtr<ast::Expr>>,
+    pub expected: Type,
+}
+
 #[derive(Debug)]
 pub struct UnresolvedModule {
     pub decl: InFile<AstPtr<ast::Module>>,
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index b1583c9d00b..5392cb6a32a 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -69,7 +69,8 @@ use hir_ty::{
     traits::FnTrait,
     AliasTy, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast, ClosureId,
     GenericArgData, Interner, ParamKind, QuantifiedWhereClause, Scalar, Substitution,
-    TraitEnvironment, TraitRefExt, Ty, TyBuilder, TyDefId, TyExt, TyKind, WhereClause,
+    TraitEnvironment, TraitRefExt, Ty, TyBuilder, TyDefId, TyExt, TyKind, ValueTyDefId,
+    WhereClause,
 };
 use itertools::Itertools;
 use nameres::diagnostics::DefDiagnosticKind;
@@ -91,10 +92,10 @@ pub use crate::{
         IncorrectCase, InvalidDeriveTarget, MacroDefError, MacroError, MacroExpansionParseError,
         MalformedDerive, MismatchedArgCount, MissingFields, MissingMatchArms, MissingUnsafe,
         MovedOutOfRef, NeedMut, NoSuchField, PrivateAssocItem, PrivateField,
-        ReplaceFilterMapNextWithFindMap, TypeMismatch, UndeclaredLabel, UnimplementedBuiltinMacro,
-        UnreachableLabel, UnresolvedExternCrate, UnresolvedField, UnresolvedImport,
-        UnresolvedMacroCall, UnresolvedMethodCall, UnresolvedModule, UnresolvedProcMacro,
-        UnusedMut,
+        ReplaceFilterMapNextWithFindMap, TypeMismatch, TypedHole, UndeclaredLabel,
+        UnimplementedBuiltinMacro, UnreachableLabel, UnresolvedExternCrate, UnresolvedField,
+        UnresolvedImport, UnresolvedMacroCall, UnresolvedMethodCall, UnresolvedModule,
+        UnresolvedProcMacro, UnusedMut,
     },
     has_source::HasSource,
     semantics::{PathResolution, Semantics, SemanticsScope, TypeInfo, VisibleTraits},
@@ -1005,6 +1006,10 @@ impl Struct {
         Type::from_def(db, self.id)
     }
 
+    pub fn constructor_ty(self, db: &dyn HirDatabase) -> Type {
+        Type::from_value_def(db, self.id)
+    }
+
     pub fn repr(self, db: &dyn HirDatabase) -> Option<ReprOptions> {
         db.struct_data(self.id).repr
     }
@@ -1042,6 +1047,10 @@ impl Union {
         Type::from_def(db, self.id)
     }
 
+    pub fn constructor_ty(self, db: &dyn HirDatabase) -> Type {
+        Type::from_value_def(db, self.id)
+    }
+
     pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> {
         db.union_data(self.id)
             .variant_data
@@ -1173,6 +1182,10 @@ impl Variant {
         self.parent
     }
 
+    pub fn constructor_ty(self, db: &dyn HirDatabase) -> Type {
+        Type::from_value_def(db, EnumVariantId { parent: self.parent.id, local_id: self.id })
+    }
+
     pub fn name(self, db: &dyn HirDatabase) -> Name {
         db.enum_data(self.parent.id).variants[self.id].name.clone()
     }
@@ -1574,6 +1587,16 @@ impl DefWithBody {
                     let expr = expr_syntax(expr);
                     acc.push(BreakOutsideOfLoop { expr, is_break, bad_value_break }.into())
                 }
+                hir_ty::InferenceDiagnostic::TypedHole { expr, expected } => {
+                    let expr = expr_syntax(*expr);
+                    acc.push(
+                        TypedHole {
+                            expr,
+                            expected: Type::new(db, DefWithBodyId::from(self), expected.clone()),
+                        }
+                        .into(),
+                    )
+                }
             }
         }
         for (pat_or_expr, mismatch) in infer.type_mismatches() {
@@ -1806,6 +1829,10 @@ impl Function {
         db.function_data(self.id).name.clone()
     }
 
+    pub fn ty(self, db: &dyn HirDatabase) -> Type {
+        Type::from_value_def(db, self.id)
+    }
+
     /// Get this function's return type
     pub fn ret_type(self, db: &dyn HirDatabase) -> Type {
         let resolver = self.id.resolver(db.upcast());
@@ -2085,11 +2112,7 @@ impl Const {
     }
 
     pub fn ty(self, db: &dyn HirDatabase) -> Type {
-        let data = db.const_data(self.id);
-        let resolver = self.id.resolver(db.upcast());
-        let ctx = hir_ty::TyLoweringContext::new(db, &resolver);
-        let ty = ctx.lower_ty(&data.type_ref);
-        Type::new_with_resolver_inner(db, &resolver, ty)
+        Type::from_value_def(db, self.id)
     }
 
     pub fn render_eval(self, db: &dyn HirDatabase) -> Result<String, ConstEvalError> {
@@ -2136,11 +2159,7 @@ impl Static {
     }
 
     pub fn ty(self, db: &dyn HirDatabase) -> Type {
-        let data = db.static_data(self.id);
-        let resolver = self.id.resolver(db.upcast());
-        let ctx = hir_ty::TyLoweringContext::new(db, &resolver);
-        let ty = ctx.lower_ty(&data.type_ref);
-        Type::new_with_resolver_inner(db, &resolver, ty)
+        Type::from_value_def(db, self.id)
     }
 }
 
@@ -3409,24 +3428,33 @@ impl Type {
         Type { env: environment, ty }
     }
 
-    fn from_def(db: &dyn HirDatabase, def: impl HasResolver + Into<TyDefId>) -> Type {
-        let ty_def = def.into();
-        let parent_subst = match ty_def {
-            TyDefId::TypeAliasId(id) => match id.lookup(db.upcast()).container {
-                ItemContainerId::TraitId(id) => {
-                    let subst = TyBuilder::subst_for_def(db, id, None).fill_with_unknown().build();
-                    Some(subst)
-                }
-                ItemContainerId::ImplId(id) => {
-                    let subst = TyBuilder::subst_for_def(db, id, None).fill_with_unknown().build();
-                    Some(subst)
-                }
-                _ => None,
+    fn from_def(db: &dyn HirDatabase, def: impl Into<TyDefId> + HasResolver) -> Type {
+        let ty = db.ty(def.into());
+        let substs = TyBuilder::unknown_subst(
+            db,
+            match def.into() {
+                TyDefId::AdtId(it) => GenericDefId::AdtId(it),
+                TyDefId::TypeAliasId(it) => GenericDefId::TypeAliasId(it),
+                TyDefId::BuiltinType(_) => return Type::new(db, def, ty.skip_binders().clone()),
             },
-            _ => None,
-        };
-        let ty = TyBuilder::def_ty(db, ty_def, parent_subst).fill_with_unknown().build();
-        Type::new(db, def, ty)
+        );
+        Type::new(db, def, ty.substitute(Interner, &substs))
+    }
+
+    fn from_value_def(db: &dyn HirDatabase, def: impl Into<ValueTyDefId> + HasResolver) -> Type {
+        let ty = db.value_ty(def.into());
+        let substs = TyBuilder::unknown_subst(
+            db,
+            match def.into() {
+                ValueTyDefId::ConstId(it) => GenericDefId::ConstId(it),
+                ValueTyDefId::FunctionId(it) => GenericDefId::FunctionId(it),
+                ValueTyDefId::StructId(it) => GenericDefId::AdtId(AdtId::StructId(it)),
+                ValueTyDefId::UnionId(it) => GenericDefId::AdtId(AdtId::UnionId(it)),
+                ValueTyDefId::EnumVariantId(it) => GenericDefId::EnumVariantId(it),
+                ValueTyDefId::StaticId(_) => return Type::new(db, def, ty.skip_binders().clone()),
+            },
+        );
+        Type::new(db, def, ty.substitute(Interner, &substs))
     }
 
     pub fn new_slice(ty: Type) -> Type {
diff --git a/crates/ide-diagnostics/src/handlers/typed_hole.rs b/crates/ide-diagnostics/src/handlers/typed_hole.rs
new file mode 100644
index 00000000000..e12bbcf6820
--- /dev/null
+++ b/crates/ide-diagnostics/src/handlers/typed_hole.rs
@@ -0,0 +1,232 @@
+use hir::{db::ExpandDatabase, ClosureStyle, HirDisplay, StructKind};
+use ide_db::{
+    assists::{Assist, AssistId, AssistKind, GroupLabel},
+    label::Label,
+    source_change::SourceChange,
+};
+use syntax::AstNode;
+use text_edit::TextEdit;
+
+use crate::{Diagnostic, DiagnosticsContext};
+
+// Diagnostic: typed-hole
+//
+// This diagnostic is triggered when an underscore expression is used in an invalid position.
+pub(crate) fn typed_hole(ctx: &DiagnosticsContext<'_>, d: &hir::TypedHole) -> Diagnostic {
+    let display_range = ctx.sema.diagnostics_display_range(d.expr.clone().map(|it| it.into()));
+    let (message, fixes) = if d.expected.is_unknown() {
+        ("`_` expressions may only appear on the left-hand side of an assignment".to_owned(), None)
+    } else {
+        (
+            format!(
+                "invalid `_` expression, expected type `{}`",
+                d.expected.display(ctx.sema.db).with_closure_style(ClosureStyle::ClosureWithId),
+            ),
+            fixes(ctx, d),
+        )
+    };
+
+    Diagnostic::new("typed-hole", message, display_range.range).with_fixes(fixes)
+}
+
+fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::TypedHole) -> Option<Vec<Assist>> {
+    let db = ctx.sema.db;
+    let root = db.parse_or_expand(d.expr.file_id);
+    let original_range =
+        d.expr.as_ref().map(|it| it.to_node(&root)).syntax().original_file_range_opt(db)?;
+    let scope = ctx.sema.scope(d.expr.value.to_node(&root).syntax())?;
+    let mut assists = vec![];
+    scope.process_all_names(&mut |name, def| {
+        let ty = match def {
+            hir::ScopeDef::ModuleDef(it) => match it {
+                hir::ModuleDef::Function(it) => it.ty(db),
+                hir::ModuleDef::Adt(hir::Adt::Struct(it)) if it.kind(db) != StructKind::Record => {
+                    it.constructor_ty(db)
+                }
+                hir::ModuleDef::Variant(it) if it.kind(db) != StructKind::Record => {
+                    it.constructor_ty(db)
+                }
+                hir::ModuleDef::Const(it) => it.ty(db),
+                hir::ModuleDef::Static(it) => it.ty(db),
+                _ => return,
+            },
+            hir::ScopeDef::GenericParam(hir::GenericParam::ConstParam(it)) => it.ty(db),
+            hir::ScopeDef::Local(it) => it.ty(db),
+            _ => return,
+        };
+        // FIXME: should also check coercions if it is at a coercion site
+        if !ty.contains_unknown() && ty.could_unify_with(db, &d.expected) {
+            assists.push(Assist {
+                id: AssistId("typed-hole", AssistKind::QuickFix),
+                label: Label::new(format!("Replace `_` with `{}`", name.display(db))),
+                group: Some(GroupLabel("Replace `_` with a matching entity in scope".to_owned())),
+                target: original_range.range,
+                source_change: Some(SourceChange::from_text_edit(
+                    original_range.file_id,
+                    TextEdit::replace(original_range.range, name.display(db).to_string()),
+                )),
+                trigger_signature_help: false,
+            });
+        }
+    });
+    if assists.is_empty() {
+        None
+    } else {
+        Some(assists)
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use crate::tests::{check_diagnostics, check_fixes};
+
+    #[test]
+    fn unknown() {
+        check_diagnostics(
+            r#"
+fn main() {
+    _;
+  //^ error: `_` expressions may only appear on the left-hand side of an assignment
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn concrete_expectation() {
+        check_diagnostics(
+            r#"
+fn main() {
+    if _ {}
+     //^ error: invalid `_` expression, expected type `bool`
+    let _: fn() -> i32 = _;
+                       //^ error: invalid `_` expression, expected type `fn() -> i32`
+    let _: fn() -> () = _; // FIXME: This should trigger an assist because `main` matches via *coercion*
+                      //^ error: invalid `_` expression, expected type `fn()`
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn integer_ty_var() {
+        check_diagnostics(
+            r#"
+fn main() {
+    let mut x = 3;
+    x = _;
+      //^ 💡 error: invalid `_` expression, expected type `i32`
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn ty_var_resolved() {
+        check_diagnostics(
+            r#"
+fn main() {
+    let mut x = t();
+    x = _;
+      //^ 💡 error: invalid `_` expression, expected type `&str`
+    x = "";
+}
+fn t<T>() -> T { loop {} }
+"#,
+        );
+    }
+
+    #[test]
+    fn valid_positions() {
+        check_diagnostics(
+            r#"
+fn main() {
+    let x = [(); _];
+    let y: [(); 10] = [(); _];
+    _ = 0;
+    (_,) = (1,);
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn check_quick_fix() {
+        check_fixes(
+            r#"
+enum Foo {
+    Bar
+}
+use Foo::Bar;
+const C: Foo = Foo::Bar;
+fn main<const CP: Foo>(param: Foo) {
+    let local = Foo::Bar;
+    let _: Foo = _$0;
+               //^ error: invalid `_` expression, expected type `fn()`
+}
+"#,
+            vec![
+                r#"
+enum Foo {
+    Bar
+}
+use Foo::Bar;
+const C: Foo = Foo::Bar;
+fn main<const CP: Foo>(param: Foo) {
+    let local = Foo::Bar;
+    let _: Foo = local;
+               //^ error: invalid `_` expression, expected type `fn()`
+}
+"#,
+                r#"
+enum Foo {
+    Bar
+}
+use Foo::Bar;
+const C: Foo = Foo::Bar;
+fn main<const CP: Foo>(param: Foo) {
+    let local = Foo::Bar;
+    let _: Foo = param;
+               //^ error: invalid `_` expression, expected type `fn()`
+}
+"#,
+                r#"
+enum Foo {
+    Bar
+}
+use Foo::Bar;
+const C: Foo = Foo::Bar;
+fn main<const CP: Foo>(param: Foo) {
+    let local = Foo::Bar;
+    let _: Foo = CP;
+               //^ error: invalid `_` expression, expected type `fn()`
+}
+"#,
+                r#"
+enum Foo {
+    Bar
+}
+use Foo::Bar;
+const C: Foo = Foo::Bar;
+fn main<const CP: Foo>(param: Foo) {
+    let local = Foo::Bar;
+    let _: Foo = Bar;
+               //^ error: invalid `_` expression, expected type `fn()`
+}
+"#,
+                r#"
+enum Foo {
+    Bar
+}
+use Foo::Bar;
+const C: Foo = Foo::Bar;
+fn main<const CP: Foo>(param: Foo) {
+    let local = Foo::Bar;
+    let _: Foo = C;
+               //^ error: invalid `_` expression, expected type `fn()`
+}
+"#,
+            ],
+        );
+    }
+}
diff --git a/crates/ide-diagnostics/src/lib.rs b/crates/ide-diagnostics/src/lib.rs
index 048dedf6bd1..55a4a482d3b 100644
--- a/crates/ide-diagnostics/src/lib.rs
+++ b/crates/ide-diagnostics/src/lib.rs
@@ -44,6 +44,7 @@ mod handlers {
     pub(crate) mod private_assoc_item;
     pub(crate) mod private_field;
     pub(crate) mod replace_filter_map_next_with_find_map;
+    pub(crate) mod typed_hole;
     pub(crate) mod type_mismatch;
     pub(crate) mod unimplemented_builtin_macro;
     pub(crate) mod unresolved_extern_crate;
@@ -290,6 +291,7 @@ pub fn diagnostics(
             AnyDiagnostic::PrivateAssocItem(d) => handlers::private_assoc_item::private_assoc_item(&ctx, &d),
             AnyDiagnostic::PrivateField(d) => handlers::private_field::private_field(&ctx, &d),
             AnyDiagnostic::ReplaceFilterMapNextWithFindMap(d) => handlers::replace_filter_map_next_with_find_map::replace_filter_map_next_with_find_map(&ctx, &d),
+            AnyDiagnostic::TypedHole(d) => handlers::typed_hole::typed_hole(&ctx, &d),
             AnyDiagnostic::TypeMismatch(d) => handlers::type_mismatch::type_mismatch(&ctx, &d),
             AnyDiagnostic::UndeclaredLabel(d) => handlers::undeclared_label::undeclared_label(&ctx, &d),
             AnyDiagnostic::UnimplementedBuiltinMacro(d) => handlers::unimplemented_builtin_macro::unimplemented_builtin_macro(&ctx, &d),