Skip to content

Gcc codegen backend fails to compile diesel #848

Closed

Description

@weiznich

To put this upfront: I'm well aware that the gcc backend is nowhere near to be production ready. I'm mostly filling this bug to let you know, not to get this fixed soon.

I tried this code:

git clone https://github.com/diesel-rs/diesel
cd diesel
git checkout 70d1fc8a519ed69d5783d98592fe8d4731b82aef
# without gcc codegen it works
cargo +nightly build -p diesel_cli --no-default-features -F sqlite-bundled
# with gcc codegen it fails
CARGO_PROFILE_DEV_CODEGEN_BACKEND=gcc cargo +nightly build -Zcodegen-backend -p diesel_cli --no-default-features -F sqlite-bundled

I expected to see this happen: Compilation succeeds

Instead, this happened: Compilation fails with the following error

error: unexpected token: `{`
  --> dsl_auto_type/src/auto_type/mod.rs:30:10
   |
30 | #[derive(darling::FromMeta)]
   |          ^^^^^^^^^^^^^^^^^
   |
   = note: this error originates in the derive macro `darling::FromMeta` (in Nightly builds, run with -Z macro-backtrace for more info)

error: unexpected token: `=`
  --> dsl_auto_type/src/auto_type/mod.rs:30:10
   |
30 | #[derive(darling::FromMeta)]
   |          ^^^^^^^^^^^^^^^^^
   |
   = note: this error originates in the derive macro `darling::FromMeta` (in Nightly builds, run with -Z macro-backtrace for more info)

error: unexpected token: `.`
  --> dsl_auto_type/src/auto_type/mod.rs:30:10
   |
30 | #[derive(darling::FromMeta)]
   |          ^^^^^^^^^^^^^^^^^
   |
   = note: this error originates in the derive macro `darling::FromMeta` (in Nightly builds, run with -Z macro-backtrace for more info)

error: proc-macro derive produced unparsable tokens
  --> dsl_auto_type/src/auto_type/mod.rs:30:10
   |
30 | #[derive(darling::FromMeta)]
   |          ^^^^^^^^^^^^^^^^^

error[E0600]: cannot apply unary operator `!` to type `(bool, Option<Option<syn::Path>>)`
  --> dsl_auto_type/src/auto_type/mod.rs:30:10
   |
30 | #[derive(darling::FromMeta)]
   |          ^^^^^^^^^^^^^^^^^ cannot apply unary operator `!`
   |
   = note: this error originates in the derive macro `darling::FromMeta` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0600]: cannot apply unary operator `!` to type `(bool, Option<Flag>)`
  --> dsl_auto_type/src/auto_type/mod.rs:30:10
   |
30 | #[derive(darling::FromMeta)]
   |          ^^^^^^^^^^^^^^^^^ cannot apply unary operator `!`
   |
   = note: this error originates in the derive macro `darling::FromMeta` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0600]: cannot apply unary operator `!` to type `(bool, Option<Option<proc_macro2::Ident>>)`
  --> dsl_auto_type/src/auto_type/mod.rs:30:10
   |
30 | #[derive(darling::FromMeta)]
   |          ^^^^^^^^^^^^^^^^^ cannot apply unary operator `!`
   |
   = note: this error originates in the derive macro `darling::FromMeta` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0600]: cannot apply unary operator `!` to type `(bool, Option<Option<SpannedValue<String>>>)`
  --> dsl_auto_type/src/auto_type/mod.rs:30:10
   |
30 | #[derive(darling::FromMeta)]
   |          ^^^^^^^^^^^^^^^^^ cannot apply unary operator `!`
   |
   = note: this error originates in the derive macro `darling::FromMeta` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0061]: this function takes 1 argument but 0 arguments were supplied
   --> dsl_auto_type/src/auto_type/mod.rs:30:10
    |
 30 | #[derive(darling::FromMeta)]
    |          ^^^^^^^^^^^^^^^^^ argument rust-lang/rust#1 of type `&str` is missing
    |
note: associated function defined here
   --> /home/weiznich/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/darling_core-0.21.3/src/error/mod.rs:164:12
    |
