diff --git a/bindgen-integration/build.rs b/bindgen-integration/build.rs index 7021f865d7..2a0763b0b7 100644 --- a/bindgen-integration/build.rs +++ b/bindgen-integration/build.rs @@ -128,6 +128,8 @@ impl ParseCallbacks for MacroCallback { vec!["PartialEq".into()] } else if info.name == "MyOrderedEnum" { vec!["std::cmp::PartialOrd".into()] + } else if info.name == "TestDeriveOnAlias" { + vec!["std::cmp::PartialEq".into(), "std::cmp::PartialOrd".into()] } else { vec![] } @@ -193,6 +195,7 @@ fn setup_macro_test() { .blocklist_function("my_prefixed_function_to_remove") .constified_enum("my_prefixed_enum_to_be_constified") .opaque_type("my_prefixed_templated_foo") + .new_type_alias("TestDeriveOnAlias") .depfile(out_rust_file_relative.display().to_string(), &out_dep_file) .generate() .expect("Unable to generate bindings"); diff --git a/bindgen-integration/cpp/Test.h b/bindgen-integration/cpp/Test.h index eee1974cbc..81a921b5f8 100644 --- a/bindgen-integration/cpp/Test.h +++ b/bindgen-integration/cpp/Test.h @@ -241,3 +241,6 @@ enum MyOrderedEnum { METER, LIGHTYEAR, }; + +// Used to test custom derives on new-type alias. See `test_custom_derive`. +typedef int TestDeriveOnAlias; diff --git a/bindgen-integration/src/lib.rs b/bindgen-integration/src/lib.rs index 04f6a5c9de..e234477080 100755 --- a/bindgen-integration/src/lib.rs +++ b/bindgen-integration/src/lib.rs @@ -289,6 +289,13 @@ fn test_custom_derive() { assert!(meter < lightyear); assert!(meter > micron); + + // The `add_derives` callback should have added `#[derive(PartialEq, PartialOrd)]` + // to the `TestDeriveOnAlias` new-type alias. If it didn't, this will fail to compile. + let test1 = unsafe { bindings::TestDeriveOnAlias(5) }; + let test2 = unsafe { bindings::TestDeriveOnAlias(6) }; + assert!(test1 < test2); + assert!(!(test1 > test2)); } #[test] diff --git a/bindgen/codegen/mod.rs b/bindgen/codegen/mod.rs index b126a847b4..902e49a4e4 100644 --- a/bindgen/codegen/mod.rs +++ b/bindgen/codegen/mod.rs @@ -1022,10 +1022,20 @@ impl CodeGenerator for Type { let packed = false; // Types can't be packed in Rust. let derivable_traits = derives_of_item(item, ctx, packed); - if !derivable_traits.is_empty() { - let derives: Vec<_> = derivable_traits.into(); - attributes.push(attributes::derives(&derives)) - } + let mut derives: Vec<_> = derivable_traits.into(); + // The custom derives callback may return a list of derive attributes; + // add them to the end of the list. + let custom_derives = + ctx.options().all_callbacks(|cb| { + cb.add_derives(&DeriveInfo { + name: &name, + kind: DeriveTypeKind::Struct, + }) + }); + // 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())); + attributes.push(attributes::derives(&derives)); quote! { #( #attributes )*