{"record":{"id":"fd045eea262ffee4","repo":"rust-lang/rust-analyzer","slug":"rename-to-self-invoked-on-destructuring-parameter","errorCode":null,"errorMessage":"rename_to_self invoked on destructuring parameter","messagePattern":"rename_to_self invoked on destructuring parameter","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/ide/src/rename.rs","lineNumber":523,"sourceCode":"        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\"))?;\n    let impl_ = match assoc_item.container(sema.db) {\n        hir::AssocItemContainer::Trait(_) => {\n            bail!(\"Cannot rename parameter to self for trait functions\");\n        }\n        hir::AssocItemContainer::Impl(impl_) => impl_,\n    };\n    let first_param_ty = first_param.ty();\n    let impl_ty = impl_.self_ty(sema.db);\n    let (ty, self_param) = if impl_ty.is_reference() {\n        // if the impl is a ref to the type we can just match the `&T` with self directly\n        (first_param_ty.clone(), \"self\")\n    } else {\n        first_param_ty.as_reference_inner().map_or((first_param_ty.clone(), \"self\"), |ty| {","sourceCodeStart":505,"sourceCodeEnd":541,"githubUrl":"https://github.com/rust-lang/rust-analyzer/blob/e8f7e90aa3e7b26aa9a000200f606c1078da99ec/crates/ide/src/rename.rs#L505-L541","documentation":"rename_to_self needs the first parameter to correspond to a single local binding so it can verify and convert it to self. When the first parameter is destructured (e.g. a tuple or struct pattern like `(a, b): (i32, i32)`), first_param.as_local returns None and the function bails, because a destructuring pattern cannot become a self parameter.","triggerScenarios":"Calling rename with new_name == \"self\" on a local that is a binding inside a destructured first-parameter pattern (tuple/struct/ref patterns), so the parameter has no single as_local.","commonSituations":"Users pressing F2 on a pattern-bound identifier inside a destructured parameter and typing `self`; refactoring tools over functions with pattern parameters.","solutions":["Replace the destructured parameter with a single named parameter, then rename it to self.","Destructure inside the function body instead (bind the parameter to a name, then `let (a, b) = param;`).","Rename the binding to a non-self identifier."],"exampleFix":"// before\nfn f((a, b): (i32, i32)) {} // rename a -> self: error\n// after\nfn f(x: (i32, i32)) { let (a, b) = x; } // rename x -> self ok\n","handlingStrategy":"validation","validationCode":"// Destructured first parameters cannot become self\n// (e.g. `fn f((a, b): (i32, i32))`) - check the param is a simple binding\nfn is_simple_binding(param_pattern: &str) -> bool {\n    param_pattern.chars().all(|c| c.is_alphanumeric() || c == '_' || c.is_whitespace())\n        && !param_pattern.trim().is_empty()\n}","typeGuard":null,"tryCatchPattern":"match rename(db, pos, \"self\", &config) {\n    Ok(change) => apply(change),\n    Err(e) if e.to_string().contains(\"rename_to_self invoked on destructuring parameter\") => {\n        prompt_user(\"Destructured parameters cannot be renamed to self\");\n    }\n    Err(e) => report(e),\n}","preventionTips":["Name the first parameter with a simple identifier instead of a pattern","Move destructuring into the function body via let bindings","Skip rename-to-self refactors when the param list contains pattern parameters"],"tags":["rust-analyzer","rename","self-parameter","pattern"],"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"}