From ec8456bd74026bf5a0f1ff530b8fa36d893c2933 Mon Sep 17 00:00:00 2001 From: Alexey Zabelin Date: Sat, 16 Sep 2017 18:41:34 -0400 Subject: [PATCH] Add --no-partialeq flag - [x] Add a new RegexSet member to bindgen::Builder (similar to the whitelisted_types set). - [x] A Builder method to add strings to that RegexSet. - [x] Plumbing in src/options.rs to convert --no-partialeq CLI flags into invocations of the builder method. - [x] Make the MonotoneFramework::constrain function in src/ir/analysis/derive_partialeq.rs check if the given item is explicitly marked not to be Partialeq, and if so, insert it into the self.cannot_derive_partialeq set via return self.insert(id). - [x] Tests! - [x] When the no-partialeq type is transitively referenced by a whitelisted item - [x] When the no-partialeq type is explicitly whitelisted - [x] When the no-partialeq type is marked opaque Fixes #965 --- .../derive_partial_eq_or_partial_ord.rs | 4 ++ src/ir/context.rs | 6 ++ src/lib.rs | 27 ++++++++ src/options.rs | 13 ++++ .../expectations/tests/no-partialeq-opaque.rs | 29 +++++++++ .../tests/no-partialeq-whitelisted.rs | 39 ++++++++++++ ...hitelisted-item-references-no-partialeq.rs | 62 +++++++++++++++++++ tests/headers/no-partialeq-opaque.hpp | 5 ++ tests/headers/no-partialeq-whitelisted.hpp | 5 ++ ...itelisted-item-references-no-partialeq.hpp | 7 +++ 10 files changed, 197 insertions(+) create mode 100644 tests/expectations/tests/no-partialeq-opaque.rs create mode 100644 tests/expectations/tests/no-partialeq-whitelisted.rs create mode 100644 tests/expectations/tests/whitelisted-item-references-no-partialeq.rs create mode 100644 tests/headers/no-partialeq-opaque.hpp create mode 100644 tests/headers/no-partialeq-whitelisted.hpp create mode 100644 tests/headers/whitelisted-item-references-no-partialeq.hpp diff --git a/src/ir/analysis/derive_partial_eq_or_partial_ord.rs b/src/ir/analysis/derive_partial_eq_or_partial_ord.rs index 876477abb8..1d4a5939ee 100644 --- a/src/ir/analysis/derive_partial_eq_or_partial_ord.rs +++ b/src/ir/analysis/derive_partial_eq_or_partial_ord.rs @@ -128,6 +128,10 @@ impl<'ctx> MonotoneFramework for CannotDerivePartialEqOrPartialOrd<'ctx> { } }; + if self.ctx.no_partialeq_by_name(&item) { + return self.insert(id) + } + trace!("ty: {:?}", ty); if item.is_opaque(self.ctx, &()) { let layout_can_derive = ty.layout(self.ctx).map_or(true, |l| { diff --git a/src/ir/context.rs b/src/ir/context.rs index 513cc665ef..6a87ee8ee0 100644 --- a/src/ir/context.rs +++ b/src/ir/context.rs @@ -2205,6 +2205,12 @@ impl BindgenContext { // float or not. self.has_float.as_ref().unwrap().contains(id) } + + /// Check if `--no-partialeq` flag is enabled for this item. + pub fn no_partialeq_by_name(&self, item: &Item) -> bool { + let name = item.canonical_path(self)[1..].join("::"); + self.options().no_partialeq_types.matches(&name) + } } /// A builder struct for configuring item resolution options. diff --git a/src/lib.rs b/src/lib.rs index 727704113c..dcef26272b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -500,6 +500,20 @@ impl Builder { output_vector.push(path.into()); } + self.options + .no_partialeq_types + .get_items() + .iter() + .map(|item| { + output_vector.push("--no-partialeq".into()); + output_vector.push( + item.trim_left_matches("^") + .trim_right_matches("$") + .into(), + ); + }) + .count(); + output_vector } @@ -1105,6 +1119,13 @@ impl Builder { )) } } + + /// Don't derive `PartialEq` for a given type. Regular + /// expressions are supported. + pub fn no_partialeq(mut self, arg: String) -> Builder { + self.options.no_partialeq_types.insert(arg); + self + } } /// Configuration options for generated bindings. @@ -1279,7 +1300,11 @@ struct BindgenOptions { /// The absolute path to the rustfmt configuration file, if None, the standard rustfmt /// options are used. + rustfmt_configuration_file: Option, + + /// The set of types that we should not derive `PartialEq` for. + no_partialeq_types: RegexSet, } /// TODO(emilio): This is sort of a lie (see the error message that results from @@ -1297,6 +1322,7 @@ impl BindgenOptions { self.bitfield_enums.build(); self.constified_enum_modules.build(); self.rustified_enums.build(); + self.no_partialeq_types.build(); } /// Update rust target version @@ -1365,6 +1391,7 @@ impl Default for BindgenOptions { time_phases: false, rustfmt_bindings: false, rustfmt_configuration_file: None, + no_partialeq_types: Default::default(), } } } diff --git a/src/options.rs b/src/options.rs index b3182270ca..957f17a287 100644 --- a/src/options.rs +++ b/src/options.rs @@ -265,6 +265,13 @@ where .takes_value(true) .multiple(false) .number_of_values(1), + Arg::with_name("no-partialeq") + .long("no-partialeq") + .help("Avoid deriving PartialEq for types matching .") + .value_name("regex") + .takes_value(true) + .multiple(true) + .number_of_values(1), ]) // .args() .get_matches_from(args); @@ -537,6 +544,12 @@ where builder = builder.rustfmt_configuration_file(Some(path)); } + if let Some(no_partialeq) = matches.values_of("no-partialeq") { + for regex in no_partialeq { + builder = builder.no_partialeq(String::from(regex)); + } + } + let verbose = matches.is_present("verbose"); Ok((builder, output, verbose)) diff --git a/tests/expectations/tests/no-partialeq-opaque.rs b/tests/expectations/tests/no-partialeq-opaque.rs new file mode 100644 index 0000000000..8fd5451fb3 --- /dev/null +++ b/tests/expectations/tests/no-partialeq-opaque.rs @@ -0,0 +1,29 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] + + +#[repr(C)] +#[derive(Debug, Default, Copy)] +pub struct NoPartialEq { + pub _bindgen_opaque_blob: u32, +} +#[test] +fn bindgen_test_layout_NoPartialEq() { + assert_eq!( + ::std::mem::size_of::(), + 4usize, + concat!("Size of: ", stringify!(NoPartialEq)) + ); + assert_eq!( + ::std::mem::align_of::(), + 4usize, + concat!("Alignment of ", stringify!(NoPartialEq)) + ); +} +impl Clone for NoPartialEq { + fn clone(&self) -> Self { + *self + } +} diff --git a/tests/expectations/tests/no-partialeq-whitelisted.rs b/tests/expectations/tests/no-partialeq-whitelisted.rs new file mode 100644 index 0000000000..f07864cea8 --- /dev/null +++ b/tests/expectations/tests/no-partialeq-whitelisted.rs @@ -0,0 +1,39 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] + + +#[repr(C)] +#[derive(Debug, Default, Copy)] +pub struct NoPartialEq { + pub i: ::std::os::raw::c_int, +} +#[test] +fn bindgen_test_layout_NoPartialEq() { + assert_eq!( + ::std::mem::size_of::(), + 4usize, + concat!("Size of: ", stringify!(NoPartialEq)) + ); + assert_eq!( + ::std::mem::align_of::(), + 4usize, + concat!("Alignment of ", stringify!(NoPartialEq)) + ); + assert_eq!( + unsafe { &(*(0 as *const NoPartialEq)).i as *const _ as usize }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(NoPartialEq), + "::", + stringify!(i) + ) + ); +} +impl Clone for NoPartialEq { + fn clone(&self) -> Self { + *self + } +} diff --git a/tests/expectations/tests/whitelisted-item-references-no-partialeq.rs b/tests/expectations/tests/whitelisted-item-references-no-partialeq.rs new file mode 100644 index 0000000000..a7bbab74a1 --- /dev/null +++ b/tests/expectations/tests/whitelisted-item-references-no-partialeq.rs @@ -0,0 +1,62 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] + + +#[repr(C)] +#[derive(Debug, Default, Copy)] +pub struct NoPartialEq { + pub _address: u8, +} +#[test] +fn bindgen_test_layout_NoPartialEq() { + assert_eq!( + ::std::mem::size_of::(), + 1usize, + concat!("Size of: ", stringify!(NoPartialEq)) + ); + assert_eq!( + ::std::mem::align_of::(), + 1usize, + concat!("Alignment of ", stringify!(NoPartialEq)) + ); +} +impl Clone for NoPartialEq { + fn clone(&self) -> Self { + *self + } +} +#[repr(C)] +#[derive(Debug, Default, Copy)] +pub struct WhitelistMe { + pub a: NoPartialEq, +} +#[test] +fn bindgen_test_layout_WhitelistMe() { + assert_eq!( + ::std::mem::size_of::(), + 1usize, + concat!("Size of: ", stringify!(WhitelistMe)) + ); + assert_eq!( + ::std::mem::align_of::(), + 1usize, + concat!("Alignment of ", stringify!(WhitelistMe)) + ); + assert_eq!( + unsafe { &(*(0 as *const WhitelistMe)).a as *const _ as usize }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(WhitelistMe), + "::", + stringify!(a) + ) + ); +} +impl Clone for WhitelistMe { + fn clone(&self) -> Self { + *self + } +} diff --git a/tests/headers/no-partialeq-opaque.hpp b/tests/headers/no-partialeq-opaque.hpp new file mode 100644 index 0000000000..a5a03cd287 --- /dev/null +++ b/tests/headers/no-partialeq-opaque.hpp @@ -0,0 +1,5 @@ +// bindgen-flags: --with-derive-partialeq --opaque-type "NoPartialEq" --no-partialeq "NoPartialEq" + +class NoPartialEq { + int i; +}; diff --git a/tests/headers/no-partialeq-whitelisted.hpp b/tests/headers/no-partialeq-whitelisted.hpp new file mode 100644 index 0000000000..dba4e91f76 --- /dev/null +++ b/tests/headers/no-partialeq-whitelisted.hpp @@ -0,0 +1,5 @@ +// bindgen-flags: --with-derive-partialeq --whitelist-type "NoPartialEq" --no-partialeq "NoPartialEq" + +class NoPartialEq { + int i; +}; diff --git a/tests/headers/whitelisted-item-references-no-partialeq.hpp b/tests/headers/whitelisted-item-references-no-partialeq.hpp new file mode 100644 index 0000000000..d9d3d4311f --- /dev/null +++ b/tests/headers/whitelisted-item-references-no-partialeq.hpp @@ -0,0 +1,7 @@ +// bindgen-flags: --with-derive-partialeq --whitelist-type "WhitelistMe" --no-partialeq "NoPartialEq" + +struct NoPartialEq {}; + +class WhitelistMe { + NoPartialEq a; +};