lifetime transformation: refactoring & a new test

This commit is contained in:
ponyii 2023-05-28 21:15:57 +04:00
parent fe8f862757
commit 7f45cccda4
3 changed files with 45 additions and 10 deletions

View File

@ -2637,10 +2637,14 @@ pub fn params(self, db: &dyn HirDatabase) -> Vec<GenericParam> {
Either::Right(x) => GenericParam::TypeParam(x), Either::Right(x) => GenericParam::TypeParam(x),
} }
}); });
self.lifetime_params(db).into_iter().chain(ty_params).collect() self.lifetime_params(db)
.into_iter()
.map(GenericParam::LifetimeParam)
.chain(ty_params)
.collect()
} }
pub fn lifetime_params(self, db: &dyn HirDatabase) -> Vec<GenericParam> { pub fn lifetime_params(self, db: &dyn HirDatabase) -> Vec<LifetimeParam> {
let generics = db.generic_params(self.into()); let generics = db.generic_params(self.into());
generics generics
.lifetimes .lifetimes
@ -2648,7 +2652,6 @@ pub fn lifetime_params(self, db: &dyn HirDatabase) -> Vec<GenericParam> {
.map(|(local_id, _)| LifetimeParam { .map(|(local_id, _)| LifetimeParam {
id: LifetimeParamId { parent: self.into(), local_id }, id: LifetimeParamId { parent: self.into(), local_id },
}) })
.map(GenericParam::LifetimeParam)
.collect() .collect()
} }

View File

@ -833,6 +833,33 @@ impl Test for () {
); );
} }
#[test]
fn fn_with_lifetimes() {
check_edit(
"fn foo",
r#"
trait Test<'a, 'b, T> {
fn foo(&self, a: &'a T, b: &'b T) -> &'a T;
}
impl<'x, 'y, A> Test<'x, 'y, A> for () {
t$0
}
"#,
r#"
trait Test<'a, 'b, T> {
fn foo(&self, a: &'a T, b: &'b T) -> &'a T;
}
impl<'x, 'y, A> Test<'x, 'y, A> for () {
fn foo(&self, a: &'x A, b: &'y A) -> &'x A {
$0
}
}
"#,
);
}
#[test] #[test]
fn complete_without_name() { fn complete_without_name() {
let test = |completion: &str, hint: &str, completed: &str, next_sibling: &str| { let test = |completion: &str, hint: &str, completed: &str, next_sibling: &str| {

View File

@ -10,7 +10,7 @@
}; };
#[derive(Default)] #[derive(Default)]
struct Substs { struct AstSubsts {
types: Vec<ast::TypeArg>, types: Vec<ast::TypeArg>,
lifetimes: Vec<ast::LifetimeArg>, lifetimes: Vec<ast::LifetimeArg>,
} }
@ -42,7 +42,7 @@ struct Substs {
/// ``` /// ```
pub struct PathTransform<'a> { pub struct PathTransform<'a> {
generic_def: Option<hir::GenericDef>, generic_def: Option<hir::GenericDef>,
substs: Substs, substs: AstSubsts,
target_scope: &'a SemanticsScope<'a>, target_scope: &'a SemanticsScope<'a>,
source_scope: &'a SemanticsScope<'a>, source_scope: &'a SemanticsScope<'a>,
} }
@ -80,7 +80,12 @@ pub fn generic_transformation(
target_scope: &'a SemanticsScope<'a>, target_scope: &'a SemanticsScope<'a>,
source_scope: &'a SemanticsScope<'a>, source_scope: &'a SemanticsScope<'a>,
) -> PathTransform<'a> { ) -> PathTransform<'a> {
PathTransform { source_scope, target_scope, generic_def: None, substs: Substs::default() } PathTransform {
source_scope,
target_scope,
generic_def: None,
substs: AstSubsts::default(),
}
} }
pub fn apply(&self, syntax: &SyntaxNode) { pub fn apply(&self, syntax: &SyntaxNode) {
@ -134,7 +139,7 @@ fn build_ctx(&self) -> Ctx<'a> {
.into_iter() .into_iter()
.flat_map(|it| it.lifetime_params(db)) .flat_map(|it| it.lifetime_params(db))
.zip(self.substs.lifetimes.clone()) .zip(self.substs.lifetimes.clone())
.filter_map(|(k, v)| Some((k.name(db).to_string(), v.lifetime()?))) .filter_map(|(k, v)| Some((k.name(db).display(db.upcast()).to_string(), v.lifetime()?)))
.collect(); .collect();
Ctx { type_substs, lifetime_substs, target_module, source_scope: self.source_scope } Ctx { type_substs, lifetime_substs, target_module, source_scope: self.source_scope }
} }
@ -279,7 +284,7 @@ fn transform_path(&self, path: ast::Path) -> Option<()> {
// FIXME: It would probably be nicer if we could get this via HIR (i.e. get the // FIXME: It would probably be nicer if we could get this via HIR (i.e. get the
// trait ref, and then go from the types in the substs back to the syntax). // trait ref, and then go from the types in the substs back to the syntax).
fn get_syntactic_substs(impl_def: ast::Impl) -> Option<Substs> { fn get_syntactic_substs(impl_def: ast::Impl) -> Option<AstSubsts> {
let target_trait = impl_def.trait_()?; let target_trait = impl_def.trait_()?;
let path_type = match target_trait { let path_type = match target_trait {
ast::Type::PathType(path) => path, ast::Type::PathType(path) => path,
@ -290,8 +295,8 @@ fn get_syntactic_substs(impl_def: ast::Impl) -> Option<Substs> {
get_type_args_from_arg_list(generic_arg_list) get_type_args_from_arg_list(generic_arg_list)
} }
fn get_type_args_from_arg_list(generic_arg_list: ast::GenericArgList) -> Option<Substs> { fn get_type_args_from_arg_list(generic_arg_list: ast::GenericArgList) -> Option<AstSubsts> {
let mut result = Substs::default(); let mut result = AstSubsts::default();
generic_arg_list.generic_args().for_each(|generic_arg| match generic_arg { generic_arg_list.generic_args().for_each(|generic_arg| match generic_arg {
ast::GenericArg::TypeArg(type_arg) => result.types.push(type_arg), ast::GenericArg::TypeArg(type_arg) => result.types.push(type_arg),
ast::GenericArg::LifetimeArg(l_arg) => result.lifetimes.push(l_arg), ast::GenericArg::LifetimeArg(l_arg) => result.lifetimes.push(l_arg),