Skip to content

Commit

Permalink
fix: Support generics in extract_function assist
Browse files Browse the repository at this point in the history
This change attempts to resolve issue rust-lang#7637: Extract into Function does not
create a generic function with constraints when extracting generic code.

In `FunctionBody::analyze_container`, when the ancestor matches `ast::Fn`, we
can perserve both the `generic_param_list` and the `where_clause`. These can
then be included in the newly extracted function output via `format_function`.

From what I can tell, the only other ancestor type that could potentially have
a generic param list would be `ast::ClosureExpr`. In this case, we perserve the
`generic_param_list`, but no where clause is ever present.

In this initial implementation, only generic type parameters (and their
associated where clauses) which are referenced in the extracted function body
are copied to the new function signature. Const and Lifetime params are ignored
for now.

I don't believe this implementation will work in contexts where the generic
parameters and where clauses are defined multiple layers above the function
being extracted, such as with nested function declarations. Resolving this
seems like another obvious improvement, but one that will potentially require
more significant changes to the structure of `analyze_container` that I wasn't
comfortable trying to make as a first change.
  • Loading branch information
DorianListens committed Jul 6, 2022
1 parent c46570e commit ea7b8b8
Show file tree
Hide file tree
Showing 2 changed files with 292 additions and 8 deletions.
9 changes: 9 additions & 0 deletions crates/hir/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3286,6 +3286,15 @@ impl Type {
let tys = hir_ty::replace_errors_with_variables(&(self.ty.clone(), to.ty.clone()));
hir_ty::could_coerce(db, self.env.clone(), &tys)
}

pub fn as_type_param(&self, db: &dyn HirDatabase) -> Option<TypeParam> {
match self.ty.kind(Interner) {
TyKind::Placeholder(p) => Some(TypeParam {
id: TypeParamId::from_unchecked(hir_ty::from_placeholder_idx(db, *p)),
}),
_ => None,
}
}
}

#[derive(Debug)]
Expand Down
Loading

0 comments on commit ea7b8b8

Please sign in to comment.