rust-lang/rust-analyzer · error

Only the first parameter may be renamed to self

Error message

Only the first parameter may be renamed to self

What it means

Renaming to `self` is only allowed for the first parameter of the function. rename_to_self resolves the first parameter's local and, if it differs from the local under the cursor, bails with this error. Self parameters must occupy the first position in Rust's parameter list.

Source

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

    }

    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"))?;
    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

View on GitHub (pinned to e8f7e90aa3)

Solutions

  1. Target the first parameter of the function when renaming to self.
  2. Reorder parameters manually so the desired one is first, then rename to self.
  3. Rename the local to another identifier and refactor to self manually.

Example fix

// before
fn f(a: i32, b: i32) {} // rename b -> self: error
// after
fn f(b: i32, a: i32) {} // rename first param b -> self
Defensive patterns

Strategy: validation

Validate before calling

// Only the first parameter may become self; verify the cursor's local
// is the first named parameter of the enclosing fn before renaming
fn is_first_param(cursor_param_index: usize) -> bool {
    cursor_param_index == 0
}

Try / catch

match rename(db, pos, "self", &config) {
    Ok(change) => apply(change),
    Err(e) if e.to_string().contains("Only the first parameter may be renamed to self") => {
        prompt_user("Only the first parameter can become self");
    }
    Err(e) => report(e),
}

Prevention

When it happens

Trigger: Calling rename with new_name == "self" on any local/parameter that is not the function's first parameter (e.g. the second or third fn parameter).

Common situations: Users pressing F2 on a later parameter and typing `self`, expecting rust-analyzer to reorder parameters — which it refuses to do.

Related errors


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