Skip to content

fix(macros): only take an integer type from repr in the Type derive - #4403

Open
LckyLke wants to merge 1 commit into
transact-rs:mainfrom
LckyLke:fix/type-derive-ignore-non-integer-repr
Open

fix(macros): only take an integer type from repr in the Type derive#4403
LckyLke wants to merge 1 commit into
transact-rs:mainfrom
LckyLke:fix/type-derive-ignore-non-integer-repr

Conversation

@LckyLke

@LckyLke LckyLke commented Sep 6, 2026

Copy link
Copy Markdown

Fixes #4366.

#[derive(sqlx::Type)] reads the enum's #[repr(...)] to find the integer type of a weak enum. It took the first plain identifier in the list, so #[repr(C)] produced MyEnum::Variant as C and bounds like C: Encode<'q, DB>, which do not compile.

The derive now only accepts an integer type from repr: i8 to i128, u8 to u128, isize, and usize. Markers such as C, transparent, and packed are ignored. An enum with only #[repr(C)] is therefore a strong enum, mapped by variant name, the same as an enum without any repr. For an enum without fields that is the only form repr(C) can take, because Rust rejects repr(C) combined with an integer repr on such enums.

A side effect is that a struct with a non-integer repr, for example #[repr(transparent)] on a #[sqlx(transparent)] newtype, no longer fails with "unexpected #[repr(..)]". That check only makes sense for an integer repr.

Added two cases to tests/sqlite/derives.rs: a #[repr(C)] enum round-trips as text, and a #[repr(transparent)] transparent struct round-trips as an integer. Ran with:

DATABASE_URL=sqlite://$PWD/tests/sqlite/sqlite.db cargo test --no-default-features --features sqlite,macros,runtime-tokio --test sqlite-derives

Comment thread tests/sqlite/derives.rs

// A `repr` without an integer type does not make a weak enum
#[derive(Debug, PartialEq, sqlx::Type)]
#[repr(C)]

@abonander abonander Sep 9, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I would prefer to forbid #[repr(C)] because it's ambiguous what the enum should map to.

This test assumes these enums should map to a string. However, some users may actually expect us to apply the C-like enum rules and map this to an integer. I don't think that's particularly unreasonable, actually. The real problem is that the actual integer type is defined per-target, so we'd have to encode all those rules and validate them. But then you'd potentially get a different type on various platforms when you're presumably trying to map that to the same schema type.

That's a lot of technical debt for a rather niche feature.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since it didn't even compile before, forbidding #[repr(C)] is a backwards compatible change.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

repr(C) breaks sqlx::Type on enums

2 participants