Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/hir/src/lib.rs9
-rw-r--r--crates/ide/src/rename.rs9
-rw-r--r--crates/ide_assists/src/handlers/inline_call.rs47
3 files changed, 41 insertions, 24 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 8bab7c1f3e..37bb2e1997 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -1506,10 +1506,15 @@ impl Param {
db.function_data(self.func.id).params[self.idx].0.clone()
}
- pub fn as_local(&self, db: &dyn HirDatabase) -> Local {
+ pub fn as_local(&self, db: &dyn HirDatabase) -> Option<Local> {
let parent = DefWithBodyId::FunctionId(self.func.into());
let body = db.body(parent);
- Local { parent, pat_id: body.params[self.idx] }
+ let pat_id = body.params[self.idx];
+ if let Pat::Bind { .. } = &body[pat_id] {
+ Some(Local { parent, pat_id: body.params[self.idx] })
+ } else {
+ None
+ }
}
pub fn pattern_source(&self, db: &dyn HirDatabase) -> Option<ast::Pat> {
diff --git a/crates/ide/src/rename.rs b/crates/ide/src/rename.rs
index 83bc299adc..1bb3cdb907 100644
--- a/crates/ide/src/rename.rs
+++ b/crates/ide/src/rename.rs
@@ -219,8 +219,13 @@ fn rename_to_self(sema: &Semantics<RootDatabase>, local: hir::Local) -> RenameRe
let first_param = params
.first()
.ok_or_else(|| format_err!("Cannot rename local to self unless it is a parameter"))?;
- if first_param.as_local(sema.db) != local {
- bail!("Only the first parameter may be renamed to self");
+ match first_param.as_local(sema.db) {
+ Some(plocal) => {
+ if plocal != local {
+ bail!("Only the first parameter may be renamed to self");
+ }
+ }
+ None => bail!("rename_to_self invoked on destructuring parameter"),
}
let assoc_item = fn_def
diff --git a/crates/ide_assists/src/handlers/inline_call.rs b/crates/ide_assists/src/handlers/inline_call.rs
index af2cb332e5..c857adf876 100644
--- a/crates/ide_assists/src/handlers/inline_call.rs
+++ b/crates/ide_assists/src/handlers/inline_call.rs
@@ -317,30 +317,37 @@ fn inline(
if !matches!(pat, ast::Pat::IdentPat(pat) if pat.is_simple_ident()) {
return Vec::new();
}
- usages_for_locals(param.as_local(sema.db))
- .map(|FileReference { name, range, .. }| match name {
- ast::NameLike::NameRef(_) => body
- .syntax()
- .covering_element(range)
- .ancestors()
- .nth(3)
- .and_then(ast::PathExpr::cast),
- _ => None,
- })
- .collect::<Option<Vec<_>>>()
- .unwrap_or_default()
+ // FIXME: we need to fetch all locals declared in the parameter here
+ // not only the local if it is a simple binding
+ match param.as_local(sema.db) {
+ Some(l) => usages_for_locals(l)
+ .map(|FileReference { name, range, .. }| match name {
+ ast::NameLike::NameRef(_) => body
+ .syntax()
+ .covering_element(range)
+ .ancestors()
+ .nth(3)
+ .and_then(ast::PathExpr::cast),
+ _ => None,
+ })
+ .collect::<Option<Vec<_>>>()
+ .unwrap_or_default(),
+ None => Vec::new(),
+ }
})
.collect();
if function.self_param(sema.db).is_some() {
let this = || make::name_ref("this").syntax().clone_for_update();
- usages_for_locals(params[0].2.as_local(sema.db))
- .flat_map(|FileReference { name, range, .. }| match name {
- ast::NameLike::NameRef(_) => Some(body.syntax().covering_element(range)),
- _ => None,
- })
- .for_each(|it| {
- ted::replace(it, &this());
- })
+ if let Some(self_local) = params[0].2.as_local(sema.db) {
+ usages_for_locals(self_local)
+ .flat_map(|FileReference { name, range, .. }| match name {
+ ast::NameLike::NameRef(_) => Some(body.syntax().covering_element(range)),
+ _ => None,
+ })
+ .for_each(|it| {
+ ted::replace(it, &this());
+ })
+ }
}
// Inline parameter expressions or generate `let` statements depending on whether inlining works or not.
for ((pat, param_ty, _), usages, expr) in izip!(params, param_use_nodes, arguments).rev() {