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 thisView on GitHub (pinned to e8f7e90aa3)
Solutions
- Rename the user-defined item instead; builtin types cannot be renamed.
- To alias a builtin, introduce a type alias (`type MyInt = i32;`) manually.
- 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
- Check the resolved Definition kind before issuing a rename request.
- Hide the rename action in the UI when the cursor is on a primitive type token.
- Prefer introducing type aliases instead of attempting builtin renames.
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
- Cannot rename a builtin attr.
- Cannot rename `Self`
- Invalid name `{0}`: cannot rename module to {0}
- Invalid name `{}`: not a lifetime identifier
- Invalid name `{}`: not an identifier
AI-assisted analysis of rust-lang/rust-analyzer@e8f7e90aa3 (2026-09-03).
Data as JSON: /api/errors/0e3a6164d6e8eb7a.
Report an issue: GitHub.