From 727367cbcc7cabdaacfea1510b8973fdc5560b73 Mon Sep 17 00:00:00 2001 From: Eric Seppanen Date: Sun, 7 Nov 2021 13:41:19 -0800 Subject: [PATCH] allow custom derives on enums Custom derives are just as useful on enums as they are on structs; not supporting this was an oversight. Adds a test that will fail to compile if the custom derive doesn't work on enums. This test fails without the codegen fix. --- bindgen-integration/build.rs | 4 ++++ bindgen-integration/cpp/Test.h | 7 +++++++ bindgen-integration/src/lib.rs | 10 ++++++++++ src/codegen/mod.rs | 10 ++++++++++ 4 files changed, 31 insertions(+) diff --git a/bindgen-integration/build.rs b/bindgen-integration/build.rs index fa0246c460..77ea64b581 100644 --- a/bindgen-integration/build.rs +++ b/bindgen-integration/build.rs @@ -126,6 +126,10 @@ impl ParseCallbacks for MacroCallback { vec![ "PartialEq".into(), ] + } else if name == "MyOrderedEnum" { + vec![ + "PartialOrd".into(), + ] } else { vec![] } diff --git a/bindgen-integration/cpp/Test.h b/bindgen-integration/cpp/Test.h index ad71b0f672..eee1974cbc 100644 --- a/bindgen-integration/cpp/Test.h +++ b/bindgen-integration/cpp/Test.h @@ -234,3 +234,10 @@ typedef union { } Coord; Coord coord(double x, double y, double z, double t); + +// Used to test custom derives on enum. See `test_custom_derive`. +enum MyOrderedEnum { + MICRON, + METER, + LIGHTYEAR, +}; diff --git a/bindgen-integration/src/lib.rs b/bindgen-integration/src/lib.rs index f56e72597d..43f71580d2 100755 --- a/bindgen-integration/src/lib.rs +++ b/bindgen-integration/src/lib.rs @@ -275,4 +275,14 @@ fn test_custom_derive() { let test1 = unsafe { bindings::Test::new(5) }; let test2 = unsafe { bindings::Test::new(6) }; assert_ne!(test1, test2); + + // The `add_derives` callback should have added `#[derive(PartialOrd)]` + // to the `MyOrderedEnum` enum. If it didn't, this will fail to compile. + + let micron = unsafe { bindings::MyOrderedEnum::MICRON }; + let meter = unsafe { bindings::MyOrderedEnum::METER }; + let lightyear = unsafe { bindings::MyOrderedEnum::LIGHTYEAR }; + + assert!(meter < lightyear); + assert!(meter > micron); } diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index 69dde2c580..b703a1064b 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -3014,6 +3014,16 @@ impl CodeGenerator for Enum { derives.push(derive); } } + + // The custom derives callback may return a list of derive attributes; + // add them to the end of the list. + let custom_derives; + if let Some(cb) = &ctx.options().parse_callbacks { + custom_derives = cb.add_derives(&name); + // In most cases this will be a no-op, since custom_derives will be empty. + derives.extend(custom_derives.iter().map(|s| s.as_str())); + }; + attrs.push(attributes::derives(&derives)); }