From 64832b0ddb274bc752b1627c95fa0558d847e27d Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 5 Dec 2024 14:37:38 +0100 Subject: [PATCH] fix: Resolve generic parameters within use captures --- .../crates/hir-def/src/resolver.rs | 4 +- .../rust-analyzer/crates/hir/src/semantics.rs | 4 ++ .../crates/hir/src/source_analyzer.rs | 8 +++ .../rust-analyzer/crates/ide-db/src/defs.rs | 7 ++ .../rust-analyzer/crates/ide/src/rename.rs | 69 +++++++++++++++++++ 5 files changed, 90 insertions(+), 2 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs index 0ca7070fd05f..316406c151f9 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs @@ -642,9 +642,9 @@ impl Resolver { }) } - pub fn generic_params(&self) -> Option<&Arc> { + pub fn generic_params(&self) -> Option<&GenericParams> { self.scopes().find_map(|scope| match scope { - Scope::GenericParams { params, .. } => Some(params), + Scope::GenericParams { params, .. } => Some(&**params), _ => None, }) } diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs index 0b09cf279269..f9d3f9d07e65 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs @@ -1517,6 +1517,10 @@ impl<'db> SemanticsImpl<'db> { self.analyze(path.syntax())?.resolve_path(self.db, path) } + pub fn resolve_use_type_arg(&self, name: &ast::NameRef) -> Option { + self.analyze(name.syntax())?.resolve_use_type_arg(name) + } + pub fn resolve_mod_path( &self, scope: &SyntaxNode, diff --git a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs index 56ed81f053c1..4329a888b392 100644 --- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs +++ b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs @@ -642,6 +642,14 @@ impl SourceAnalyzer { } } + pub(crate) fn resolve_use_type_arg(&self, name: &ast::NameRef) -> Option { + let name = name.as_name(); + self.resolver + .all_generic_params() + .find_map(|(params, parent)| params.find_type_by_name(&name, *parent)) + .map(crate::TypeParam::from) + } + pub(crate) fn resolve_path( &self, db: &dyn HirDatabase, diff --git a/src/tools/rust-analyzer/crates/ide-db/src/defs.rs b/src/tools/rust-analyzer/crates/ide-db/src/defs.rs index 5eec33636bec..932ca373020d 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/defs.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/defs.rs @@ -733,6 +733,12 @@ impl NameRefClass { } None }, + ast::UseBoundGenericArgs(_) => { + sema.resolve_use_type_arg(name_ref) + .map(GenericParam::TypeParam) + .map(Definition::GenericParam) + .map(NameRefClass::Definition) + }, ast::ExternCrate(extern_crate_ast) => { let extern_crate = sema.to_def(&extern_crate_ast)?; let krate = extern_crate.resolved_crate(sema.db)?; @@ -764,6 +770,7 @@ impl NameRefClass { sema.resolve_label(lifetime).map(Definition::Label).map(NameRefClass::Definition) } SyntaxKind::LIFETIME_ARG + | SyntaxKind::USE_BOUND_GENERIC_ARGS | SyntaxKind::SELF_PARAM | SyntaxKind::TYPE_BOUND | SyntaxKind::WHERE_PRED diff --git a/src/tools/rust-analyzer/crates/ide/src/rename.rs b/src/tools/rust-analyzer/crates/ide/src/rename.rs index 665fc954d239..a9519c03b322 100644 --- a/src/tools/rust-analyzer/crates/ide/src/rename.rs +++ b/src/tools/rust-analyzer/crates/ide/src/rename.rs @@ -3102,6 +3102,75 @@ fn main() { let _: S; } r#" use lib::S as Baz; fn main() { let _: Baz; } +"#, + ); + } + + #[test] + fn rename_type_param_ref_in_use_bound() { + check( + "U", + r#" +fn foo() -> impl use Trait {} +"#, + r#" +fn foo() -> impl use Trait {} +"#, + ); + } + + #[test] + fn rename_type_param_in_use_bound() { + check( + "U", + r#" +fn foo() -> impl use Trait {} +"#, + r#" +fn foo() -> impl use Trait {} +"#, + ); + } + + #[test] + fn rename_lifetime_param_ref_in_use_bound() { + check( + "u", + r#" +fn foo<'t>() -> impl use<'t$0> Trait {} +"#, + r#" +fn foo<'u>() -> impl use<'u> Trait {} +"#, + ); + } + + #[test] + fn rename_lifetime_param_in_use_bound() { + check( + "u", + r#" +fn foo<'t$0>() -> impl use<'t> Trait {} +"#, + r#" +fn foo<'u>() -> impl use<'u> Trait {} +"#, + ); + } + + #[test] + fn rename_parent_type_param_in_use_bound() { + check( + "U", + r#" +trait Trait { + fn foo() -> impl use Trait {} +} +"#, + r#" +trait Trait { + fn foo() -> impl use Trait {} +} "#, ); }