fix(macros): only take an integer type from repr in the Type derive - #4403
fix(macros): only take an integer type from repr in the Type derive#4403LckyLke wants to merge 1 commit into
repr in the Type derive#4403Conversation
|
|
||
| // A `repr` without an integer type does not make a weak enum | ||
| #[derive(Debug, PartialEq, sqlx::Type)] | ||
| #[repr(C)] |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Since it didn't even compile before, forbidding #[repr(C)] is a backwards compatible change.
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)]producedMyEnum::Variant as Cand bounds likeC: Encode<'q, DB>, which do not compile.The derive now only accepts an integer type from
repr:i8toi128,u8tou128,isize, andusize. Markers such asC,transparent, andpackedare ignored. An enum with only#[repr(C)]is therefore a strong enum, mapped by variant name, the same as an enum without anyrepr. For an enum without fields that is the only formrepr(C)can take, because Rust rejectsrepr(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 integerrepr.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: