diff --git a/crates/hir_def/src/path/lower.rs b/crates/hir_def/src/path/lower.rs index a469546c13d..505493a7483 100644 --- a/crates/hir_def/src/path/lower.rs +++ b/crates/hir_def/src/path/lower.rs @@ -101,8 +101,12 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option break; } ast::PathSegmentKind::SelfKw => { - kind = PathKind::Super(0); - break; + // don't break out if `self` is the last segment of a path, this mean we got an + // use tree like `foo::{self}` which we want to resolve as `foo` + if !segments.is_empty() { + kind = PathKind::Super(0); + break; + } } ast::PathSegmentKind::SuperKw => { let nested_super_count = if let PathKind::Super(n) = kind { n } else { 0 }; @@ -117,6 +121,11 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option segments.reverse(); generic_args.reverse(); + if segments.is_empty() && kind == PathKind::Plain && type_anchor.is_none() { + // plain empty paths don't exist, this means we got a single `self` segment as our path + kind = PathKind::Super(0); + } + // handle local_inner_macros : // Basically, even in rustc it is quite hacky: // https://github.com/rust-lang/rust/blob/614f273e9388ddd7804d5cbc80b8865068a3744e/src/librustc_resolve/macros.rs#L456 diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index 9a605b09d08..20b799490e1 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs @@ -3496,4 +3496,33 @@ mod foo$0; "#]], ); } + + #[test] + fn hover_self_in_use() { + check( + r#" +//! This should not appear +mod foo { + /// But this should appear + pub mod bar {} +} +use foo::bar::{self$0}; +"#, + expect![[r#" + *self* + + ```rust + test::foo + ``` + + ```rust + pub mod bar + ``` + + --- + + But this should appear + "#]], + ); + } }