Make search for applicable generics more precise

This commit is contained in:
Dorian Scheidt 2022-07-13 10:20:55 -05:00
parent 075ab03851
commit 796641b5d8

View file

@ -823,8 +823,9 @@ impl FunctionBody {
});
let parent = self.parent()?;
let generic_param_lists = parent_generic_param_lists(&parent);
let where_clauses = parent_where_clauses(&parent);
let parents = generic_parents(&parent);
let generic_param_lists = parents.iter().filter_map(|it| it.generic_param_list()).collect();
let where_clauses = parents.iter().filter_map(|it| it.where_clause()).collect();
Some(ContainerInfo {
is_in_tail,
@ -990,24 +991,54 @@ impl FunctionBody {
}
}
fn parent_where_clauses(parent: &SyntaxNode) -> Vec<ast::WhereClause> {
let mut where_clause: Vec<ast::WhereClause> = parent
.ancestors()
.filter_map(ast::AnyHasGenericParams::cast)
.filter_map(|it| it.where_clause())
.collect();
where_clause.reverse();
where_clause
enum GenericParent {
Fn(ast::Fn),
Impl(ast::Impl),
Trait(ast::Trait),
}
fn parent_generic_param_lists(parent: &SyntaxNode) -> Vec<ast::GenericParamList> {
let mut generic_param_list: Vec<ast::GenericParamList> = parent
.ancestors()
.filter_map(ast::AnyHasGenericParams::cast)
.filter_map(|it| it.generic_param_list())
.collect();
generic_param_list.reverse();
generic_param_list
impl GenericParent {
fn generic_param_list(&self) -> Option<ast::GenericParamList> {
match self {
GenericParent::Fn(fn_) => fn_.generic_param_list(),
GenericParent::Impl(impl_) => impl_.generic_param_list(),
GenericParent::Trait(trait_) => trait_.generic_param_list(),
}
}
fn where_clause(&self) -> Option<ast::WhereClause> {
match self {
GenericParent::Fn(fn_) => fn_.where_clause(),
GenericParent::Impl(impl_) => impl_.where_clause(),
GenericParent::Trait(trait_) => trait_.where_clause(),
}
}
}
/// Search `parent`'s ancestors for items with potentially applicable generic parameters
fn generic_parents(parent: &SyntaxNode) -> Vec<GenericParent> {
let mut list = Vec::new();
if let Some(parent_item) = parent.ancestors().find_map(ast::Item::cast) {
match parent_item {
ast::Item::Fn(ref fn_) => {
if let Some(parent_parent) = parent_item
.syntax()
.parent()
.and_then(|it| it.parent())
.and_then(ast::Item::cast)
{
match parent_parent {
ast::Item::Impl(impl_) => list.push(GenericParent::Impl(impl_)),
ast::Item::Trait(trait_) => list.push(GenericParent::Trait(trait_)),
_ => (),
}
}
list.push(GenericParent::Fn(fn_.clone()));
}
_ => (),
}
}
list
}
/// checks if relevant var is used with `&mut` access inside body