{"id":"80ac4bbfa39f95e7","repo":"rust-lang/rust","slug":"unexpected-external-source-src","errorCode":null,"errorMessage":"Unexpected external source {src:?}","messagePattern":"Unexpected external source (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"compiler/rustc_metadata/src/rmeta/encoder.rs","lineNumber":319,"sourceCode":"        // In `encode_source_map`, we serialize foreign `SourceFile`s into our metadata\n        // if we're a proc-macro crate.\n        // This allows us to avoid loading the dependencies of proc-macro crates: all of\n        // the information we need to decode `Span`s is stored in the proc-macro crate.\n        let (kind, metadata_index) = if source_file.is_imported() && !s.is_proc_macro {\n            // To simplify deserialization, we 'rebase' this span onto the crate it originally came\n            // from (the crate that 'owns' the file it references. These rebased 'lo' and 'hi'\n            // values are relative to the source map information for the 'foreign' crate whose\n            // 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;","sourceCodeStart":301,"sourceCodeEnd":337,"githubUrl":"https://github.com/rust-lang/rust/blob/22057b88b091743bc0fd8d592a9264f0a6951403/compiler/rustc_metadata/src/rmeta/encoder.rs#L301-L337","documentation":"While encoding a span, rustc_metadata checks whether the span's `SourceFile` is imported (foreign). For foreign files it reads `source_file.external_src` expecting the `ExternalSource::Foreign { metadata_index, .. }` variant; any other variant (e.g. `Local`, `Absent`, or not-yet-loaded) triggers `panic!(\"Unexpected external source {src:?}\")`. This invariant — imported file must have a resolved foreign metadata index — is asserted at encoder.rs:319.","triggerScenarios":"Encoding metadata for a crate whose span references a `SourceFile` flagged `is_imported()` (foreign) but whose `external_src` has not been populated with `ExternalSource::Foreign { .. }` — e.g. the foreign crate's source map was never loaded/encoded, or the proc-macro fast path was taken incorrectly.","commonSituations":"An internal rustc change that marks a source file imported without wiring up the foreign source map encoding. Building a proc-macro crate where `is_proc_macro` interaction with `is_imported()` misroutes the file into the foreign branch. Span/source-map refactoring that leaves `external_src` in `Local`/`Absent` state at encode time.","solutions":["If you hit this as a user (not hacking rustc), it is a compiler ICE — run `cargo clean` and rebuild; if it reproduces, file a rustc issue with the `RUST_BACKTRACE=1` output.","For rustc hackers: ensure the foreign `SourceFile`'s `external_src` is populated to `ExternalSource::Foreign { metadata_index, source_map }` before encoding spans, or that `is_proc_macro` correctly routes imported files through the local encode_source_map path.","Audit recent changes to `SourceFile::is_imported` / `encode_source_map` / proc-macro handling to find the missing population of `external_src`."],"exampleFix":"// Conceptual fix in rustc_metadata source-map wiring:\n// before: file marked imported but external_src left as Local/Absent\n// after:  populate external_src before span encoding\n//\n// source_file.external_src = RwLock::new(ExternalSource::Foreign {\n//     metadata_index,\n//     source_map: foreign_source_map.clone(),\n// });","handlingStrategy":"validation","validationCode":"// The encoder panics on a source kind it doesn't recognise\n// ('Unexpected external source'). If you are feeding sources into the encoder\n// (e.g. a custom build hook or a proc-macro that emits rmeta), validate the\n// source kind against the allow-list BEFORE encoding.\n#[derive(Debug)]\nenum SourceKind { Crate, Dependency, ExternalCrate /* … */ }\n\nfn is_known_source(src: &SourceKind) -> bool {\n    matches!(src, SourceKind::Crate | SourceKind::Dependency\n        | SourceKind::ExternalCrate)\n}\n\n// Pre-check every source you hand the encoder:\nfor src in &sources {\n    if !is_known_source(src) {\n        return Err(format!(\"unexpected external source {src:?}; refusing to encode\"));\n    }\n }","typeGuard":"// Narrow the source to a known variant before passing to the encoder.\nenum EncoderSource {\n    Local,\n    ExternPreloaded,\n    ExternMacros,\n}\n\nfn classify(src: &SourceKind) -> Option<EncoderSource> {\n    match src {\n        SourceKind::Crate        => Some(EncoderSource::Local),\n        SourceKind::Dependency   => Some(EncoderSource::ExternPreloaded),\n        SourceKind::ExternalCrate=> Some(EncoderSource::ExternMacros),\n        _ => None,\n    }\n}\n\nif let Some(kind) = classify(&src) { encoder.encode_source(kind); }","tryCatchPattern":null,"preventionTips":["Only feed source kinds the encoder documents — anything else is an internal rustc bug, not a user path.","If you hit this, the cause is almost always a mismatched rustc_internal / rustc_data_structures version in your fork; rebuild against a consistent toolchain.","File a rustc issue with the `SourceKind` debug print — the panic message exists precisely so unidentified kinds get reported."],"tags":["rustc-metadata","rmeta","encoder","source-map","span","ice"],"analyzedSha":"22057b88b091743bc0fd8d592a9264f0a6951403","analyzedAt":"2026-08-03T08:09:25.915Z","schemaVersion":2}