diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index 1a9f6cc768b..ffd5278ecb6 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -26,8 +26,8 @@ use hir_ty::{
     autoderef,
     display::{HirDisplayError, HirFormatter},
     expr::ExprValidator,
-    method_resolution, ApplicationTy, Canonical, InEnvironment, Substs, TraitEnvironment, Ty,
-    TyDefId, TypeCtor,
+    method_resolution, ApplicationTy, Canonical, GenericPredicate, InEnvironment, Substs,
+    TraitEnvironment, Ty, TyDefId, TypeCtor,
 };
 use ra_db::{CrateId, CrateName, Edition, FileId};
 use ra_prof::profile;
@@ -186,6 +186,22 @@ impl ModuleDef {
 
         module.visibility_of(db, self)
     }
+
+    pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
+        match self {
+            ModuleDef::Adt(it) => Some(it.name(db)),
+            ModuleDef::Trait(it) => Some(it.name(db)),
+            ModuleDef::Function(it) => Some(it.name(db)),
+            ModuleDef::EnumVariant(it) => Some(it.name(db)),
+            ModuleDef::TypeAlias(it) => Some(it.name(db)),
+
+            ModuleDef::Module(it) => it.name(db),
+            ModuleDef::Const(it) => it.name(db),
+            ModuleDef::Static(it) => it.name(db),
+
+            ModuleDef::BuiltinType(it) => Some(it.as_name()),
+        }
+    }
 }
 
 pub use hir_def::{
@@ -1359,6 +1375,27 @@ impl Type {
         Some(adt.into())
     }
 
+    pub fn as_dyn_trait(&self) -> Option<Trait> {
+        self.ty.value.dyn_trait().map(Into::into)
+    }
+
+    pub fn as_impl_traits(&self, db: &dyn HirDatabase) -> Option<Vec<Trait>> {
+        self.ty.value.impl_trait_bounds(db).map(|it| {
+            it.into_iter()
+                .filter_map(|pred| match pred {
+                    hir_ty::GenericPredicate::Implemented(trait_ref) => {
+                        Some(Trait::from(trait_ref.trait_))
+                    }
+                    _ => None,
+                })
+                .collect()
+        })
+    }
+
+    pub fn as_associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<Trait> {
+        self.ty.value.associated_type_parent_trait(db).map(Into::into)
+    }
+
     // FIXME: provide required accessors such that it becomes implementable from outside.
     pub fn is_equal_for_find_impls(&self, other: &Type) -> bool {
         match (&self.ty.value, &other.ty.value) {
@@ -1380,6 +1417,80 @@ impl Type {
             ty: InEnvironment { value: ty, environment: self.ty.environment.clone() },
         }
     }
+
+    pub fn walk(&self, db: &dyn HirDatabase, mut cb: impl FnMut(Type)) {
+        // TypeWalk::walk for a Ty at first visits parameters and only after that the Ty itself.
+        // We need a different order here.
+
+        fn walk_substs(
+            db: &dyn HirDatabase,
+            type_: &Type,
+            substs: &Substs,
+            cb: &mut impl FnMut(Type),
+        ) {
+            for ty in substs.iter() {
+                walk_type(db, &type_.derived(ty.clone()), cb);
+            }
+        }
+
+        fn walk_bounds(
+            db: &dyn HirDatabase,
+            type_: &Type,
+            bounds: &[GenericPredicate],
+            cb: &mut impl FnMut(Type),
+        ) {
+            for pred in bounds {
+                match pred {
+                    GenericPredicate::Implemented(trait_ref) => {
+                        cb(type_.clone());
+                        walk_substs(db, type_, &trait_ref.substs, cb);
+                    }
+                    _ => (),
+                }
+            }
+        }
+
+        fn walk_type(db: &dyn HirDatabase, type_: &Type, cb: &mut impl FnMut(Type)) {
+            let ty = type_.ty.value.strip_references();
+            match ty {
+                Ty::Apply(ApplicationTy { ctor, parameters }) => {
+                    match ctor {
+                        TypeCtor::Adt(_) => {
+                            cb(type_.derived(ty.clone()));
+                        }
+                        TypeCtor::AssociatedType(_) => {
+                            if let Some(_) = ty.associated_type_parent_trait(db) {
+                                cb(type_.derived(ty.clone()));
+                            }
+                        }
+                        _ => (),
+                    }
+
+                    // adt params, tuples, etc...
+                    walk_substs(db, type_, parameters, cb);
+                }
+                Ty::Opaque(opaque_ty) => {
+                    if let Some(bounds) = ty.impl_trait_bounds(db) {
+                        walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb);
+                    }
+
+                    walk_substs(db, type_, &opaque_ty.parameters, cb);
+                }
+                Ty::Placeholder(_) => {
+                    if let Some(bounds) = ty.impl_trait_bounds(db) {
+                        walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb);
+                    }
+                }
+                Ty::Dyn(bounds) => {
+                    walk_bounds(db, &type_.derived(ty.clone()), bounds.as_ref(), cb);
+                }
+
+                _ => (),
+            }
+        }
+
+        walk_type(db, self, &mut cb);
+    }
 }
 
 impl HirDisplay for Type {
diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs
index 2b9372b4b1b..f2223232492 100644
--- a/crates/ra_hir_ty/src/lib.rs
+++ b/crates/ra_hir_ty/src/lib.rs
@@ -73,6 +73,7 @@ pub use lower::{
 pub use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment};
 
 pub use chalk_ir::{BoundVar, DebruijnIndex};
+use itertools::Itertools;
 
 /// A type constructor or type name: this might be something like the primitive
 /// type `bool`, a struct like `Vec`, or things like function pointers or
@@ -815,6 +816,11 @@ impl Ty {
         }
     }
 