164 |     pub fn unsupported_format(format: &str) -> Self {
    |            ^^^^^^^^^^^^^^^^^^
    = note: this error originates in the derive macro `darling::FromMeta` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0308]: mismatched types
  --> dsl_auto_type/src/auto_type/mod.rs:30:10
   |
30 | #[derive(darling::FromMeta)]
   |          ^^^^^^^^^^^^^^^^^
   |          |
   |          expected `(bool, Option<Option<Path>>)`, found `Option<Option<Path>>`
   |          expected due to this type
   |
   = note: expected tuple `(bool, Option<Option<syn::Path>>)`
               found enum `Option<Option<syn::Path>>`
   = note: this error originates in the derive macro `darling::FromMeta` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0308]: mismatched types
  --> dsl_auto_type/src/auto_type/mod.rs:30:10
   |
30 | #[derive(darling::FromMeta)]
   |          ^^^^^^^^^^^^^^^^^
   |          |
   |          expected `(bool, Option<Flag>)`, found `Option<Flag>`
   |          expected due to this type
   |
   = note: expected tuple `(bool, Option<Flag>)`
               found enum `Option<Flag>`
   = note: this error originates in the derive macro `darling::FromMeta` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0308]: mismatched types
  --> dsl_auto_type/src/auto_type/mod.rs:30:10
   |
30 | #[derive(darling::FromMeta)]
   |          ^^^^^^^^^^^^^^^^^
   |          |
   |          expected `(bool, Option<Option<Ident>>)`, found `Option<Option<Ident>>`
   |          expected due to this type
   |
   = note: expected tuple `(bool, Option<Option<proc_macro2::Ident>>)`
               found enum `Option<Option<proc_macro2::Ident>>`
   = note: this error originates in the derive macro `darling::FromMeta` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0308]: mismatched types
  --> dsl_auto_type/src/auto_type/mod.rs:30:10
   |
30 | #[derive(darling::FromMeta)]
   |          ^^^^^^^^^^^^^^^^^
   |          |
   |          expected `(bool, Option<Option<...>>)`, found `Option<Option<SpannedValue<String>>>`
   |          expected due to this type
   |
   = note: expected tuple `(bool, Option<Option<SpannedValue<String>>>)`
               found enum `Option<Option<SpannedValue<String>>>`
   = note: this error originates in the derive macro `darling::FromMeta` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0599]: no method named `expect` found for tuple `(bool, Option<Option<syn::Path>>)` in the current scope
  --> dsl_auto_type/src/auto_type/mod.rs:30:10
   |
30 | #[derive(darling::FromMeta)]
   |          ^^^^^^^^^^^^^^^^^ method not found in `(bool, Option<Option<syn::Path>>)`
   |
   = note: this error originates in the derive macro `darling::FromMeta` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0599]: no method named `expect` found for tuple `(bool, Option<Flag>)` in the current scope
  --> dsl_auto_type/src/auto_type/mod.rs:30:10
   |
30 | #[derive(darling::FromMeta)]
   |          ^^^^^^^^^^^^^^^^^ method not found in `(bool, Option<Flag>)`
   |
   = note: this error originates in the derive macro `darling::FromMeta` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0599]: no method named `expect` found for tuple `(bool, Option<Option<proc_macro2::Ident>>)` in the current scope
  --> dsl_auto_type/src/auto_type/mod.rs:30:10
   |
30 | #[derive(darling::FromMeta)]
   |          ^^^^^^^^^^^^^^^^^ method not found in `(bool, Option<Option<proc_macro2::Ident>>)`
   |
   = note: this error originates in the derive macro `darling::FromMeta` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0599]: no method named `expect` found for tuple `(bool, Option<Option<SpannedValue<String>>>)` in the current scope
  --> dsl_auto_type/src/auto_type/mod.rs:30:10
   |
30 | #[derive(darling::FromMeta)]
   |          ^^^^^^^^^^^^^^^^^ method not found in `(bool, Option<Option<SpannedValue<String>>>)`
   |
   = note: this error originates in the derive macro `darling::FromMeta` (in Nightly builds, run with -Z macro-backtrace for more info)

If that's helpful: dsl_auto_type is a local proc-macro crate

Meta

rustc --version --verbose:

