{"record":{"id":"cc9e26621beeef43","repo":"rust-lang/cargo","slug":"cannot-mix-proc-macro-crate-type-with-others","errorCode":null,"errorMessage":"cannot mix `proc-macro` crate type with others","messagePattern":"cannot mix `proc-macro` crate type with others","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/workspace/parser/targets.rs","lineNumber":258,"sourceCode":"    // A plugin requires exporting plugin_registrar so a crate cannot be\n    // both at once.\n    let crate_types = match (lib.crate_types(), lib.proc_macro()) {\n        (Some(kinds), _)\n            if kinds.contains(&CrateType::Dylib.as_str().to_owned())\n                && kinds.contains(&CrateType::Cdylib.as_str().to_owned()) =>\n        {\n            anyhow::bail!(format!(\n                \"library `{}` cannot set the crate type of both `dylib` and `cdylib`\",\n                name_or_panic(lib)\n            ));\n        }\n        (Some(kinds), _) if kinds.contains(&\"proc-macro\".to_string()) => {\n            warnings.push(format!(\n                \"library `{}` should only specify `proc-macro = true` instead of setting `crate-type`\",\n                name_or_panic(lib)\n            ));\n            if kinds.len() > 1 {\n                anyhow::bail!(\"cannot mix `proc-macro` crate type with others\");\n            }\n            vec![CrateType::ProcMacro]\n        }\n        (Some(kinds), _) => kinds.iter().map(|s| s.into()).collect(),\n        (None, Some(true)) => vec![CrateType::ProcMacro],\n        (None, _) => vec![CrateType::Lib],\n    };\n\n    let mut target = Target::lib_target(name_or_panic(lib), crate_types, path, edition);\n    configure(lib, &mut target, TARGET_KIND_HUMAN_LIB, warnings)?;\n    target.set_name_inferred(original_lib.map_or(true, |v| v.name.is_none()));\n    Ok(Some(target))\n}\n\n#[tracing::instrument(skip_all)]\npub fn normalize_bins(\n    toml_bins: Option<&Vec<TomlBinTarget>>,\n    package_root: &Path,","sourceCodeStart":240,"sourceCodeEnd":276,"githubUrl":"https://github.com/rust-lang/cargo/blob/eb98b54bc9f3c74519f43d066cb3fd02ebc88df0/src/workspace/parser/targets.rs#L240-L276","documentation":"When `crate-type` contains `proc-macro`, it must be the sole entry. A proc-macro crate must export only `#[proc_macro_derive]`/`#[proc_macro_attribute]` items at the crate root and cannot coexist with other crate types. The match arm at targets.rs:257-259 emits a warning suggesting `proc-macro = true`, then bails if `kinds.len() > 1`.","triggerScenarios":"Cargo.toml has `[lib] crate-type = [\"proc-macro\", \"rlib\"]` or any list where `proc-macro` appears alongside another type. The `if kinds.len() > 1` check inside the proc-macro arm fires.","commonSituations":"Trying to ship a proc-macro and a normal library from the same crate. Migrating from `proc-macro = true` to explicit crate-type and leaving extra entries. IDE/template scaffolding that pre-fills multiple crate types.","solutions":["Replace `crate-type = [\"proc-macro\", ...]` with the boolean `proc-macro = true` (the recommended form).","If you must use `crate-type`, list only `[\"proc-macro\"]`.","Move non-macro code into a separate companion crate."],"exampleFix":"# before\n[lib]\ncrate-type = [\"proc-macro\", \"rlib\"]\n\n# after\n[lib]\nproc-macro = true","handlingStrategy":"validation","validationCode":"fn proc_macro_mixed(crate_types: &[String]) -> bool {\n    crate_types.iter().any(|t| t == \"proc-macro\") && crate_types.len() > 1\n}\n// prefer `[lib] proc-macro = true` over explicit crate-type","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use `proc-macro = true` instead of `crate-type = [\"proc-macro\"]`.","Never list `proc-macro` alongside other crate types.","Keep proc-macro crates focused solely on macros."],"tags":["cargo","config","proc-macro","crate-type","manifest"],"backgroundTag":null,"analyzedSha":"eb98b54bc9f3c74519f43d066cb3fd02ebc88df0","analyzedAt":"2026-08-11T17:42:36.556Z","contentChangedAt":"2026-08-11T17:42:36.556Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}