rust-lang/rust-analyzer · error

Cannot rename builtin type

Error message

Cannot rename builtin type

What it means

rust_analyzer's `Definition::rename` refuses to rename any `Definition::BuiltinType` (e.g. `u32`, `bool`, `str`). Builtin types are provided by the language/core crate and have no single definitional site to rewrite, so every reference would be ambiguous. The library deliberately bails instead of producing an incorrect SourceChange.

Source

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

        // cases where self.krate() is None is handled below.
        let edition = if let Some(krate) = self.krate(sema.db) {
            // Can we not rename non-local items?
            // Then bail if non-local
            if !krate.origin(sema.db).is_local() {
                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

View on GitHub (pinned to e8f7e90aa3)

Solutions

  1. Rename the user-defined item instead; builtin types cannot be renamed.
  2. To alias a builtin, introduce a type alias (`type MyInt = i32;`) manually.
  3. In client code, check `matches!(def, Definition::BuiltinType(_))` before calling rename and surface a user-friendly message.

Example fix

// before (rename request on builtin)
definition.rename(sema, "i64", ...); // Err: Cannot rename builtin type
// after
if matches!(definition, Definition::BuiltinType(_)) {
    return; // skip rename, show "builtin types cannot be renamed"
}
definition.rename(sema, "i64", ...)?;
Defensive patterns

Strategy: validation

Validate before calling

fn can_rename(def: &Definition) -> bool {
    !matches!(def, Definition::BuiltinType(_) | Definition::BuiltinAttr(_) | Definition::SelfType(_) | Definition::ToolModule(_))
}

Type guard

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

Try / catch

match def.rename(sema, new_name, ...) {
    Err(e) if e.to_string().contains("Cannot rename builtin type") => eprintln!("builtin types cannot be renamed"),
    Err(e) => return Err(e),
    Ok(change) => apply(change),
}

Prevention

When it happens

Trigger: Calling `Definition::rename` (public API, crates/ide-db/src/rename.rs:114) on a definition resolved to a builtin type, e.g. when the user invokes rename on the `i32` token in `let x: i32 = 0;`.

Common situations: Cursor placed on a primitive type name in source code and the editor issues a `textDocument/rename` LSP request; IDE plugins resolving the token to `hir::Namespace`-style builtin types rather than a user item.

Related errors


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