Unnamed repository; edit this file 'description' to name the repository.
fix: Resolve generic parameters within use captures
Lukas Wirth 2024-12-06
parent 7f39ee3 · commit d6b6226
-rw-r--r--crates/hir-def/src/resolver.rs4
-rw-r--r--crates/hir/src/semantics.rs4
-rw-r--r--crates/hir/src/source_analyzer.rs8
-rw-r--r--crates/ide-db/src/defs.rs7
-rw-r--r--crates/ide/src/rename.rs69
5 files changed, 90 insertions, 2 deletions
diff --git a/crates/hir-def/src/resolver.rs b/crates/hir-def/src/resolver.rs
index 0ca7070fd0..316406c151 100644
--- a/crates/hir-def/src/resolver.rs
+++ b/crates/hir-def/src/resolver.rs
@@ -642,9 +642,9 @@ impl Resolver {
})
}
- pub fn generic_params(&self) -> Option<&Arc<GenericParams>> {
+ 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/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index 0b09cf2792..f9d3f9d07e 100644
--- a/crates/hir/src/semantics.rs
+++ b/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<TypeParam> {
+ self.analyze(name.syntax())?.resolve_use_type_arg(name)
+ }
+
pub fn resolve_mod_path(
&self,
scope: &SyntaxNode,
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs
index 56ed81f053..4329a888b3 100644
--- a/crates/hir/src/source_analyzer.rs
+++ b/crates/hir/src/source_analyzer.rs
@@ -642,6 +642,14 @@ impl SourceAnalyzer {
}
}
+ pub(crate) fn resolve_use_type_arg(&self, name: &ast::NameRef) -> Option<crate::TypeParam> {
+ 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/crates/ide-db/src/defs.rs b/crates/ide-db/src/defs.rs
index 5eec33636b..932ca37302 100644
--- a/crates/ide-db/src/defs.rs
+++ b/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/crates/ide/src/rename.rs b/crates/ide/src/rename.rs
index 665fc954d2..a9519c03b3 100644
--- a/crates/ide/src/rename.rs
+++ b/crates/ide/src/rename.rs
@@ -3105,4 +3105,73 @@ fn main() { let _: Baz; }
"#,
);
}
+
+ #[test]
+ fn rename_type_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_type_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_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<T> {
+ fn foo() -> impl use<T$0> Trait {}
+}
+"#,
+ r#"
+trait Trait<U> {
+ fn foo() -> impl use<U> Trait {}
+}
+"#,
+ );
+ }
}