Mehdi Akiki
Rust Failure Atlas / Language and diagnostics

RFA-474 · Case file with fixtures · Case 446 of 694 · Compiler evidence

A Local Rust Item Cannot Reuse an External Crate Name

External crate roots and local declarations share relevant module namespace space. Rename the domain item, alias an unusual dependency when justified, or remove obsolete extern syntax without obscuring which API a path selects.

Reviewed
Rust
Rust 1.98.1, edition 2024
Targets
all Rust targets
Profiles
dev, release, test

Direct answer

What this Rust failure means

Why it happens
Dependency roots are source-level names and the local type attempts to claim the same relevant module namespace entry.
First discriminating check
Preserve conventional dependency identity and rename the local concept by domain role unless a real package collision justifies a contained crate alias.

I imported the external core crate and declared a local struct core in the same module. Rust emitted E0260 because the local item conflicts with the crate's name.

The failing fixture uses deliberately poor struct casing to expose the rule. More realistic collisions involve crate names and local modules, aliases, or generated type names.

Crate roots are visible names

An external crate is not only an entry in Cargo metadata. It becomes a root used by source paths such as core::mem. A conflicting local declaration would make that first path segment ambiguous.

The E0260 explanation offers two repairs: rename the item or rename the crate import.

I decide based on which name is conventional and which is under local design control.

Prefer a domain name for the local item

The repaired fixture renames the zero-sized local type to CoreMarker. In real code, I would choose the specific concept the type represents.

Names such as ClientCore, Engine, or RuntimeState are easier to search than borrowing a broad dependency name. Rust's type naming conventions also make a struct's role visually clearer.

Renaming the local declaration usually has less ecosystem-wide cost than renaming a standard crate root.

Crate aliases can resolve unavoidable collisions

The extern-crate Reference permits as aliases. Cargo manifest dependency keys can also determine source crate names.

If two external packages publish the same library name or a migration needs two versions, an alias may be necessary. I make it stable and descriptive, then contain it within an adapter module.

I do not rename a familiar crate simply because a generated local module chose an overly generic name.

Edition 2024 usually avoids extern crate lines

Dependencies are normally supplied through the extern prelude in modern editions. An explicit extern crate core; may be removable.

But removing the line does not always mean a local core module is a good idea: it can still shadow the conventional crate path and confuse imports. I evaluate source clarity beyond whether E0260 disappears.

Special no_std, macro, and legacy-edition situations deserve their own verification.

Modules can create the same architectural confusion

A local mod serde or mod tokio may conflict with the reader's expectation that those names refer to dependencies, even if some scoped arrangement compiles. Qualified crate::serde versus ::serde rules and edition differences can become difficult to maintain.

I reserve well-known crate names for those crates and name local adapters serde_support or tokio_runtime by role.

This reduces mistakes in generated paths and documentation examples.

The namespace Reference separates types, values, macros, lifetimes, and labels. A tuple struct can introduce both type and value entries; a module occupies the type namespace.

When a collision appears inconsistent, I list every namespace entry introduced by each declaration. The item kind often explains why one same-name pair is allowed while another fails.

Generated code needs a reserved-name policy

Schemas may contain entities called core, std, crate, or the names of dependencies. A generator should normalise and reserve these identifiers before emitting modules and types.

I prefer a deterministic suffix based on role and preserve the original schema name in metadata. Waiting for rustc to report E0260 produces a technically correct but less helpful error far from the input model.

My E0260 checklist

When renaming the local item, I let compiler-assisted references update code but inspect string-based configuration, generated paths, documentation, and macro inputs separately. Rust name resolution cannot find those textual dependencies. A module name may also appear in tracing targets or serialized tags even when it is not meant as stable data. I decide which strings are API and which should follow the code rename, then add a compatibility mapping where external consumers depend on the old spelling.

  • Which external crate owns the existing root name?
  • What local declaration attempts to reuse it?
  • Is the explicit extern declaration required in this edition?
  • Which name is conventional and which is locally controllable?
  • Would a role-based local name improve architecture?
  • Is a crate alias necessary for a real dependency collision?
  • Does a local module shadow a familiar ecosystem path?
  • Should a generator reserve dependency and keyword names?

The core principle is that dependency names participate in the source namespace. I preserve their identity and give local concepts domain-specific names, using aliases only when the dependency graph truly requires another stable root.