rust-lang/rust-analyzer · error
Cannot rename parameter to self for trait functions
Error message
Cannot rename parameter to self for trait functions
What it means
rust-analyzer's rename_to_self refuses to convert the first parameter of a trait function into a `self` parameter. A trait's method signature declares its receiver abstractly (e.g. `fn foo(x: &Self)`) and rewriting it to `self` would change the trait contract for every implementor, not just the local function body, so the IDE bails out instead of producing an unsafe edit.
Source
Thrown at crates/ide/src/rename.rs:531
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"),
}
let assoc_item = fn_def
.as_assoc_item(sema.db)
.ok_or_else(|| format_err!("Cannot rename parameter to self for free function"))?;
let impl_ = match assoc_item.container(sema.db) {
hir::AssocItemContainer::Trait(_) => {
bail!("Cannot rename parameter to self for trait functions");
}
hir::AssocItemContainer::Impl(impl_) => impl_,
};
let first_param_ty = first_param.ty();
let impl_ty = impl_.self_ty(sema.db);
let (ty, self_param) = if impl_ty.is_reference() {
// if the impl is a ref to the type we can just match the `&T` with self directly
(first_param_ty.clone(), "self")
} else {
first_param_ty.as_reference_inner().map_or((first_param_ty.clone(), "self"), |ty| {
(ty, if first_param_ty.is_mutable_reference() { "&mut self" } else { "&self" })
})
};
if ty != impl_ty {
bail!("Parameter type differs from impl block type");
}
View on GitHub (pinned to e8f7e90aa3)
Solutions
- Rename the trait method's parameter to a normal identifier instead of `self`.
- If a method receiver is wanted, convert a concrete `impl` method's first parameter to `self` rather than the trait declaration's, or edit the trait signature manually (e.g. `fn foo(self)` / `fn foo(&self)`).
- Implement the method in an `impl Trait for Type` block and rename that impl's first parameter to `self` there.
Example fix
// before
trait Speaker {
fn speak(me: &Self);
}
// after
trait Speaker {
fn speak(&self);
} Defensive patterns
Strategy: try-catch
Try / catch
match rust_analyzer.rename(new_name == "self") {
Ok(edit) => apply(edit),
Err(e) if e.contains("trait functions") => {
// edit the trait signature manually or target an impl method instead
}
Err(e) => return Err(e),
} Prevention
- Only request rename-to-self on methods inside `impl` blocks.
- Edit trait method receivers (`self`, `&self`, `&mut self`) directly in source.
- Check the enclosing item kind (trait vs impl) before issuing the rename.
When it happens
Trigger: Calling rename with new name "self" on the first parameter of a function defined inside a `trait` block, where `fn_def.as_assoc_item()` resolves and `assoc_item.container()` is `AssocItemContainer::Trait(_)`.
Common situations: Selecting a parameter like `x: &Self` in a trait default method and invoking rename-to-self (IDE shortcut / `rust-analyzer.rename` from an editor LSP client).
Related errors
- Cannot rename builtin type
- Cannot rename a builtin attr.
- Cannot rename `Self`
- Invalid name `{0}`: cannot rename module to {0}
- Invalid name `{}`: not a lifetime identifier
AI-assisted analysis of rust-lang/rust-analyzer@e8f7e90aa3 (2026-09-03).
Data as JSON: /api/errors/6aef099348315fac.
Report an issue: GitHub.