diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index 8833750c846..0295eb94860 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -865,6 +865,10 @@ impl GenericParam {
         let params = db.generic_params(self.id.parent);
         params.params[self.id.local_id].name.clone()
     }
+
+    pub fn module(self, db: &impl HirDatabase) -> Module {
+        self.id.parent.module(db).into()
+    }
 }
 
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs
index 437f800c1e1..686ab1d79f6 100644
--- a/crates/ra_hir/src/from_source.rs
+++ b/crates/ra_hir/src/from_source.rs
@@ -1,7 +1,7 @@
 //! FIXME: write short doc here
 use hir_def::{
     child_by_source::ChildBySource, dyn_map::DynMap, keys, nameres::ModuleSource, AstItemDef,
-    EnumVariantId, LocationCtx, ModuleId, VariantId,
+    EnumVariantId, GenericDefId, LocationCtx, ModuleId, VariantId,
 };
 use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind};
 use ra_syntax::{
@@ -11,8 +11,8 @@ use ra_syntax::{
 
 use crate::{
     db::{AstDatabase, DefDatabase, HirDatabase},
-    Const, DefWithBody, Enum, EnumVariant, FieldSource, Function, ImplBlock, InFile, Local,
-    MacroDef, Module, Static, Struct, StructField, Trait, TypeAlias, Union,
+    Const, DefWithBody, Enum, EnumVariant, FieldSource, Function, GenericParam, ImplBlock, InFile,
+    Local, MacroDef, Module, Static, Struct, StructField, Trait, TypeAlias, Union,
 };
 
 pub trait FromSource: Sized {
@@ -177,6 +177,23 @@ impl Local {
     }
 }
 
+impl GenericParam {
+    pub fn from_source(db: &impl HirDatabase, src: InFile<ast::TypeParam>) -> Option<Self> {
+        let file_id = src.file_id;
+        let parent: GenericDefId = src.value.syntax().ancestors().find_map(|it| {
+            let res = match_ast! {
+                match it {
+                    ast::FnDef(value) => { Function::from_source(db, InFile { value, file_id})?.id.into() },
+                    _ => return None,
+                }
+            };
+            Some(res)
+        })?;
+        let &id = parent.child_by_source(db)[keys::TYPE_PARAM].get(&src)?;
+        Some(GenericParam { id })
+    }
+}
+
 impl Module {
     pub fn from_declaration(db: &impl DefDatabase, src: InFile<ast::Module>) -> Option<Self> {
         let parent_declaration = src.value.syntax().ancestors().skip(1).find_map(ast::Module::cast);
diff --git a/crates/ra_hir_def/src/generics.rs b/crates/ra_hir_def/src/generics.rs
index 0df5a20f566..159f9034bc6 100644
--- a/crates/ra_hir_def/src/generics.rs
+++ b/crates/ra_hir_def/src/generics.rs
@@ -14,11 +14,14 @@ use ra_db::FileId;
 use ra_syntax::ast::{self, NameOwner, TypeBoundsOwner, TypeParamsOwner};
 
 use crate::{
+    child_by_source::ChildBySource,
     db::DefDatabase,
+    dyn_map::DynMap,
+    keys,
     src::HasChildSource,
     src::HasSource,
     type_ref::{TypeBound, TypeRef},
-    AdtId, AstItemDef, GenericDefId, LocalGenericParamId, Lookup,
+    AdtId, AstItemDef, GenericDefId, GenericParamId, LocalGenericParamId, Lookup,
 };
 
 /// Data about a generic parameter (to a function, struct, impl, ...).
@@ -183,3 +186,18 @@ impl HasChildSource for GenericDefId {
         sm
     }
 }
+
+impl ChildBySource for GenericDefId {
+    fn child_by_source(&self, db: &impl DefDatabase) -> DynMap {
+        let mut res = DynMap::default();
+        let arena_map = self.child_source(db);
+        let arena_map = arena_map.as_ref();
+        for (local_id, src) in arena_map.value.iter() {
+            let id = GenericParamId { parent: *self, local_id };
+            if let Either::Right(type_param) = src {
+                res[keys::TYPE_PARAM].insert(arena_map.with_value(type_param.clone()), id)
+            }
+        }
+        res
+    }
+}
diff --git a/crates/ra_hir_def/src/keys.rs b/crates/ra_hir_def/src/keys.rs
index 447b7e3baa2..ca5630c8018 100644
--- a/crates/ra_hir_def/src/keys.rs
+++ b/crates/ra_hir_def/src/keys.rs
@@ -8,7 +8,7 @@ use rustc_hash::FxHashMap;
 
 use crate::{
     dyn_map::{DynMap, Policy},
-    ConstId, EnumVariantId, FunctionId, StaticId, StructFieldId, TypeAliasId,
+    ConstId, EnumVariantId, FunctionId, GenericParamId, StaticId, StructFieldId, TypeAliasId,
 };
 
 type Key<K, V> = crate::dyn_map::Key<InFile<K>, V, AstPtrPolicy<K, V>>;
@@ -20,6 +20,7 @@ pub const ENUM_VARIANT: Key<ast::EnumVariant, EnumVariantId> = Key::new();
 pub const TYPE_ALIAS: Key<ast::TypeAliasDef, TypeAliasId> = Key::new();
 pub const TUPLE_FIELD: Key<ast::TupleFieldDef, StructFieldId> = Key::new();
 pub const RECORD_FIELD: Key<ast::RecordFieldDef, StructFieldId> = Key::new();
+pub const TYPE_PARAM: Key<ast::TypeParam, GenericParamId> = Key::new();
 
 /// XXX: AST Nodes and SyntaxNodes have identity equality semantics: nodes are
 /// equal if they point to exactly the same object.
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs
index b8dfc0ab1a9..6dfb3c03d01 100644
--- a/crates/ra_hir_def/src/lib.rs
+++ b/crates/ra_hir_def/src/lib.rs
@@ -525,6 +525,20 @@ impl HasModule for DefWithBodyId {
     }
 }
 
+impl HasModule for GenericDefId {
+    fn module(&self, db: &impl db::DefDatabase) -> ModuleId {
+        match self {
+            GenericDefId::FunctionId(it) => it.lookup(db).module(db),
+            GenericDefId::AdtId(it) => it.module(db),
+            GenericDefId::TraitId(it) => it.module(db),
+            GenericDefId::TypeAliasId(it) => it.lookup(db).module(db),
+            GenericDefId::ImplId(it) => it.module(db),
+            GenericDefId::EnumVariantId(it) => it.parent.module(db),
+            GenericDefId::ConstId(it) => it.lookup(db).module(db),
+        }
+    }
+}
+
 impl HasModule for StaticLoc {
     fn module(&self, _db: &impl db::DefDatabase) -> ModuleId {
         self.container
diff --git a/crates/ra_ide/src/references/classify.rs b/crates/ra_ide/src/references/classify.rs
index b716d32e597..65df2e33523 100644
--- a/crates/ra_ide/src/references/classify.rs
+++ b/crates/ra_ide/src/references/classify.rs
@@ -110,6 +110,15 @@ pub(crate) fn classify_name(db: &RootDatabase, name: InFile<&ast::Name>) -> Opti
                     kind: NameKind::Macro(def),
                 })
             },
+            ast::TypeParam(it) => {
+                let src = name.with_value(it);
+                let def = hir::GenericParam::from_source(db, src)?;
+                Some(NameDefinition {
+                    visibility: None,
+                    container: def.module(db),
+                    kind: NameKind::GenericParam(def),
+                })
+            },
             _ => None,
         }
     }