rust-lang/rust-analyzer · error

Method already has a self parameter

Error message

Method already has a self parameter

What it means

When renaming a local to `self`, the target function must not already have a self parameter; two self parameters are illegal Rust. rename_to_self checks fn_def.self_param and rejects the operation with this error if one already exists.

Source

Thrown at crates/ide/src/rename.rs:510

        }
    }
}

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"),
    }

    let assoc_item = fn_def
        .as_assoc_item(sema.db)
        .ok_or_else(|| format_err!("Cannot rename parameter to self for free function"))?;

View on GitHub (pinned to e8f7e90aa3)

Solutions

  1. Rename the local to a plain identifier instead of `self`.
  2. To merge the local with the existing self parameter, refactor manually (use the self value directly).

Example fix

// before
impl T { fn f(&self, other: i32) { other } } // rename other -> self: error
// after
impl T { fn f(&self) { /* use self */ } }
Defensive patterns

Strategy: validation

Validate before calling

// Only attempt rename-to-self in functions that lack a self parameter
// (check via hover/signature or parse the fn signature client-side)
fn has_self_param(signature: &str) -> bool {
    signature.trim_start_matches(|c: char| c.is_alphanumeric() || c == '_' || c.is_whitespace())
        .starts_with('&') || signature.starts_with("self")
}
if has_self_param(fn_signature) { /* skip rename-to-self */ }

Try / catch

match rename(db, pos, "self", &config) {
    Ok(change) => apply(change),
    Err(e) if e.to_string().contains("Method already has a self parameter") => {
        prompt_user("This method already has a self parameter");
    }
    Err(e) => report(e),
}

Prevention

When it happens

Trigger: Calling rename with new_name == "self" on a local inside a method (a fn that already has a `self`/`&self`/`&mut self` parameter).

Common situations: Users pressing F2 on another parameter or local inside a method and typing `self`; refactoring tools converting an associated fn that already has self.

Related errors


AI-assisted analysis of rust-lang/rust-analyzer@e8f7e90aa3 (2026-09-03). Data as JSON: /api/errors/30094ec8c3af1aa5. Report an issue: GitHub.