{"record":{"id":"6666dcd017d81acf","repo":"rust-lang/rust-analyzer","slug":"syntaxcontext-as-id-called-on-a-root-syntaxc","errorCode":null,"errorMessage":"`SyntaxContext::as_id()` called on a root `SyntaxContext`","messagePattern":"`SyntaxContext::as_id\\(\\)` called on a root `SyntaxContext`","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/span/src/hygiene.rs","lineNumber":145,"sourceCode":"            D: zalsa_::serde::Deserializer<'de>,\n        {\n            unimplemented!(\"attempted to deserialize value that cannot set `PERSIST` to false\");\n        }\n    }\n\n    impl SyntaxContext {\n        pub fn ingredient(zalsa: &zalsa_::Zalsa) -> &zalsa_struct_::IngredientImpl<Self> {\n            static CACHE: zalsa_::IngredientCache<zalsa_struct_::IngredientImpl<SyntaxContext>> =\n                zalsa_::IngredientCache::new();\n\n            // SAFETY: The ingredient at offset 0 in `JarImpl<SyntaxContext>` has type\n            // `IngredientImpl<SyntaxContext>`.\n            unsafe { CACHE.get_or_create::<zalsa_struct_::JarImpl<SyntaxContext>, 0>(zalsa) }\n        }\n    }\n    impl zalsa_::AsId for SyntaxContext {\n        fn as_id(&self) -> salsa::Id {\n            self.as_salsa_id().expect(\"`SyntaxContext::as_id()` called on a root `SyntaxContext`\")\n        }\n    }\n    impl zalsa_::FromId for SyntaxContext {\n        fn from_id(id: salsa::Id) -> Self {\n            Self::from_salsa_id(id)\n        }\n    }\n    unsafe impl Send for SyntaxContext {}\n\n    unsafe impl Sync for SyntaxContext {}\n\n    impl zalsa_::SalsaStructInDb for SyntaxContext {\n        type MemoIngredientMap = salsa::plumbing::MemoIngredientSingletonIndex;\n        const LEAF_TYPE_IDS: &[salsa::plumbing::ConstTypeId] =\n            &[salsa::plumbing::ConstTypeId::of::<SyntaxContext>()];\n\n        fn lookup_ingredient_index(aux: &zalsa_::Zalsa) -> salsa::plumbing::IngredientIndices {\n            aux.lookup_jar_by_type::<zalsa_struct_::JarImpl<SyntaxContext>>().into()","sourceCodeStart":127,"sourceCodeEnd":163,"githubUrl":"https://github.com/rust-lang/rust-analyzer/blob/e8f7e90aa3e7b26aa9a000200f606c1078da99ec/crates/span/src/hygiene.rs#L127-L163","documentation":"SyntaxContext in rust-analyzer's span crate is backed by salsa; non-root contexts carry a salsa Id while the root context has none. The generated AsId impl calls as_salsa_id() and panics if called on the root SyntaxContext, since root has no underlying Id. This marks a misuse of the salsa ingredient API on the root sentinel value.","triggerScenarios":"Code path converts a SyntaxContext to its salsa Id (zalsa_::AsId) when that context is the root context — e.g. interning/lookup logic that failed to special-case the root and passed it into a salsa query or ingredient operation.","commonSituations":"rust-analyzer development: macro hygiene machinery calling salsa lookups with a default/root SyntaxContext instead of a real interned context; refactorings that lost the root check before invoking salsa APIs.","solutions":["Check the context for root before using it as a salsa key (e.g. `if ctx.is_root()` return early / use Option).","Update rust-analyzer — this indicates an internal hygiene bug fixed upstream.","If you control the call site, switch the API to handle Option<SyntaxContext> or a non-root guarantee explicitly.","Write a regression test where a macro expansion with root hygiene flows into the salsa query."],"exampleFix":"// before\nlet id = zalsa_::AsId::as_id(&ctx);\n// after\nlet id = if ctx.is_root() { None } else { Some(ctx.as_salsa_id().unwrap()) };","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"fn as_id_opt(ctx: &SyntaxContext) -> Option<salsa::Id> { ctx.as_salsa_id().ok() }","tryCatchPattern":"let Some(id) = ctx.as_salsa_id() else { return fallback_for_root(); };","preventionTips":["Special-case the root SyntaxContext before salsa interning/lookups","Prefer Option-returning helpers over expect on hygiene internals","Add regression tests for macro expansions with root hygiene"],"tags":["rust-analyzer","salsa","hygiene","internal-invariant"],"backgroundTag":"salsa-root-context-misuse","analyzedSha":"e8f7e90aa3e7b26aa9a000200f606c1078da99ec","analyzedAt":"2026-09-03T21:08:06.959Z","contentChangedAt":"2026-09-03T21:08:06.959Z","schemaVersion":2},"datasetVersion":"2026-09-11T07:07:21.782Z"}