+    /// If this is a `dyn Trait`, returns that trait.
+    pub fn dyn_trait(&self) -> Option<TraitId> {
+        self.dyn_trait_ref().map(|it| it.trait_)
+    }
+
     fn builtin_deref(&self) -> Option<Ty> {
         match self {
             Ty::Apply(a_ty) => match a_ty.ctor {
@@ -867,13 +873,56 @@ impl Ty {
         }
     }
 
-    /// If this is a `dyn Trait`, returns that trait.
-    pub fn dyn_trait(&self) -> Option<TraitId> {
+    pub fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<GenericPredicate>> {
         match self {
-            Ty::Dyn(predicates) => predicates.iter().find_map(|pred| match pred {
-                GenericPredicate::Implemented(tr) => Some(tr.trait_),
-                _ => None,
-            }),
+            Ty::Opaque(opaque_ty) => {
+                let predicates = match opaque_ty.opaque_ty_id {
+                    OpaqueTyId::ReturnTypeImplTrait(func, idx) => {
+                        db.return_type_impl_traits(func).map(|it| {
+                            let data = (*it)
+                                .as_ref()
+                                .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
+                            data.clone().subst(&opaque_ty.parameters)
+                        })
+                    }
+                };
+
+                predicates.map(|it| it.value)
+            }
+            Ty::Placeholder(id) => {
+                let generic_params = db.generic_params(id.parent);
+                let param_data = &generic_params.types[id.local_id];
+                match param_data.provenance {
+                    hir_def::generics::TypeParamProvenance::ArgumentImplTrait => {
+                        let predicates = db
+                            .generic_predicates_for_param(*id)
+                            .into_iter()
+                            .map(|pred| pred.value.clone())
+                            .collect_vec();
+
+                        Some(predicates)
+                    }
+                    _ => None,
+                }
+            }
+            _ => None,
+        }
+    }
+
+    pub fn associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<TraitId> {
+        match self {
+            Ty::Apply(ApplicationTy { ctor: TypeCtor::AssociatedType(type_alias_id), .. }) => {
+                match type_alias_id.lookup(db.upcast()).container {
+                    AssocContainerId::TraitId(trait_id) => Some(trait_id),
+                    _ => None,
+                }
+            }
+            Ty::Projection(projection_ty) => {
+                match projection_ty.associated_ty.lookup(db.upcast()).container {
+                    AssocContainerId::TraitId(trait_id) => Some(trait_id),
+                    _ => None,
+                }
+            }
             _ => None,
         }
     }
@@ -1057,5 +1106,5 @@ pub struct ReturnTypeImplTraits {
 
 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
 pub(crate) struct ReturnTypeImplTrait {
-    pub(crate) bounds: Binders<Vec<GenericPredicate>>,
+    pub bounds: Binders<Vec<GenericPredicate>>,
 }
diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs
index ad78b767120..d870e4cbce6 100644
--- a/crates/ra_ide/src/hover.rs
+++ b/crates/ra_ide/src/hover.rs
@@ -2,7 +2,7 @@ use std::iter::once;
 
 use hir::{
     Adt, AsAssocItem, AssocItemContainer, Documentation, FieldSource, HasSource, HirDisplay,
-    ModuleDef, ModuleSource, Semantics,
+    Module, ModuleDef, ModuleSource, Semantics,
 };
 use itertools::Itertools;
 use ra_db::SourceDatabase;
@@ -13,7 +13,9 @@ use ra_ide_db::{
 use ra_syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset};
 
 use crate::{
-    display::{macro_label, rust_code_markup, rust_code_markup_with_doc, ShortLabel, ToNav},
+    display::{
+        macro_label, rust_code_markup, rust_code_markup_with_doc, ShortLabel, ToNav, TryToNav,
+    },
     runnables::runnable,
     FileId, FilePosition, NavigationTarget, RangeInfo, Runnable,
 };
@@ -24,19 +26,21 @@ pub struct HoverConfig {
     pub implementations: bool,
     pub run: bool,
     pub debug: bool,
+    pub goto_type_def: bool,
 }
 
 impl Default for HoverConfig {
     fn default() -> Self {
-        Self { implementations: true, run: true, debug: true }
+        Self { implementations: true, run: true, debug: true, goto_type_def: true }
     }
 }
 
 impl HoverConfig {
-    pub const NO_ACTIONS: Self = Self { implementations: false, run: false, debug: false };
+    pub const NO_ACTIONS: Self =
+        Self { implementations: false, run: false, debug: false, goto_type_def: false };
 
     pub fn any(&self) -> bool {
-        self.implementations || self.runnable()
+        self.implementations || self.runnable() || self.goto_type_def
     }
 
     pub fn none(&self) -> bool {
@@ -52,6 +56,13 @@ impl HoverConfig {
 pub enum HoverAction {
     Runnable(Runnable),
     Implementaion(FilePosition),
+    GoToType(Vec<HoverGotoTypeData>),
+}
+
+#[derive(Debug, Clone, Eq, PartialEq)]
+pub struct HoverGotoTypeData {
+    pub mod_path: String,
+    pub nav: NavigationTarget,
 }
 
 /// Contains the results when hovering over an item
@@ -138,6 +149,10 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
                 res.push_action(action);
             }
 
+            if let Some(action) = goto_type_action(db, name_kind) {
+                res.push_action(action);
+            }
+
             return Some(RangeInfo::new(range, res));
         }
     }
@@ -218,6 +233,44 @@ fn runnable_action(
     }
 }
 
+fn goto_type_action(db: &RootDatabase, def: Definition) -> Option<HoverAction> {
+    match def {
+        Definition::Local(it) => {
+            let mut targets: Vec<ModuleDef> = Vec::new();
+            let mut push_new_def = |item: ModuleDef| {
+                if !targets.contains(&item) {
+                    targets.push(item);
+                }
+            };
+
+            it.ty(db).walk(db, |t| {
+                if let Some(adt) = t.as_adt() {
+                    push_new_def(adt.into());
+                } else if let Some(trait_) = t.as_dyn_trait() {
+                    push_new_def(trait_.into());
+                } else if let Some(traits) = t.as_impl_traits(db) {
+                    traits.into_iter().for_each(|it| push_new_def(it.into()));
+                } else if let Some(trait_) = t.as_associated_type_parent_trait(db) {
+                    push_new_def(trait_.into());
+                }
+            });
+
+            let targets = targets
+                .into_iter()
+                .filter_map(|it| {
+                    Some(HoverGotoTypeData {
+                        mod_path: mod_path(db, &it)?,
+                        nav: it.try_to_nav(db)?,
+                    })
+                })
+                .collect();
+
+            Some(HoverAction::GoToType(targets))
+        }
+        _ => None,
+    }
+}
+
 fn hover_text(
     docs: Option<String>,
     desc: Option<String>,
@@ -248,25 +301,31 @@ fn definition_owner_name(db: &RootDatabase, def: &Definition) -> Option<String>
     .map(|name| name.to_string())
 }
 
-fn determine_mod_path(db: &RootDatabase, def: &Definition) -> Option<String> {
-    let mod_path = def.module(db).map(|module| {
-        once(db.crate_graph()[module.krate().into()].display_name.as_ref().map(ToString::to_string))
-            .chain(
-                module
-                    .path_to_root(db)
-                    .into_iter()
-                    .rev()
-                    .map(|it| it.name(db).map(|name| name.to_string())),
-            )
-            .chain(once(definition_owner_name(db, def)))
-            .flatten()
-            .join("::")
-    });
-    mod_path
+fn determine_mod_path(db: &RootDatabase, module: Module, name: Option<String>) -> String {
+    once(db.crate_graph()[module.krate().into()].display_name.as_ref().map(ToString::to_string))
+        .chain(
+            module
+                .path_to_root(db)
+                .into_iter()
+                .rev()
+                .map(|it| it.name(db).map(|name| name.to_string())),
+        )
+        .chain(once(name))
+        .flatten()
+        .join("::")
+}
+
+// returns None only for ModuleDef::BuiltinType
+fn mod_path(db: &RootDatabase, item: &ModuleDef) -> Option<String> {
+    Some(determine_mod_path(db, item.module(db)?, item.name(db).map(|name| name.to_string())))
+}
+
+fn definition_mod_path(db: &RootDatabase, def: &Definition) -> Option<String> {
+    def.module(db).map(|module| determine_mod_path(db, module, definition_owner_name(db, def)))
 }
 
 fn hover_text_from_name_kind(db: &RootDatabase, def: Definition) -> Option<String> {
-    let mod_path = determine_mod_path(db, &def);
+    let mod_path = definition_mod_path(db, &def);
     return match def {
         Definition::Macro(it) => {
             let src = it.source(db);
@@ -1310,4 +1369,1045 @@ fn func(foo: i32) { if true { <|>foo; }; }
             ]
             "###);
     }
+
+    #[test]
+    fn test_hover_struct_has_goto_type_action() {
+        let (_, actions) = check_hover_result(
+            "
+            //- /main.rs
+            struct S{ f1: u32 }
+
+            fn main() {
+                let s<|>t = S{ f1:0 };
+            }
+            ",
+            &["S"],
+        );
+        assert_debug_snapshot!(actions,
+            @r###"
+            [
+                GoToType(
+                    [
+                        HoverGotoTypeData {
+                            mod_path: "S",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    1,
+                                ),
+                                full_range: 0..19,
+                                name: "S",
+                                kind: STRUCT_DEF,
+                                focus_range: Some(
+                                    7..8,
+                                ),
+                                container_name: None,
+                                description: Some(
+                                    "struct S",
+                                ),
+                                docs: None,
+                            },
+                        },
+                    ],
+                ),
+            ]
+            "###);
+    }
+
+    #[test]
+    fn test_hover_generic_struct_has_goto_type_actions() {
+        let (_, actions) = check_hover_result(
+            "
+            //- /main.rs
+            struct Arg(u32);
+            struct S<T>{ f1: T }
+
+            fn main() {
+                let s<|>t = S{ f1:Arg(0) };
+            }
+            ",
+            &["S<Arg>"],
+        );
+        assert_debug_snapshot!(actions,
+            @r###"
+            [
+                GoToType(
+                    [
+                        HoverGotoTypeData {
+                            mod_path: "S",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    1,
+                                ),
+                                full_range: 17..37,
+                                name: "S",
+                                kind: STRUCT_DEF,
+                                focus_range: Some(
+                                    24..25,
+                                ),
+                                container_name: None,
+                                description: Some(
+                                    "struct S",
+                                ),
+                                docs: None,
+                            },
+                        },
+                        HoverGotoTypeData {
+                            mod_path: "Arg",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    1,
+                                ),
+                                full_range: 0..16,
+                                name: "Arg",
+                                kind: STRUCT_DEF,
+                                focus_range: Some(
+                                    7..10,
+                                ),
+                                container_name: None,
+                                description: Some(
+                                    "struct Arg",
+                                ),
+                                docs: None,
+                            },
+                        },
+                    ],
+                ),
+            ]
+            "###);
+    }
+
+    #[test]
+    fn test_hover_generic_struct_has_flattened_goto_type_actions() {
+        let (_, actions) = check_hover_result(
+            "
+            //- /main.rs
+            struct Arg(u32);
+            struct S<T>{ f1: T }
+
+            fn main() {
+                let s<|>t = S{ f1: S{ f1: Arg(0) } };
+            }
+            ",
+            &["S<S<Arg>>"],
+        );
+        assert_debug_snapshot!(actions,
+            @r###"
+            [
+                GoToType(
+                    [
+                        HoverGotoTypeData {
+                            mod_path: "S",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    1,
+                                ),
+                                full_range: 17..37,
+                                name: "S",
+                                kind: STRUCT_DEF,
+                                focus_range: Some(
+                                    24..25,
+                                ),
+                                container_name: None,
+                                description: Some(
+                                    "struct S",
+                                ),
+                                docs: None,
+                            },
+                        },
+                        HoverGotoTypeData {
+                            mod_path: "Arg",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    1,
+                                ),
+                                full_range: 0..16,
+                                name: "Arg",
+                                kind: STRUCT_DEF,
+                                focus_range: Some(
+                                    7..10,
+                                ),
+                                container_name: None,
+                                description: Some(
+                                    "struct Arg",
+                                ),
+                                docs: None,
+                            },
+                        },
+                    ],
+                ),
+            ]
+            "###);
+    }
+
+    #[test]
+    fn test_hover_tuple_has_goto_type_actions() {
+        let (_, actions) = check_hover_result(
+            "
+            //- /main.rs
+            struct A(u32);
+            struct B(u32);
+            mod M {
+                pub struct C(u32);
+            }
+
+            fn main() {
+                let s<|>t = (A(1), B(2), M::C(3) );
+            }
+            ",
+            &["(A, B, C)"],
+        );
+        assert_debug_snapshot!(actions,
+            @r###"
+            [
+                GoToType(
+                    [
+                        HoverGotoTypeData {
+                            mod_path: "A",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    1,
+                                ),
+                                full_range: 0..14,
+                                name: "A",
+                                kind: STRUCT_DEF,
+                                focus_range: Some(
+                                    7..8,
+                                ),
+                                container_name: None,
+                                description: Some(
+                                    "struct A",
+                                ),
+                                docs: None,
+                            },
+                        },
+                        HoverGotoTypeData {
+                            mod_path: "B",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    1,
+                                ),
+                                full_range: 15..29,
+                                name: "B",
+                                kind: STRUCT_DEF,
+                                focus_range: Some(
+                                    22..23,
+                                ),
+                                container_name: None,
+                                description: Some(
+                                    "struct B",
+                                ),
+                                docs: None,
+                            },
+                        },
+                        HoverGotoTypeData {
+                            mod_path: "M::C",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    1,
+                                ),
+                                full_range: 42..60,
+                                name: "C",
+                                kind: STRUCT_DEF,
+                                focus_range: Some(
+                                    53..54,
+                                ),
+                                container_name: None,
+                                description: Some(
+                                    "pub struct C",
+                                ),
+                                docs: None,
+                            },
+                        },
+                    ],
+                ),
+            ]
+               "###);
+    }
+
+    #[test]
+    fn test_hover_return_impl_trait_has_goto_type_action() {
+        let (_, actions) = check_hover_result(
+            "
+            //- /main.rs
+            trait Foo {}
+
+            fn foo() -> impl Foo {}
+
+            fn main() {
+                let s<|>t = foo();
+            }
+            ",
+            &["impl Foo"],
+        );
+        assert_debug_snapshot!(actions,
+            @r###"
+            [
+                GoToType(
+                    [
+                        HoverGotoTypeData {
+                            mod_path: "Foo",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    1,
+                                ),
+                                full_range: 0..12,
+                                name: "Foo",
+                                kind: TRAIT_DEF,
+                                focus_range: Some(
+                                    6..9,
+                                ),
+                                container_name: None,
+                                description: Some(
+                                    "trait Foo",
+                                ),
+                                docs: None,
+                            },
+                        },
+                    ],
+                ),
+            ]
+            "###);
+    }
+
+    #[test]
+    fn test_hover_generic_return_impl_trait_has_goto_type_action() {
+        let (_, actions) = check_hover_result(
+            "
+            //- /main.rs
+            trait Foo<T> {}
+            struct S;
+
+            fn foo() -> impl Foo<S> {}
+
+            fn main() {
+                let s<|>t = foo();
+            }
+            ",
+            &["impl Foo<S>"],
+        );
+        assert_debug_snapshot!(actions,
+            @r###"
+            [
+                GoToType(
+                    [
+                        HoverGotoTypeData {
+                            mod_path: "Foo",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    1,
+                                ),
+                                full_range: 0..15,
+                                name: "Foo",
+                                kind: TRAIT_DEF,
+                                focus_range: Some(
+                                    6..9,
+                                ),
+                                container_name: None,
+                                description: Some(
+                                    "trait Foo",
+                                ),
+                                docs: None,
+                            },
+                        },
+                        HoverGotoTypeData {
+                            mod_path: "S",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    1,
+                                ),
+                                full_range: 16..25,
+                                name: "S",
+                                kind: STRUCT_DEF,
+                                focus_range: Some(
+                                    23..24,
+                                ),
+                                container_name: None,
+                                description: Some(
+                                    "struct S",
+                                ),
+                                docs: None,
+                            },
+                        },
+                    ],
+                ),
+            ]
+            "###);
+    }
+
+    #[test]
+    fn test_hover_return_impl_traits_has_goto_type_action() {
+        let (_, actions) = check_hover_result(
+            "
+            //- /main.rs
+            trait Foo {}
+            trait Bar {}
+
+            fn foo() -> impl Foo + Bar {}
+
+            fn main() {
+                let s<|>t = foo();
+            }
+            ",
+            &["impl Foo + Bar"],
+        );
+        assert_debug_snapshot!(actions,
+            @r###"
+            [
+                GoToType(
+                    [
+                        HoverGotoTypeData {
+                            mod_path: "Foo",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    1,
+                                ),
+                                full_range: 0..12,
+                                name: "Foo",
+                                kind: TRAIT_DEF,
+                                focus_range: Some(
+                                    6..9,
+                                ),
+                                container_name: None,
+                                description: Some(
+                                    "trait Foo",
+                                ),
+                                docs: None,
+                            },
+                        },
+                        HoverGotoTypeData {
+                            mod_path: "Bar",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    1,
+                                ),
+                                full_range: 13..25,
+                                name: "Bar",
+                                kind: TRAIT_DEF,
+                                focus_range: Some(
+                                    19..22,
+                                ),
+                                container_name: None,
+                                description: Some(
+                                    "trait Bar",
+                                ),
+                                docs: None,
+                            },
+                        },
+                    ],
+                ),
+            ]
+            "###);
+    }
+
+    #[test]
+    fn test_hover_generic_return_impl_traits_has_goto_type_action() {
+        let (_, actions) = check_hover_result(
+            "
+            //- /main.rs
+            trait Foo<T> {}
+            trait Bar<T> {}
+            struct S1 {}
+            struct S2 {}
+
+            fn foo() -> impl Foo<S1> + Bar<S2> {}
+
+            fn main() {
+                let s<|>t = foo();
+            }
+            ",
+            &["impl Foo<S1> + Bar<S2>"],
+        );
+        assert_debug_snapshot!(actions,
+            @r###"
+            [
+                GoToType(
+                    [
+                        HoverGotoTypeData {
+                            mod_path: "Foo",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    1,
+                                ),
+                                full_range: 0..15,
+                                name: "Foo",
+                                kind: TRAIT_DEF,
+                                focus_range: Some(
+                                    6..9,
+                                ),
+                                container_name: None,
+                                description: Some(
+                                    "trait Foo",
+                                ),
+                                docs: None,
+                            },
+                        },
+                        HoverGotoTypeData {
+                            mod_path: "Bar",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    1,
+                                ),
+                                full_range: 16..31,
+                                name: "Bar",
+                                kind: TRAIT_DEF,
+                                focus_range: Some(
+                                    22..25,
+                                ),
+                                container_name: None,
+                                description: Some(
+                                    "trait Bar",
+                                ),
+                                docs: None,
+                            },
+                        },
+                        HoverGotoTypeData {
+                            mod_path: "S1",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    1,
+                                ),
+                                full_range: 32..44,
+                                name: "S1",
+                                kind: STRUCT_DEF,
+                                focus_range: Some(
+                                    39..41,
+                                ),
+                                container_name: None,
+                                description: Some(
+                                    "struct S1",
+                                ),
+                                docs: None,
+                            },
+                        },
+                        HoverGotoTypeData {
+                            mod_path: "S2",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    1,
+                                ),
+                                full_range: 45..57,
+                                name: "S2",
+                                kind: STRUCT_DEF,
+                                focus_range: Some(
+                                    52..54,
+                                ),
+                                container_name: None,
+                                description: Some(
+                                    "struct S2",
+                                ),
+                                docs: None,
+                            },
+                        },
+                    ],
+                ),
+            ]
+               "###);
+    }
+
+    #[test]
+    fn test_hover_arg_impl_trait_has_goto_type_action() {
+        let (_, actions) = check_hover_result(
+            "
+            //- /lib.rs
+            trait Foo {}
+            fn foo(ar<|>g: &impl Foo) {}
+            ",
+            &["&impl Foo"],
+        );
+        assert_debug_snapshot!(actions,
+            @r###"
+            [
+                GoToType(
+                    [
+                        HoverGotoTypeData {
+                            mod_path: "Foo",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    1,
+                                ),
+                                full_range: 0..12,
+                                name: "Foo",
+                                kind: TRAIT_DEF,
+                                focus_range: Some(
+                                    6..9,
+                                ),
+                                container_name: None,
+                                description: Some(
+                                    "trait Foo",
+                                ),
+                                docs: None,
+                            },
+                        },
+                    ],
+                ),
+            ]
+            "###);
+    }
+
+    #[test]
+    fn test_hover_arg_impl_traits_has_goto_type_action() {
+        let (_, actions) = check_hover_result(
+            "
+            //- /lib.rs
+            trait Foo {}
+            trait Bar<T> {}
+            struct S{}
+
+            fn foo(ar<|>g: &impl Foo + Bar<S>) {}
+            ",
+            &["&impl Foo + Bar<S>"],
+        );
+        assert_debug_snapshot!(actions,
+            @r###"
+            [
+                GoToType(
+                    [
+                        HoverGotoTypeData {
+                            mod_path: "Foo",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    1,
+                                ),
+                                full_range: 0..12,
+                                name: "Foo",
+                                kind: TRAIT_DEF,
+                                focus_range: Some(
+                                    6..9,
+                                ),
+                                container_name: None,
+                                description: Some(
+                                    "trait Foo",
+                                ),
+                                docs: None,
+                            },
+                        },
+                        HoverGotoTypeData {
+                            mod_path: "Bar",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    1,
+                                ),
+                                full_range: 13..28,
+                                name: "Bar",
+                                kind: TRAIT_DEF,
+                                focus_range: Some(
+                                    19..22,
+                                ),
+                                container_name: None,
+                                description: Some(
+                                    "trait Bar",
+                                ),
+                                docs: None,
+                            },
+                        },
+                        HoverGotoTypeData {
+                            mod_path: "S",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    1,
+                                ),
+                                full_range: 29..39,
+                                name: "S",
+                                kind: STRUCT_DEF,
+                                focus_range: Some(
+                                    36..37,
+                                ),
+                                container_name: None,
+                                description: Some(
+                                    "struct S",
+                                ),
+                                docs: None,
+                            },
+                        },
+                    ],
+                ),
+            ]
+            "###);
+    }
+
+    #[test]
+    fn test_hover_arg_generic_impl_trait_has_goto_type_action() {
+        let (_, actions) = check_hover_result(
+            "
+            //- /lib.rs
+            trait Foo<T> {}
+            struct S {}
+            fn foo(ar<|>g: &impl Foo<S>) {}
+            ",
+            &["&impl Foo<S>"],
+        );
+        assert_debug_snapshot!(actions,
+            @r###"
+            [
+                GoToType(
+                    [
+                        HoverGotoTypeData {
+                            mod_path: "Foo",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    1,
+                                ),
+                                full_range: 0..15,
+                                name: "Foo",
+                                kind: TRAIT_DEF,
+                                focus_range: Some(
+                                    6..9,
+                                ),
+                                container_name: None,
+                                description: Some(
+                                    "trait Foo",
+                                ),
+                                docs: None,
+                            },
+                        },
+                        HoverGotoTypeData {
+                            mod_path: "S",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    1,
+                                ),
+                                full_range: 16..27,
+                                name: "S",
+                                kind: STRUCT_DEF,
+                                focus_range: Some(
+                                    23..24,
+                                ),
+                                container_name: None,
+                                description: Some(
+                                    "struct S",
+                                ),
+                                docs: None,
+                            },
+                        },
+                    ],
+                ),
+            ]
+            "###);
+    }
+
+    #[test]
+    fn test_hover_dyn_return_has_goto_type_action() {
+        let (_, actions) = check_hover_result(
+            "
+            //- /main.rs
+            trait Foo {}
+            struct S;
+            impl Foo for S {}
+
+            struct B<T>{}
+
+            fn foo() -> B<dyn Foo> {}
+
+            fn main() {
+                let s<|>t = foo();
+            }
+            ",
+            &["B<dyn Foo>"],
+        );
+        assert_debug_snapshot!(actions,
+            @r###"
+            [
+                GoToType(
+                    [
+                        HoverGotoTypeData {
+                            mod_path: "B",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    1,
+                                ),
+                                full_range: 41..54,
+                                name: "B",
+                                kind: STRUCT_DEF,
+                                focus_range: Some(
+                                    48..49,
+                                ),
+                                container_name: None,
+                                description: Some(
+                                    "struct B",
+                                ),
+                                docs: None,
+                            },
+                        },
+                        HoverGotoTypeData {
+                            mod_path: "Foo",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    1,
+                                ),
+                                full_range: 0..12,
+                                name: "Foo",
+                                kind: TRAIT_DEF,
+                                focus_range: Some(
+                                    6..9,
+                                ),
+                                container_name: None,
+                                description: Some(
+                                    "trait Foo",
+                                ),
+                                docs: None,
+                            },
+                        },
+                    ],
+                ),
+            ]
+            "###);
+    }
+
+    #[test]
+    fn test_hover_dyn_arg_has_goto_type_action() {
+        let (_, actions) = check_hover_result(
+            "
+            //- /lib.rs
+            trait Foo {}
+            fn foo(ar<|>g: &dyn Foo) {}
+            ",
+            &["&dyn Foo"],
+        );
+        assert_debug_snapshot!(actions,
+            @r###"
+            [
+                GoToType(
+                    [
+                        HoverGotoTypeData {
+                            mod_path: "Foo",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    1,
+                                ),
+                                full_range: 0..12,
+                                name: "Foo",
+                                kind: TRAIT_DEF,
+                                focus_range: Some(
+                                    6..9,
+                                ),
+                                container_name: None,
+                                description: Some(
+                                    "trait Foo",
+                                ),
+                                docs: None,
+                            },
+                        },
+                    ],
+                ),
+            ]
+            "###);
+    }
+
+    #[test]
+    fn test_hover_generic_dyn_arg_has_goto_type_action() {
+        let (_, actions) = check_hover_result(
+            "
+            //- /lib.rs
+            trait Foo<T> {}
+            struct S {}
+            fn foo(ar<|>g: &dyn Foo<S>) {}
+            ",
+            &["&dyn Foo<S>"],
+        );
+        assert_debug_snapshot!(actions,
+            @r###"
+            [
+                GoToType(
+                    [
+                        HoverGotoTypeData {
+                            mod_path: "Foo",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    1,
+                                ),
+                                full_range: 0..15,
+                                name: "Foo",
+                                kind: TRAIT_DEF,
+                                focus_range: Some(
+                                    6..9,
+                                ),
+                                container_name: None,
+                                description: Some(
+                                    "trait Foo",
+                                ),
+                                docs: None,
+                            },
+                        },
+                        HoverGotoTypeData {
+                            mod_path: "S",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    1,
+                                ),
+                                full_range: 16..27,
+                                name: "S",
+                                kind: STRUCT_DEF,
+                                focus_range: Some(
+                                    23..24,
+                                ),
+                                container_name: None,
+                                description: Some(
+                                    "struct S",
+                                ),
+                                docs: None,
+                            },
+                        },
+                    ],
+                ),
+            ]
+            "###);
+    }
+
+    #[test]
+    fn test_hover_goto_type_action_links_order() {
+        let (_, actions) = check_hover_result(
+            "
+            //- /lib.rs
+            trait ImplTrait<T> {}
+            trait DynTrait<T> {}
+            struct B<T> {}
+            struct S {}
+
+            fn foo(a<|>rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {}
+            ",
+            &["&impl ImplTrait<B<dyn DynTrait<B<S>>>>"],
+        );
+        assert_debug_snapshot!(actions,
+            @r###"
+            [
+                GoToType(
+                    [
+                        HoverGotoTypeData {
+                            mod_path: "ImplTrait",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    1,
+                                ),
+                                full_range: 0..21,
+                                name: "ImplTrait",
+                                kind: TRAIT_DEF,
+                                focus_range: Some(
+                                    6..15,
+                                ),
+                                container_name: None,
+                                description: Some(
+                                    "trait ImplTrait",
+                                ),
+                                docs: None,
+                            },
+                        },
+                        HoverGotoTypeData {
+                            mod_path: "B",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    1,
+                                ),
+                                full_range: 43..57,
+                                name: "B",
+                                kind: STRUCT_DEF,
+                                focus_range: Some(
+                                    50..51,
+                                ),
+                                container_name: None,
+                                description: Some(
+                                    "struct B",
+                                ),
+                                docs: None,
+                            },
+                        },
+                        HoverGotoTypeData {
+                            mod_path: "DynTrait",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    1,
+                                ),
+                                full_range: 22..42,
+                                name: "DynTrait",
+                                kind: TRAIT_DEF,
+                                focus_range: Some(
+                                    28..36,
+                                ),
+                                container_name: None,
+                                description: Some(
+                                    "trait DynTrait",
+                                ),
+                                docs: None,
+                            },
+                        },
+                        HoverGotoTypeData {
+                            mod_path: "S",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    1,
+                                ),
+                                full_range: 58..69,
+                                name: "S",
+                                kind: STRUCT_DEF,
+                                focus_range: Some(
+                                    65..66,
+                                ),
+                                container_name: None,
+                                description: Some(
+                                    "struct S",
+                                ),
+                                docs: None,
+                            },
+                        },
+                    ],
+                ),
+            ]
+            "###);
+    }
+
+    #[test]
+    fn test_hover_associated_type_has_goto_type_action() {
+        let (_, actions) = check_hover_result(
+            "
+            //- /main.rs
+            trait Foo {
+                type Item;
+                fn get(self) -> Self::Item {}
+            }
+
+            struct Bar{}
+            struct S{}
+
+            impl Foo for S{
+                type Item = Bar;
+            }
+
+            fn test() -> impl Foo {
+                S{}
+            }
+
+            fn main() {
+                let s<|>t = test().get();
+            }
+            ",
+            &["Foo::Item<impl Foo>"],
+        );
+        assert_debug_snapshot!(actions,
+            @r###"
+            [
+                GoToType(
+                    [
+                        HoverGotoTypeData {
+                            mod_path: "Foo",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    1,
+                                ),
+                                full_range: 0..62,
+                                name: "Foo",
+                                kind: TRAIT_DEF,
+                                focus_range: Some(
+                                    6..9,
+                                ),
+                                container_name: None,
+                                description: Some(
+                                    "trait Foo",
+                                ),
+                                docs: None,
+                            },
+                        },
+                    ],
+                ),
+            ]
+            "###);
+    }
 }
diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs
index 51dc1f041ca..be9ab62c0bb 100644
--- a/crates/ra_ide/src/lib.rs
+++ b/crates/ra_ide/src/lib.rs
@@ -66,7 +66,7 @@ pub use crate::{
     display::{file_structure, FunctionSignature, NavigationTarget, StructureNode},
     expand_macro::ExpandedMacro,
     folding_ranges::{Fold, FoldKind},
-    hover::{HoverAction, HoverConfig, HoverResult},
+    hover::{HoverAction, HoverConfig, HoverGotoTypeData, HoverResult},
     inlay_hints::{InlayHint, InlayHintsConfig, InlayKind},
     references::{Declaration, Reference, ReferenceAccess, ReferenceKind, ReferenceSearchResult},
     runnables::{Runnable, RunnableKind, TestId},
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index 0df7427cb97..aa2c4ae15dc 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -296,6 +296,7 @@ impl Config {
             set(value, "/hoverActions/implementations", &mut self.hover.implementations);
             set(value, "/hoverActions/run", &mut self.hover.run);
             set(value, "/hoverActions/debug", &mut self.hover.debug);
+            set(value, "/hoverActions/gotoTypeDef", &mut self.hover.goto_type_def);
         } else {
             self.hover = HoverConfig::NO_ACTIONS;
         }
diff --git a/crates/rust-analyzer/src/main_loop/handlers.rs b/crates/rust-analyzer/src/main_loop/handlers.rs
index b34b529b5ca..2d7e649d2dc 100644
--- a/crates/rust-analyzer/src/main_loop/handlers.rs
+++ b/crates/rust-analyzer/src/main_loop/handlers.rs
@@ -18,8 +18,8 @@ use lsp_types::{
     TextDocumentIdentifier, Url, WorkspaceEdit,
 };
 use ra_ide::{
-    FileId, FilePosition, FileRange, HoverAction, Query, RangeInfo, Runnable, RunnableKind,
-    SearchScope, TextEdit,
+    FileId, FilePosition, FileRange, HoverAction, HoverGotoTypeData, NavigationTarget, Query,
+    RangeInfo, Runnable, RunnableKind, SearchScope, TextEdit,
 };
 use ra_prof::profile;
 use ra_project_model::TargetKind;
@@ -1150,6 +1150,23 @@ fn debug_single_command(runnable: &lsp_ext::Runnable) -> Command {
     }
 }
 