rustc 1.95.0-nightly (474276961 2026-01-26)
binary: rustc
commit-hash: 474276961f48b0d05f4ea260ba400096b027584e
commit-date: 2026-01-26
host: x86_64-unknown-linux-gnu
release: 1.95.0-nightly
LLVM version: 21.1.8

Activity

  1. mysma-9403 commented on Jan 27, 2026

    @mysma-9403

    Hi!

    I tried to look into this and I believe the root issue is that the GCC backend is being used to compile the proc-macro crate itself (dsl_auto_type / darling), not just the main diesel_cli binary. If I'm reading the code correctly, this is what's happening:

    Why proc-macros are affected

    CARGO_PROFILE_DEV_CODEGEN_BACKEND=gcc sets the backend globally — there's no mechanism in rustc to use one backend for proc-macros and another for regular crates. The backend is selected once per rustc invocation in get_codegen_backend and used for all codegen.

    The GCC backend inherits the default supported_crate_types() implementation, which includes CrateType::ProcMacro — so Cargo doesn't know to exclude proc-macro crates from the GCC backend. It happily compiles them with GCC.

    What I think goes wrong

    The error pattern strongly suggests that the proc-macro runs but produces incorrect output:

    error: proc-macro derive produced unparsable tokens
    

    This means:

    1. The GCC backend compiled the darling proc-macro crate (a dylib)
    2. The compiled proc-macro was loaded and executed during diesel_derives compilation
    3. The proc-macro ran, but the generated code was incorrect — likely due to a codegen bug in the GCC backend affecting the token stream construction inside darling
    4. The subsequent errors (unexpected {, type mismatches, missing methods) are all downstream from the broken proc-macro output

    If this theory is right, the issue isn't specific to diesel — any sufficiently complex proc-macro (like darling::FromMeta) would probably fail with the GCC backend.

    A quick way to confirm this

    It would help to check whether compiling only the final binary with the GCC backend (while letting proc-macros use LLVM) avoids the issue. I don't think Cargo supports this cleanly today — see cargo#13001 — but one could manually compile the proc-macro with the default backend and then use GCC only for the downstream crate.

    Possible directions

    Not sure which of these makes sense from the GCC backend perspective:

    1. Investigate the codegen bug — look at what darling / syn / proc_macro2 code path triggers incorrect codegen in the GCC backend. This is probably the right long-term fix but could be deep.

    2. Opt proc-macros out of the GCC backend — Cargo could force proc-macro crates to always use the default (LLVM) backend, similar to how it already ignores panic settings for proc-macros. This would be a Cargo-side change.

    3. Have the GCC backend not claim ProcMacro support — override supported_crate_types() in the GCC backend to exclude CrateType::ProcMacro until it's mature enough. This would cause Cargo to fall back to LLVM for proc-macro crates.

    Option 3 seems like the most pragmatic short-term fix if proc-macro codegen with GCC is known to be unreliable. But I'm not sure if there are cases where it already works fine and this would be a regression.

    Does this analysis seem right, or am I misunderstanding how Cargo selects the backend for proc-macro crates?

  2. bjorn3 commented on Jan 27, 2026

    @bjorn3
    Member

    If proc macros are not supported by cg_gcc, that is a bug.

    This would cause Cargo to fall back to LLVM for proc-macro crates.

    It doesn't. There is no such fallback behavior in cargo. supported_crate_types is only used to skip unsupported crate types when a single crate has multiple crate types as well as reporting an error before anything gets compiled for unsupported crate types.

  3. antoyo commented on Feb 12, 2026

    @antoyo
    Contributor

    This works when using a sysroot compiled by cg_gcc, so I suspect this is an ABI bug: we probably have some discrepancies with the LLVM ABI.
    I suspect it might be related to our wrong handling of sret: I'll try to get back to this in the coming months.
    I created issue #850 to add some CI to detect this.

    Thanks for reporting this issue.

  4. antoyo commented on Jun 1, 2026

    @antoyo
    Contributor

    This seems fixed now.
    @weiznich: Could you please confirm this works for you with the latest nightly?

  5. weiznich commented on Jun 3, 2026

    @weiznich
    Author

    I can confirm that this is now fixed 🎉. Thanks for your continuous work on this ❤️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions