rust-lang/rust-analyzer · error

Cannot rename `Self`

Error message

Cannot rename `Self`

What it means

`Definition::rename` refuses to rename `Definition::SelfType`. `Self` is a keyword-like alias for the implementing type, not a real name in scope; rewriting its occurrences would require changing the underlying type's name instead. The library bails rather than silently doing nothing or producing wrong edits.

Solutions

  1. Resolve the impl target type and rename that type definition instead of `Self`.
  2. Use find-references on `Self` to locate the impl, then rename the concrete type.
  3. Filter out `Definition::SelfType(_)` in the caller before dispatching to rename.

Example fix

// before
// rename `Self` directly -> error
// after: rename the implementing type
let ty = impl_self_ty(sema); // resolve SelfType to Foo
if let Some(adt_def) = ty.as_adt() {
    Definition::from(adt_def).rename(sema, "NewFoo", ...)?;
}
Defensive patterns

Strategy: validation

Validate before calling

if matches!(def, Definition::SelfType(_)) {
    return Err(anyhow!("rename the implementing type instead of `Self`"));
}

Type guard

fn is_self_type(def: &Definition) -> bool {
    matches!(def, Definition::SelfType(_))
}

Try / catch

match def.rename(sema, new_name, ...) {
    Err(e) if e.to_string().contains("Cannot rename `Self`") => redirect_to_impl_target_rename(),
    other => other?,
}

Prevention

When it happens

Trigger: Calling `Definition::rename` (crates/ide-db/src/rename.rs:119) on a definition resolved to `SelfType`, e.g. placing the cursor on `Self` in `impl Foo { fn new() -> Self }` and renaming.

Common situations: Developer invokes rename on `Self` inside an impl block or trait definition and the IDE returns this error instead of a workspace edit.

Related errors


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

Appendix: source

Thrown at crates/ide-db/src/rename.rs:119

                bail!("Cannot rename a non-local definition")
            }
            krate.edition(sema.db)
        } else {
            Edition::LATEST
        };

        match *self {
            Definition::Module(module) => rename_mod(sema, module, new_name),
            Definition::ToolModule(_) => {
                bail!("Cannot rename a tool module")
            }
            Definition::BuiltinType(_) => {
                bail!("Cannot rename builtin type")
            }
            Definition::BuiltinAttr(_) => {
                bail!("Cannot rename a builtin attr.")
            }
            Definition::SelfType(_) => bail!("Cannot rename `Self`"),
            Definition::Macro(mac) => rename_reference(
                sema,
                Definition::Macro(mac),
                new_name,
                rename_definition,
                edition,
                config,
            ),
            def => rename_reference(sema, def, new_name, rename_definition, edition, config),
        }
    }

    /// Textual range of the identifier which will change when renaming this
    /// `Definition`. Note that builtin types can't be
    /// renamed and extern crate names will report its range, though a rename will introduce
    /// an alias instead.
    pub fn range_for_rename(self, sema: &Semantics<'_, RootDatabase>) -> Option<FileRange> {
        let syn_ctx_is_root = |(range, ctx): (_, SyntaxContext)| ctx.is_root().then_some(range);

View on GitHub (pinned to e8f7e90aa3)