+fn goto_location_command(snap: &GlobalStateSnapshot, nav: &NavigationTarget) -> Option<Command> {
+    let value = if snap.config.client_caps.location_link {
+        let link = to_proto::location_link(snap, None, nav.clone()).ok()?;
+        to_value(link).ok()?
+    } else {
+        let range = FileRange { file_id: nav.file_id(), range: nav.range() };
+        let location = to_proto::location(snap, range).ok()?;
+        to_value(location).ok()?
+    };
+
+    Some(Command {
+        title: nav.name().to_string(),
+        command: "rust-analyzer.gotoLocation".into(),
+        arguments: Some(vec![value]),
+    })
+}
+
 fn to_command_link(command: Command, tooltip: String) -> lsp_ext::CommandLink {
     lsp_ext::CommandLink { tooltip: Some(tooltip), command }
 }
@@ -1180,13 +1197,13 @@ fn show_impl_command_link(
     None
 }
 
-fn to_runnable_action(
+fn runnable_action_links(
     snap: &GlobalStateSnapshot,
     file_id: FileId,
     runnable: Runnable,
 ) -> Option<lsp_ext::CommandLinkGroup> {
     let cargo_spec = CargoTargetSpec::for_file(&snap, file_id).ok()?;
-    if should_skip_target(&runnable, cargo_spec.as_ref()) {
+    if !snap.config.hover.runnable() || should_skip_target(&runnable, cargo_spec.as_ref()) {
         return None;
     }
 
@@ -1208,6 +1225,26 @@ fn to_runnable_action(
     })
 }
 
+fn goto_type_action_links(
+    snap: &GlobalStateSnapshot,
+    nav_targets: &[HoverGotoTypeData],
+) -> Option<lsp_ext::CommandLinkGroup> {
+    if !snap.config.hover.goto_type_def || nav_targets.is_empty() {
+        return None;
+    }
+
+    Some(lsp_ext::CommandLinkGroup {
+        title: Some("Go to ".into()),
+        commands: nav_targets
+            .iter()
+            .filter_map(|it| {
+                goto_location_command(snap, &it.nav)
+                    .map(|cmd| to_command_link(cmd, it.mod_path.clone()))
+            })
+            .collect(),
+    })
+}
+
 fn prepare_hover_actions(
     snap: &GlobalStateSnapshot,
     file_id: FileId,
@@ -1221,7 +1258,8 @@ fn prepare_hover_actions(
         .iter()
         .filter_map(|it| match it {
             HoverAction::Implementaion(position) => show_impl_command_link(snap, position),
-            HoverAction::Runnable(r) => to_runnable_action(snap, file_id, r.clone()),
+            HoverAction::Runnable(r) => runnable_action_links(snap, file_id, r.clone()),
+            HoverAction::GoToType(targets) => goto_type_action_links(snap, targets),
         })
         .collect()
 }
diff --git a/editors/code/package.json b/editors/code/package.json
index 3acc375f672..e6ceb235fcf 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -510,6 +510,11 @@
                     "type": "boolean",
                     "default": true
                 },
+                "rust-analyzer.hoverActions.gotoTypeDef": {
+                    "markdownDescription": "Whether to show `Go to Type Definition` action. Only applies when `#rust-analyzer.hoverActions.enable#` is set.",
+                    "type": "boolean",
+                    "default": true
+                },
                 "rust-analyzer.linkedProjects": {
                     "markdownDescription": "Disable project auto-discovery in favor of explicitly specified set of projects.  \nElements must be paths pointing to Cargo.toml, rust-project.json, or JSON objects in rust-project.json format",
                     "type": "array",
diff --git a/editors/code/src/commands.ts b/editors/code/src/commands.ts
index 3e9c3aa0e59..48a25495fb9 100644
--- a/editors/code/src/commands.ts
+++ b/editors/code/src/commands.ts
@@ -353,6 +353,20 @@ export function applyActionGroup(_ctx: Ctx): Cmd {
     };
 }
 
+export function gotoLocation(ctx: Ctx): Cmd {
+    return async (locationLink: lc.LocationLink) => {
+        const client = ctx.client;
+        if (client) {
+            const uri = client.protocol2CodeConverter.asUri(locationLink.targetUri);
+            let range = client.protocol2CodeConverter.asRange(locationLink.targetSelectionRange);
+            // collapse the range to a cursor position
+            range = range.with({ end: range.start });
+
+            await vscode.window.showTextDocument(uri, { selection: range });
+        }
+    };
+}
+
 export function resolveCodeAction(ctx: Ctx): Cmd {
     const client = ctx.client;
     return async (params: ra.ResolveCodeActionParams) => {
diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts
index d8f0037d4c9..9591d4fe32c 100644
--- a/editors/code/src/config.ts
+++ b/editors/code/src/config.ts
@@ -117,7 +117,7 @@ export class Config {
         return {
             engine: this.get<string>("debug.engine"),
             engineSettings: this.get<object>("debug.engineSettings"),
-            openUpDebugPane: this.get<boolean>("debug.openUpDebugPane"),
+            openDebugPane: this.get<boolean>("debug.openDebugPane"),
             sourceFileMap: sourceFileMap
         };
     }
@@ -135,6 +135,9 @@ export class Config {
         return {
             enable: this.get<boolean>("hoverActions.enable"),
             implementations: this.get<boolean>("hoverActions.implementations"),
+            run: this.get<boolean>("hoverActions.run"),
+            debug: this.get<boolean>("hoverActions.debug"),
+            gotoTypeDef: this.get<boolean>("hoverActions.gotoTypeDef"),
         };
     }
 }
diff --git a/editors/code/src/debug.ts b/editors/code/src/debug.ts
index a0c9b3ab2e6..61c12dbe074 100644
--- a/editors/code/src/debug.ts
+++ b/editors/code/src/debug.ts
@@ -82,7 +82,7 @@ async function getDebugConfiguration(ctx: Ctx, runnable: ra.Runnable): Promise<v
     }
 
     debugOutput.clear();
-    if (ctx.config.debug.openUpDebugPane) {
+    if (ctx.config.debug.openDebugPane) {
         debugOutput.show(true);
     }
 
diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts
index a92c676fa2d..270fbcb6448 100644
--- a/editors/code/src/main.ts
+++ b/editors/code/src/main.ts
@@ -100,6 +100,7 @@ export async function activate(context: vscode.ExtensionContext) {
     ctx.registerCommand('applySnippetWorkspaceEdit', commands.applySnippetWorkspaceEditCommand);
     ctx.registerCommand('resolveCodeAction', commands.resolveCodeAction);
     ctx.registerCommand('applyActionGroup', commands.applyActionGroup);
+    ctx.registerCommand('gotoLocation', commands.gotoLocation);
 
     ctx.pushCleanup(activateTaskProvider(workspaceFolder));