diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs index 364263d9bb..dd5f9f31c9 100644 --- a/crates/ra_ide_api/src/goto_definition.rs +++ b/crates/ra_ide_api/src/goto_definition.rs @@ -100,6 +100,7 @@ pub(crate) fn reference_definition( } } } + // Try name resolution let resolver = hir::source_binder::resolver_for_node(db, file_id, name_ref.syntax()); if let Some(path) = @@ -126,17 +127,35 @@ pub(crate) fn reference_definition( None => { // If we failed to resolve then check associated items if let Some(function) = function { - // Should we do this above and then grab path from the PathExpr? + // Resolve associated item for path expressions if let Some(path_expr) = name_ref.syntax().ancestors().find_map(ast::PathExpr::cast) { let infer_result = function.infer(db); let source_map = function.body_source_map(db); - let expr = ast::Expr::cast(path_expr.syntax()).unwrap(); + + if let Some(expr) = ast::Expr::cast(path_expr.syntax()) { + if let Some(res) = source_map + .node_expr(expr) + .and_then(|it| infer_result.assoc_resolutions_for_expr(it.into())) + { + return Exact(NavigationTarget::from_impl_item(db, res)); + } + } + } + + // Resolve associated item for path patterns + if let Some(path_pat) = + name_ref.syntax().ancestors().find_map(ast::PathPat::cast) + { + let infer_result = function.infer(db); + let source_map = function.body_source_map(db); + + let pat: &ast::Pat = path_pat.into(); if let Some(res) = source_map - .node_expr(expr) - .and_then(|it| infer_result.assoc_resolutions_for_expr(it.into())) + .node_pat(pat) + .and_then(|it| infer_result.assoc_resolutions_for_pat(it.into())) { return Exact(NavigationTarget::from_impl_item(db, res)); } diff --git a/crates/ra_ide_api/src/hover.rs b/crates/ra_ide_api/src/hover.rs index bcd052c8bc..638c24e319 100644 --- a/crates/ra_ide_api/src/hover.rs +++ b/crates/ra_ide_api/src/hover.rs @@ -534,4 +534,27 @@ mod tests { assert_eq!(trim_markup_opt(hover.info.first()), Some("fn new() -> Thing")); assert_eq!(hover.info.is_exact(), true); } + + #[test] + fn test_hover_infer_associated_const_in_pattern() { + let (analysis, position) = single_file_with_position( + " + struct X; + impl X { + const C: u32 = 1; + } + + fn main() { + match 1 { + X::C<|> => {}, + 2 => {}, + _ => {} + }; + } + ", + ); + let hover = analysis.hover(position).unwrap().unwrap(); + assert_eq!(trim_markup_opt(hover.info.first()), Some("const C: u32")); + assert_eq!(hover.info.is_exact(), true); + } }