{"id":"62bee8bc1630b241","repo":"rust-lang/cargo","slug":"returned-early","errorCode":null,"errorMessage":"returned early","messagePattern":"returned early","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/ops/cargo_fix/mod.rs","lineNumber":556,"sourceCode":"    {\n        fixes += rename_target_fields_2024(target);\n    }\n    fixes\n}\n\nfn rename_target_fields_2024(target: &mut dyn toml_edit::TableLike) -> usize {\n    let mut fixes = 0;\n    fixes += rename_table(target, \"crate_type\", \"crate-type\");\n    fixes += rename_table(target, \"proc_macro\", \"proc-macro\");\n    fixes\n}\n\nfn rename_table(parent: &mut dyn toml_edit::TableLike, old: &str, new: &str) -> usize {\n    let Some(old_key) = parent.key(old).cloned() else {\n        return 0;\n    };\n\n    let project = parent.remove(old).expect(\"returned early\");\n    if !parent.contains_key(new) {\n        parent.insert(new, project);\n        let mut new_key = parent.key_mut(new).expect(\"just inserted\");\n        *new_key.dotted_decor_mut() = old_key.dotted_decor().clone();\n        *new_key.leaf_decor_mut() = old_key.leaf_decor().clone();\n    }\n    1\n}\n\nfn check_resolver_change<'gctx>(\n    ws: &Workspace<'gctx>,\n    target_data: &mut RustcTargetData<'gctx>,\n    opts: &FixOptions,\n) -> CargoResult<()> {\n    let root = ws.root_maybe();\n    match root {\n        MaybePackage::Package(root_pkg) => {\n            if root_pkg.manifest().resolve_behavior().is_some() {","sourceCodeStart":538,"sourceCodeEnd":574,"githubUrl":"https://github.com/rust-lang/cargo/blob/0e07a155371a6ce88ae53a2c00df940280c09a67/src/ops/cargo_fix/mod.rs#L538-L574","documentation":"This panic is in rename_table(), a helper used by cargo fix to rename deprecated manifest fields during edition migration (e.g., crate_type -> crate-type, proc_macro -> proc-macro). On line 552 it checks parent.key(old).cloned() and returns 0 early if None. On line 556 it calls parent.remove(old).expect(\"returned early\") — since the key existed at line 552, remove should return the value.","triggerScenarios":"Migrating a Cargo.toml with deprecated field names (crate_type, proc_macro) where the key exists for the .key() check but is removed by the time .remove() is called. This requires concurrent mutation of the TOML document between the two calls — effectively impossible in single-threaded cargo fix execution.","commonSituations":"Running cargo fix --edition on a manifest with crate_type or proc_macro fields; essentially unreachable unless there is a re-entrant edit to the same toml_edit document or a bug in toml_edit's key/remove consistency.","solutions":["Manually rename the deprecated fields in Cargo.toml before running cargo fix (crate_type -> crate-type, proc_macro -> proc-macro).","Re-run cargo fix — if it was a transient issue it won't recur.","Update cargo to the latest version to get the newest edition-migration logic."],"exampleFix":"# before (deprecated field name in Cargo.toml)\n[lib]\ncrate_type = [\"cdylib\"]\n# after (rename to kebab-case)\n[lib]\ncrate-type = [\"cdylib\"]","handlingStrategy":"validation","validationCode":"// Before cargo fix --edition, rename deprecated fields manually\n// Check for crate_type / proc_macro in Cargo.toml\nlet content = std::fs::read_to_string(\"Cargo.toml\")?;\nfor deprecated in [\"crate_type\", \"proc_macro\"] {\n    if content.contains(deprecated) {\n        eprintln!(\"warning: found deprecated field `{}`; rename to `{}`\", deprecated, deprecated.replace('_', \"-\"));\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Manually rename deprecated manifest fields before running cargo fix --edition.","Always use kebab-case for Cargo.toml field names.","Run cargo check on manifests before edition migration."],"tags":["rust","cargo","panic","invariant","cargo-fix","edition-migration","manifest"],"analyzedSha":"0e07a155371a6ce88ae53a2c00df940280c09a67","analyzedAt":"2026-08-06T01:46:58.334Z","schemaVersion":2}