rust-lang/rust · error
empty prefix in a simple import
Error message
empty prefix in a simple import
What it means
UseTree::ident() (ast.rs:3376) panics with expect("empty prefix in a simple import") when called on a Simple use tree with no rename whose prefix path has zero segments. The method contract is: it returns the trailing identifier of a simple import; for a glob or nested tree it panics with a different message. An empty prefix on a Simple tree means malformed AST.
Solutions
- Before calling .ident(), ensure the tree is Simple and prefix.segments is non-empty.
- If you construct UseTree nodes, always populate prefix with at least one segment for Simple imports.
- If this fires from rustc itself on real source, file an ICE with the minimized `use` statement.
- Switch to a method that does not assume a single identifier (handle Simple(rename), Glob, and Nested explicitly).
Example fix
// before
let name = use_tree.ident(); // panics if prefix is empty
// after
let name = match use_tree.kind {
UseTreeKind::Simple(Some(rename)) => rename,
UseTreeKind::Simple(None) => use_tree.prefix.segments
.last()
.expect("simple import needs a prefix segment").ident,
_ => panic!("ident() only valid for simple imports"),
}; Defensive patterns
Strategy: validation
Validate before calling
fn simple_ident_or_none(tree: &UseTree) -> Option<Ident> {
match tree.kind {
UseTreeKind::Simple(Some(rename)) => Some(rename),
UseTreeKind::Simple(None) => tree.prefix.segments.last().map(|s| s.ident),
_ => None,
}
} Type guard
fn is_simple_with_prefix(tree: &UseTree) -> bool {
matches!(tree.kind, UseTreeKind::Simple(_)) && !tree.prefix.segments.is_empty()
} Try / catch
let name = use_tree.prefix.segments.last()
.map(|s| s.ident)
.unwrap_or_else(|| panic!("empty prefix in a simple import at {:?}", use_tree.prefix.span)); Prevention
- Never call UseTree::ident() on a tree you did not construct; check kind and prefix.segments first.
- When building UseTree nodes, always give Simple imports at least one prefix segment.
- Handle Simple(rename), Simple(None), Glob, and Nested as distinct cases rather than assuming ident().
- If it fires from rustc on real source, file an ICE with the minimized `use` statement.
When it happens
Trigger: Programmatically constructing or lowering an ast::UseTree with UseTreeKind::Simple(None) and an empty prefix.segments, then calling .ident(); or a parser/resolver bug producing such a tree.
Common situations: Tooling or proc-macro-adjacent code that builds UseTree nodes synthetically; a malformed `use` statement; a bug in a frontend that strips the prefix path. Well-formed source never triggers this.
Related errors
- A receiver has been dropped, something panicked!
- alt layout should always work
- alt layout should have a niche like the regular one
- arg must exist for infer
- <bless error: Cannot find variable
AI-assisted analysis of rust-lang/rust@7088e4b63a (2026-08-10).
Data as JSON: /api/errors/7e3d10ecb6426454.
Report an issue: GitHub.
Appendix: source
Thrown at compiler/rustc_ast/src/ast.rs:3376
Glob(Span),
}
/// A tree of paths sharing common prefixes.
/// Used in `use` items both at top-level and inside of braces in import groups.
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct UseTree {
pub prefix: Path,
pub kind: UseTreeKind,
}
impl UseTree {
/// If the `UseTree` is just an identifier, return that.
/// Panics if it's a glob (`*`) or a nested use tree.
pub fn ident(&self) -> Ident {
match self.kind {
UseTreeKind::Simple(Some(rename)) => rename,
UseTreeKind::Simple(None) => {
self.prefix.segments.last().expect("empty prefix in a simple import").ident
}
_ => panic!("`UseTree::ident` can only be used on a simple import"),
}
}
/// Returns the full span from the start of the path to the
/// closing `}` or nested spans, `*` of glob spans or the end of the
/// identifier of simple spans.
pub fn span(&self) -> Span {
self.prefix.span.to(self.hi_span())
}
/// Returns the trailing element's span. So for a nested
/// span you get the entire `{}`-block, for a glob you
/// get the span of the `*` itself, and for simple use trees
/// you get the identifier to rename the import to or the full
/// path if no rename is specified.
pub fn hi_span(&self) -> Span {View on GitHub (pinned to 7088e4b63a)