Merge pull request #18621 from Veykril/push-suuyuvsmqpyq

fix: Resolve generic parameters within use captures
This commit is contained in:
Lukas Wirth 2024-12-05 18:26:37 +00:00 committed by GitHub
commit 34665c7274
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 90 additions and 2 deletions

View file

@ -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,
})
}

View file

@ -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,

View file

@ -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,

View file

@ -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

View file

@ -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<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 {}
}
"#,
);
}