{"id":"c9eb0780d1d8b8c1","repo":"rust-lang/rust","slug":"already-encoded-sourcemap","errorCode":null,"errorMessage":"Already encoded SourceMap!","messagePattern":"Already encoded SourceMap!","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"compiler/rustc_metadata/src/rmeta/encoder.rs","lineNumber":327,"sourceCode":"            // CrateNum we write into the metadata. This allows `imported_source_files` to binary\n            // search through the 'foreign' crate's source map information, using the\n            // deserialized 'lo' and 'hi' values directly.\n            //\n            // All of this logic ensures that the final result of deserialization is a 'normal'\n            // Span that can be used without any additional trouble.\n            let metadata_index = {\n                // Introduce a new scope so that we drop the 'read()' temporary\n                match &*source_file.external_src.read() {\n                    ExternalSource::Foreign { metadata_index, .. } => *metadata_index,\n                    src => panic!(\"Unexpected external source {src:?}\"),\n                }\n            };\n\n            (SpanKind::Foreign, metadata_index)\n        } else {\n            // Record the fact that we need to encode the data for this `SourceFile`\n            let source_files =\n                s.required_source_files.as_mut().expect(\"Already encoded SourceMap!\");\n            let (metadata_index, _) = source_files.insert_full(source_file_index);\n            let metadata_index: u32 =\n                metadata_index.try_into().expect(\"cannot export more than U32_MAX files\");\n\n            (SpanKind::Local, metadata_index)\n        };\n\n        // Encode the start position relative to the file start, so we profit more from the\n        // variable-length integer encoding.\n        let lo = self.lo - source_file.start_pos;\n\n        // Encode length which is usually less than span.hi and profits more\n        // from the variable-length integer encoding that we use.\n        let len = self.hi - self.lo;\n\n        let tag = SpanTag::new(kind, ctxt, len.0 as usize);\n        tag.encode(s);\n        if tag.context().is_none() {","sourceCodeStart":309,"sourceCodeEnd":345,"githubUrl":"https://github.com/rust-lang/rust/blob/22057b88b091743bc0fd8d592a9264f0a6951403/compiler/rustc_metadata/src/rmeta/encoder.rs#L309-L345","documentation":"During span encoding, local `SourceFile`s are registered into `EncodeContext::required_source_files` (an `IndexMap`) so each gets a stable metadata index. That map is `Option` and is taken/set to `None` once `encode_source_map` has already serialized the full SourceMap. If a later span encode then hits the local branch, `s.required_source_files.as_mut().expect(\"Already encoded SourceMap!\")` panics — a span was encoded after the source map was finalized.","triggerScenarios":"Calling into span encoding after `encode_source_map` has already consumed `required_source_files` (set it to `None`) — i.e. the encoding pipeline serialized the SourceMap before all spans referencing local files were encoded, or a code path encodes a span out-of-order.","commonSituations":"A rustc refactor that reorders metadata encoding so the SourceMap is finalized too early. Adding a new rmeta field that lazily encodes spans after `encode_source_map` runs. A proc-macro or incremental-compilation path that encodes spans during/after source-map finalization. For end users this manifests as an ICE.","solutions":["As a user: treat as an ICE — `cargo clean`, rebuild, and if reproducible report to rustc with `RUST_BACKTRACE=1`.","For rustc hackers: move `encode_source_map` to run strictly after all span-encoding sites, or refactor `required_source_files` so local files can be registered lazily even post-finalization (e.g. defer the `take()`).","Add an assertion/test that no `Span::encode` runs after `EncodeContext::encode_source_map`, and audit the call ordering in `encode_crate` for the offending late span encode."],"exampleFix":"// Conceptual ordering fix in rmeta encoder:\n// before: encode_source_map(...) runs, then a later span encode panics\n// after:  ensure ALL span-bearing structures are encoded first\n//\n// encode_all_definitions(&mut ec);   // encodes spans into required_source_files\n// encode_source_map(&mut ec);        // now safe to finalize + take()","handlingStrategy":"validation","validationCode":"// The encoder panics if SourceMap is encoded twice in one session\n// ('Already encoded SourceMap!'). Pre-track encoding state and refuse the\n// second call rather than letting the encoder panic.\nstruct EncoderState {\n    source_map_encoded: bool,\n}\n\nimpl EncoderState {\n    fn encode_source_map(&mut self) -> Result<(), &'static str> {\n        if self.source_map_encoded {\n            return Err(\"SourceMap already encoded; refusing duplicate pass\");\n        }\n        self.source_map_encoded = true;\n        Ok(())\n    }\n}\n\n// Call encode_source_map() exactly once per encoder; this guard makes the\n// contract explicit and the failure recoverable.","typeGuard":"// Use the type system to make double-encoding unrepresentable: encoding\n// the SourceMap consumes the encoder, returning a 'finalised' type with no\n// further source-map method.\nstruct OpenEncoder<'a> { /* ... */ }\nstruct FinalisedEncoder<'a> { /* ... */ }\n\nimpl<'a> OpenEncoder<'a> {\n    fn encode_source_map(self) -> FinalisedEncoder<'a> {\n        // encode once, then drop the open handle so it can't be called again\n        FinalisedEncoder { /* ... */ }\n    }\n}","tryCatchPattern":null,"preventionTips":["Treat SourceMap encoding as a one-shot: do it once, at the end of the encoder pass, from a single call site.","Drive encoding through a state machine (Open -> Finalised) so a second encode is a compile error, not a runtime panic.","If you fork rustc_metadata, add a debug_assert! at the call site that fails loudly in tests before production hits the panic."],"tags":["rustc-metadata","rmeta","encoder","source-map","span","ice"],"analyzedSha":"22057b88b091743bc0fd8d592a9264f0a6951403","analyzedAt":"2026-08-03T08:09:25.915Z","schemaVersion":2}