diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index 21d22aa7fb8..5ad9547f148 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -12,7 +12,7 @@ use crate::{
     macros::MacroExpansion,
     module_tree::ModuleTree,
     nameres::{ItemMap, lower::{LoweredModule, ImportSourceMap}},
-    ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks, TypableDef},
+    ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks, TypableDef, CallableDef, FnSig},
     adt::{StructData, EnumData},
     impl_block::{ModuleImplBlocks, ImplSourceMap},
     generics::{GenericParams, GenericDef},
@@ -105,6 +105,9 @@ pub trait HirDatabase: PersistentHirDatabase {
     #[salsa::invoke(crate::ty::type_for_field)]
     fn type_for_field(&self, field: StructField) -> Ty;
 
+    #[salsa::invoke(crate::ty::callable_item_sig)]
+    fn callable_item_signature(&self, def: CallableDef) -> FnSig;
+
     #[salsa::invoke(crate::expr::body_with_source_map_query)]
     fn body_with_source_map(
         &self,
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index 31f726f3584..2ea3b341fc6 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -16,7 +16,7 @@ use std::{fmt, mem};
 
 use crate::{Name, AdtDef, type_ref::Mutability, db::HirDatabase};
 
-pub(crate) use lower::{TypableDef, CallableDef, type_for_def, type_for_field};
+pub(crate) use lower::{TypableDef, CallableDef, type_for_def, type_for_field, callable_item_sig};
 pub(crate) use infer::{infer, InferenceResult, InferTy};
 use display::{HirDisplay, HirFormatter};
 
@@ -77,8 +77,6 @@ pub enum Ty {
     FnDef {
         /// The definition of the function / constructor.
         def: CallableDef,
-        /// Parameters and return type
-        sig: FnSig,
         /// Substitutions for the generic parameters of the type
         substs: Substs,
     },
@@ -189,11 +187,7 @@ impl Ty {
                 }
                 sig.ret().walk(f);
             }
-            Ty::FnDef { substs, sig, .. } => {
-                for input in sig.params() {
-                    input.walk(f);
-                }
-                sig.ret().walk(f);
+            Ty::FnDef { substs, .. } => {
                 for t in substs.0.iter() {
                     t.walk(f);
                 }
@@ -232,8 +226,7 @@ impl Ty {
             Ty::FnPtr(sig) => {
                 sig.walk_mut(f);
             }
-            Ty::FnDef { substs, sig, .. } => {
-                sig.walk_mut(f);
+            Ty::FnDef { substs, .. } => {
                 substs.walk_mut(f);
             }
             Ty::Adt { substs, .. } => {
@@ -275,7 +268,7 @@ impl Ty {
     pub fn apply_substs(self, substs: Substs) -> Ty {
         match self {
             Ty::Adt { def_id, .. } => Ty::Adt { def_id, substs },
-            Ty::FnDef { def, sig, .. } => Ty::FnDef { def, sig, substs },
+            Ty::FnDef { def, .. } => Ty::FnDef { def, substs },
             _ => self,
         }
     }
@@ -344,7 +337,8 @@ impl HirDisplay for Ty {
                 f.write_joined(sig.params(), ", ")?;
                 write!(f, ") -> {}", sig.ret().display(f.db))?;
             }
-            Ty::FnDef { def, substs, sig, .. } => {
+            Ty::FnDef { def, substs, .. } => {
+                let sig = f.db.callable_item_signature(*def);
                 let name = match def {
                     CallableDef::Function(ff) => ff.name(f.db),
                     CallableDef::Struct(s) => s.name(f.db).unwrap_or_else(Name::missing),
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index 2eb73726e77..c9a5bc7a100 100644
--- a/crates/ra_hir/src/ty/infer.rs
+++ b/crates/ra_hir/src/ty/infer.rs
@@ -725,7 +725,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
                 let callee_ty = self.infer_expr(*callee, &Expectation::none());
                 let (param_tys, ret_ty) = match &callee_ty {
                     Ty::FnPtr(sig) => (sig.params().to_vec(), sig.ret().clone()),
-                    Ty::FnDef { substs, sig, .. } => {
+                    Ty::FnDef { substs, def, .. } => {
+                        let sig = self.db.callable_item_signature(*def);
                         let ret_ty = sig.ret().clone().subst(&substs);
                         let param_tys =
                             sig.params().iter().map(|ty| ty.clone().subst(&substs)).collect();
@@ -768,7 +769,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
                             (Ty::Unknown, Vec::new(), sig.ret().clone())
                         }
                     }
-                    Ty::FnDef { substs, sig, .. } => {
+                    Ty::FnDef { substs, def, .. } => {
+                        let sig = self.db.callable_item_signature(*def);
                         let ret_ty = sig.ret().clone().subst(&substs);
 
                         if !sig.params().is_empty() {
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs
index 7d065203afd..278f592d391 100644
--- a/crates/ra_hir/src/ty/lower.rs
+++ b/crates/ra_hir/src/ty/lower.rs
@@ -212,6 +212,15 @@ pub(crate) fn type_for_def(db: &impl HirDatabase, def: TypableDef, ns: Namespace
     }
 }
 
+/// Build the signature of a callable item (function, struct or enum variant).
+pub(crate) fn callable_item_sig(db: &impl HirDatabase, def: CallableDef) -> FnSig {
+    match def {
+        CallableDef::Function(f) => fn_sig_for_fn(db, f),
+        CallableDef::Struct(s) => fn_sig_for_struct_constructor(db, s),
+        CallableDef::EnumVariant(e) => fn_sig_for_enum_variant_constructor(db, e),
+    }
+}
+
 /// Build the type of a specific field of a struct or enum variant.
 pub(crate) fn type_for_field(db: &impl HirDatabase, field: StructField) -> Ty {
     let parent_def = field.parent_def(db);
@@ -236,10 +245,9 @@ fn fn_sig_for_fn(db: &impl HirDatabase, def: Function) -> FnSig {
 /// Build the declared type of a function. This should not need to look at the
 /// function body.
 fn type_for_fn(db: &impl HirDatabase, def: Function) -> Ty {
-    let sig = fn_sig_for_fn(db, def);
     let generics = def.generic_params(db);
     let substs = make_substs(&generics);
-    Ty::FnDef { def: def.into(), sig, substs }
+    Ty::FnDef { def: def.into(), substs }
 }
 
 /// Build the declared type of a const.
@@ -279,10 +287,9 @@ fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty {
     if var_data.fields().is_none() {
         return type_for_struct(db, def); // Unit struct
     }
-    let sig = fn_sig_for_struct_constructor(db, def);
     let generics = def.generic_params(db);
     let substs = make_substs(&generics);
-    Ty::FnDef { def: def.into(), sig, substs }
+    Ty::FnDef { def: def.into(), substs }
 }
 
 fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> FnSig {
@@ -308,10 +315,9 @@ fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) ->
     if var_data.fields().is_none() {
         return type_for_enum(db, def.parent_enum(db)); // Unit variant
     }
-    let sig = fn_sig_for_enum_variant_constructor(db, def);
     let generics = def.parent_enum(db).generic_params(db);
     let substs = make_substs(&generics);
-    Ty::FnDef { def: def.into(), sig, substs }
+    Ty::FnDef { def: def.into(), substs }
 }
 
 fn make_substs(generics: &GenericParams) -> Substs {