rust-lang/rust · critical
Attempted to encode LazyAttrTokenStream
Error message
Attempted to encode LazyAttrTokenStream
What it means
`panic!("Attempted to encode LazyAttrTokenStream")` is fired by the `Encodable` impl for `LazyAttrTokenStream`. The lazy stream holds parser-internal cursor state (snapshots, call counts, node replacements) that is intentionally non-serializable; it must be *forced* into a concrete `AttrTokenStream` before it can be encoded to incr-comp data or cached. The panic exists to catch serialization of un-forced lazy streams.
Source
Thrown at compiler/rustc_ast/src/tokenstream.rs:150
break_last_token,
node_replacements,
}))
}
pub fn to_attr_token_stream(&self) -> AttrTokenStream {
self.0.to_attr_token_stream()
}
}
impl fmt::Debug for LazyAttrTokenStream {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "LazyAttrTokenStream({:?})", self.to_attr_token_stream())
}
}
impl<S: SpanEncoder> Encodable<S> for LazyAttrTokenStream {
fn encode(&self, _s: &mut S) {
panic!("Attempted to encode LazyAttrTokenStream");
}
}
impl<D: SpanDecoder> Decodable<D> for LazyAttrTokenStream {
fn decode(_d: &mut D) -> Self {
panic!("Attempted to decode LazyAttrTokenStream");
}
}
impl StableHash for LazyAttrTokenStream {
fn stable_hash<Hcx: StableHashCtxt>(&self, _hcx: &mut Hcx, _hasher: &mut StableHasher) {
panic!("Attempted to compute stable hash for LazyAttrTokenStream");
}
}
/// A token range within a `Parser`'s full token stream.
#[derive(Clone, Debug)]
pub struct ParserRange(pub Range<u32>);View on GitHub (pinned to 22057b88b0)
Solutions
- Call `.to_attr_token_stream()` (or otherwise force) the `LazyAttrTokenStream` into a concrete `AttrTokenStream` before storing it in any `Encodable` structure.
- Audit the call site in the backtrace (`RUST_BACKTRACE=1`) to find which field still holds a `LazyAttrTokenStream` at serialization time, and force it at construction.
- Add a unit test that round-trips the affected AST node through `Encodable`/`Decodable` to prevent regression.
Example fix
// before attr_tokens: LazyAttrTokenStream::new(...) // later: encode fails // after attr_tokens: lazy.to_attr_token_stream() // forced before storage
Defensive patterns
Strategy: validation
Validate before calling
// LazyAttrTokenStream is intentionally non-Encodable. // Materialize to a real stream before encoding: let encodable: AttrTokenStream = lazy.to_attr_token_stream(); // then encode encodable instead
Type guard
fn is_lazy_stream<T>(_v: &T) -> bool { false } // types-other-than-LazyAttrTokenStream are safe Prevention
- Never run `Encodable::encode` on a `LazyAttrTokenStream`; the impl is a hard panic.
- Before any serialization pipeline, call `.to_attr_token_stream()` to force evaluation.
- If you must walk a token stream for hashing/encoding, work on `AttrTokenStream`, not its lazy variant.
When it happens
Trigger: Any `Encodable::encode` call (directly or via `rustc_serialize`, incremental compilation serialization, or query caching) on a value still typed as `LazyAttrTokenStream`. This happens when a token stream wasn't forced to `AttrTokenStream` before being placed in a serializable struct.
Common situations: Refactors that change when lazy streams are forced, regressions in attribute/macro token collection, or new query results that retain `LazyAttrTokenStream` past the parse phase. Typically surfaces as an ICE during incremental compilation or crate serialization.
Related errors
- Attempted to decode LazyAttrTokenStream
- Attempted to compute stable hash for LazyAttrTokenStream
- Unexpected last token {last_token:?}
- unreachable: invalid ExternAbi variant
- if we had an explicit self, we wouldn't be here
AI-assisted analysis of rust-lang/rust@22057b88b0 (2026-08-03).
Data as JSON: /data/errors/01479b1be1cf4a96.json.
Report an issue: GitHub.