{"id":"c1dd8547c724ee2d","repo":"rust-lang/rust","slug":"parent-should-be-delimited","errorCode":null,"errorMessage":"parent should be Delimited","messagePattern":"parent should be Delimited","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"compiler/rustc_ast/src/tokenstream.rs","lineNumber":1019,"sourceCode":"                    &TokenTree::Token(token, spacing) => {\n                        debug_assert!(!token.kind.is_delim());\n                        let res = (token, spacing);\n                        self.curr.bump();\n                        return res;\n                    }\n                    &TokenTree::Delimited(sp, spacing, delim, ref tts) => {\n                        let trees = TokenTreeCursor::new(tts.clone());\n                        self.stack.push(mem::replace(&mut self.curr, trees));\n                        if !delim.skip() {\n                            return (Token::new(delim.as_open_token_kind(), sp.open), spacing.open);\n                        }\n                        // No open delimiter to return; continue on to the next iteration.\n                    }\n                };\n            } else if let Some(parent) = self.stack.pop() {\n                // We have exhausted this token stream. Move back to its parent token stream.\n                let Some(&TokenTree::Delimited(span, spacing, delim, _)) = parent.curr() else {\n                    panic!(\"parent should be Delimited\")\n                };\n                self.curr = parent;\n                self.curr.bump(); // move past the `Delimited`\n                if !delim.skip() {\n                    return (Token::new(delim.as_close_token_kind(), span.close), spacing.close);\n                }\n                // No close delimiter to return; continue on to the next iteration.\n            } else {\n                // We have exhausted the outermost token stream. The use of\n                // `Spacing::Alone` is arbitrary and immaterial, because the\n                // `Eof` token's spacing is never used.\n                return (Token::new(token::Eof, DUMMY_SP), Spacing::Alone);\n            }\n        }\n    }\n}\n\n#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]","sourceCodeStart":1001,"sourceCodeEnd":1037,"githubUrl":"https://github.com/rust-lang/rust/blob/22057b88b091743bc0fd8d592a9264f0a6951403/compiler/rustc_ast/src/tokenstream.rs#L1001-L1037","documentation":"Panic inside TokenStream's cursor (inlined_next) when unwinding from a nested Delimited stream back to its parent: the parent frame on the stack is required to be a TokenTree::Delimited entry, because that is the only construct that pushes a child stream onto the cursor. Reaching a non-Delimited parent means the cursor stack discipline was corrupted — an internal compiler bug in token-stream traversal.","triggerScenarios":"Triggered only if the cursor's internal stack is in an inconsistent state, e.g. an explicitly constructed TokenStream whose nested Delimited frames do not match the push/pop discipline, or a proc-macro that builds a TokenStream by hand via internal APIs and feeds it to code that iterates with inlined_next. Cannot occur from streams produced by the normal parser.","commonSituations":"Custom tooling or fuzzers that synthesize TokenStream internals directly; rustc development regressions; hand-rolled token manipulation in nightly-only crates. End users compiling ordinary crates will not hit this.","solutions":["Report as an ICE on the rust-lang/rust tracker with a minimal repro and the rustc version.","If using internal token APIs to build a stream manually, ensure every child stream you push corresponds to a TokenTree::Delimited entry.","Roll back to a known-good nightly to confirm it is a recent regression.","Run under a debug rustc build to catch the corruption earlier in the cursor stack."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// The cursor panics if, after exhausting a child stream, the parent's\n// current tree is not a Delimited node. Validate cursor stack integrity\n// before calling next()/bump() across a nesting boundary.\nfn parent_is_delimited(cursor: &TokenTreeCursor) -> bool {\n    cursor.stack.iter().all(|parent| {\n        matches!(parent.curr(), Some(TokenTree::Delimited(..)))\n    })\n}\n// Only descend/ascend when the invariant holds:\nif !parent_is_delimited(&cursor) { return Err(\"token stream stack is corrupt: parent is not Delimited\"); }","typeGuard":"fn is_delimited(tt: &TokenTree) -> bool {\n    matches!(tt, TokenTree::Delimited(..))\n}","tryCatchPattern":"let item = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| cursor.next()));\nmatch item {\n    Ok((tok, spacing)) => (tok, spacing),\n    Err(_) => return Err(\"TokenTreeCursor.next() panicked: parent should be Delimited (corrupted stream)\"),\n}","preventionTips":["Do not splice hand-built TokenTree sequences into a Delimited group without matching open/close delimiters — a missing closer desynchronizes the cursor stack.","When flattening or rewriting token streams, always rebuild via TokenStream::new / Delimited so the nesting invariants hold; never mutate the inner Vec in place.","If you interleave TokenTreeCursor with manual stack pushes, assert that every pushed parent's current tree is Delimited before ascending.","Round-trip test any stream transformation through TokenStream -> ast -> TokenStream to catch nesting corruption early."],"tags":["rustc","ice","ast","tokenstream","cursor"],"analyzedSha":"22057b88b091743bc0fd8d592a9264f0a6951403","analyzedAt":"2026-08-03T08:09:25.915Z","schemaVersion":2}