{"record":{"id":"30094ec8c3af1aa5","repo":"rust-lang/rust-analyzer","slug":"method-already-has-a-self-parameter","errorCode":null,"errorMessage":"Method already has a self parameter","messagePattern":"Method already has a self parameter","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/ide/src/rename.rs","lineNumber":510,"sourceCode":"        }\n    }\n}\n\nfn rename_to_self<'db>(\n    sema: &Semantics<'db, RootDatabase>,\n    local: hir::Local<'db>,\n) -> RenameResult<SourceChange> {\n    if never!(local.is_self(sema.db)) {\n        bail!(\"rename_to_self invoked on self\");\n    }\n\n    let fn_def = match local.parent(sema.db) {\n        hir::ExpressionStoreOwner::Body(hir::DefWithBody::Function(func)) => func,\n        _ => bail!(\"Cannot rename local to self outside of function\"),\n    };\n\n    if fn_def.self_param(sema.db).is_some() {\n        bail!(\"Method already has a self parameter\");\n    }\n\n    let params = fn_def.assoc_fn_params(sema.db);\n    let first_param = params\n        .first()\n        .ok_or_else(|| format_err!(\"Cannot rename local to self unless it is a parameter\"))?;\n    match first_param.as_local(sema.db) {\n        Some(plocal) => {\n            if plocal != local {\n                bail!(\"Only the first parameter may be renamed to self\");\n            }\n        }\n        None => bail!(\"rename_to_self invoked on destructuring parameter\"),\n    }\n\n    let assoc_item = fn_def\n        .as_assoc_item(sema.db)\n        .ok_or_else(|| format_err!(\"Cannot rename parameter to self for free function\"))?;","sourceCodeStart":492,"sourceCodeEnd":528,"githubUrl":"https://github.com/rust-lang/rust-analyzer/blob/e8f7e90aa3e7b26aa9a000200f606c1078da99ec/crates/ide/src/rename.rs#L492-L528","documentation":"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.","triggerScenarios":"Calling rename with new_name == \"self\" on a local inside a method (a fn that already has a `self`/`&self`/`&mut self` parameter).","commonSituations":"Users pressing F2 on another parameter or local inside a method and typing `self`; refactoring tools converting an associated fn that already has self.","solutions":["Rename the local to a plain identifier instead of `self`.","To merge the local with the existing self parameter, refactor manually (use the self value directly)."],"exampleFix":"// before\nimpl T { fn f(&self, other: i32) { other } } // rename other -> self: error\n// after\nimpl T { fn f(&self) { /* use self */ } }\n","handlingStrategy":"validation","validationCode":"// Only attempt rename-to-self in functions that lack a self parameter\n// (check via hover/signature or parse the fn signature client-side)\nfn has_self_param(signature: &str) -> bool {\n    signature.trim_start_matches(|c: char| c.is_alphanumeric() || c == '_' || c.is_whitespace())\n        .starts_with('&') || signature.starts_with(\"self\")\n}\nif has_self_param(fn_signature) { /* skip rename-to-self */ }","typeGuard":null,"tryCatchPattern":"match rename(db, pos, \"self\", &config) {\n    Ok(change) => apply(change),\n    Err(e) if e.to_string().contains(\"Method already has a self parameter\") => {\n        prompt_user(\"This method already has a self parameter\");\n    }\n    Err(e) => report(e),\n}","preventionTips":["Check the target function's signature for an existing self param first","Only offer rename-to-self for associated fns without self receivers","Educate users: inside methods, rename locals to ordinary names"],"tags":["rust-analyzer","rename","self-parameter","validation"],"backgroundTag":"invalid-rename-to-self","analyzedSha":"e8f7e90aa3e7b26aa9a000200f606c1078da99ec","analyzedAt":"2026-09-03T21:08:06.959Z","contentChangedAt":"2026-09-03T21:08:06.959Z","schemaVersion":2},"datasetVersion":"2026-09-11T07:07:21.782Z"}