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 parent = self.parent()?;
let generic_param_lists = parent_generic_param_lists(&parent); let parents = generic_parents(&parent);
let where_clauses = parent_where_clauses(&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 { Some(ContainerInfo {
is_in_tail, is_in_tail,
@ -990,24 +991,54 @@ impl FunctionBody {
} }
} }
fn parent_where_clauses(parent: &SyntaxNode) -> Vec<ast::WhereClause> { enum GenericParent {
let mut where_clause: Vec<ast::WhereClause> = parent Fn(ast::Fn),
.ancestors() Impl(ast::Impl),
.filter_map(ast::AnyHasGenericParams::cast) Trait(ast::Trait),
.filter_map(|it| it.where_clause())
.collect();
where_clause.reverse();
where_clause
} }
fn parent_generic_param_lists(parent: &SyntaxNode) -> Vec<ast::GenericParamList> { impl GenericParent {
let mut generic_param_list: Vec<ast::GenericParamList> = parent fn generic_param_list(&self) -> Option<ast::GenericParamList> {
.ancestors() match self {
.filter_map(ast::AnyHasGenericParams::cast) GenericParent::Fn(fn_) => fn_.generic_param_list(),
.filter_map(|it| it.generic_param_list()) GenericParent::Impl(impl_) => impl_.generic_param_list(),
.collect(); GenericParent::Trait(trait_) => trait_.generic_param_list(),
generic_param_list.reverse(); }
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 /// checks if relevant var is used with `&mut` access inside body