rust-lang/rust-analyzer · error
Cannot rename local to self outside of function
Error message
Cannot rename local to self outside of function
What it means
rename_to_self converts a function parameter local into a `self` parameter, which is only possible when the local belongs to a function body (a DefWithBody::Function). If the local's parent is any other owner (const, static, closure-only contexts, etc.), the function bails with this error because there is no enclosing fn to attach a self parameter to.
Source
Thrown at crates/ide/src/rename.rs:506
source_change.insert_source_edit(
replace_range.file_id.file_id(sema.db),
TextEdit::replace(replace_range.range, replacement),
);
}
}
}
fn rename_to_self<'db>(
sema: &Semantics<'db, RootDatabase>,
local: hir::Local<'db>,
) -> RenameResult<SourceChange> {
if never!(local.is_self(sema.db)) {
bail!("rename_to_self invoked on self");
}
let fn_def = match local.parent(sema.db) {
hir::ExpressionStoreOwner::Body(hir::DefWithBody::Function(func)) => func,
_ => bail!("Cannot rename local to self outside of function"),
};
if fn_def.self_param(sema.db).is_some() {
bail!("Method already has a self parameter");
}
let params = fn_def.assoc_fn_params(sema.db);
let first_param = params
.first()
.ok_or_else(|| format_err!("Cannot rename local to self unless it is a parameter"))?;
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"),
}View on GitHub (pinned to e8f7e90aa3)
Solutions
- Only attempt self-rename on parameters of functions defined inside impl blocks.
- Rename the local to a normal identifier instead of `self`.
- If a self parameter is desired, restructure the code manually: move the logic into an impl fn and add `self`.
Example fix
// before
const X: i32 = { let v = 1; v }; // rename v -> self: error
// after
impl Foo { fn method(&self) { let v = 1; } }
Defensive patterns
Strategy: validation
Validate before calling
// Only attempt rename-to-self on locals inside fn bodies
// Cursor local must be inside a function (not const/static) and not itself `self`
fn can_rename_to_self(local_parent_kind: &str) -> bool {
local_parent_kind == "function"
} Try / catch
match rename(db, pos, "self", &config) {
Ok(change) => apply(change),
Err(e) if e.to_string().contains("Cannot rename local to self outside of function") => {
prompt_user("self rename is only valid inside functions");
}
Err(e) => report(e),
} Prevention
- Only expose rename-to-self inside function bodies
- Never target `self` itself for rename (that takes the self_param path)
- Restrict the rename-to-self refactor to parameters of impl functions
When it happens
Trigger: Calling rename with new_name == "self" on a local variable whose parent is not a function body (e.g. a let binding inside a const/static, or a local in a non-fn body owner).
Common situations: Users pressing F2 on a variable inside a const or static item and typing `self`; tools attempting self-conversion refactors outside impl fns.
Related errors
- Method already has a self parameter
- Only the first parameter may be renamed to self
- Invalid name `{}`: cannot rename to a keyword
- Invalid name `{}`: {}
- rename_to_self invoked on destructuring parameter
AI-assisted analysis of rust-lang/rust-analyzer@e8f7e90aa3 (2026-09-03).
Data as JSON: /api/errors/5e95f9d13f01e5c3.
Report an issue: GitHub.