diff --git a/derive_builder/src/lib.rs b/derive_builder/src/lib.rs index 43b4fcd..b2f1533 100644 --- a/derive_builder/src/lib.rs +++ b/derive_builder/src/lib.rs @@ -504,6 +504,11 @@ //! } //! ``` //! +//! The `Builder` will also automatically `derive(Clone)` in some cases. This may not always be +//! suitable if there are generic types involved. This may be suppressed using the +//! `suppress_derive_clone` attribute. The generated code may still need an `impl Clone for +//! Builder`; when using this attribute, it will need to be implemented in another way. +//! //! Attributes declared for those traits are _not_ forwarded to the fields on the builder. //! //! ## Documentation Comments and Attributes diff --git a/derive_builder/tests/compile-fail/suppress_derive_clone.rs b/derive_builder/tests/compile-fail/suppress_derive_clone.rs new file mode 100644 index 0000000..cc15c60 --- /dev/null +++ b/derive_builder/tests/compile-fail/suppress_derive_clone.rs @@ -0,0 +1,8 @@ +#[macro_use] +extern crate derive_builder; + +#[derive(Builder)] +#[builder(suppress_derive_clone)] +pub struct Example { + field: String, +} diff --git a/derive_builder/tests/manual_clone.rs b/derive_builder/tests/manual_clone.rs new file mode 100644 index 0000000..7f1ad2f --- /dev/null +++ b/derive_builder/tests/manual_clone.rs @@ -0,0 +1,40 @@ +#[macro_use] +extern crate derive_builder; + +#[derive(Debug, Builder, PartialEq, Clone)] +#[builder(suppress_derive_clone)] +struct Lorem { + #[builder(setter(into))] + ipsum: String, +} + +impl Clone for LoremBuilder { + fn clone(&self) -> Self { + Self { + ipsum: self.ipsum.clone(), + } + } +} + +#[test] +fn error_if_uninitialized() { + let error = LoremBuilder::default().build().unwrap_err(); + assert_eq!(&error.to_string(), "`ipsum` must be initialized"); +} + +#[test] +fn builder_test() { + let x = LoremBuilder::default().ipsum("ipsum").build().unwrap(); + + assert_eq!( + x, + Lorem { + ipsum: "ipsum".into() + } + ); +} + +#[test] +fn builder_is_clone() { + let _ = LoremBuilder::default().clone(); +} diff --git a/derive_builder_core/src/macro_options/darling_opts.rs b/derive_builder_core/src/macro_options/darling_opts.rs index aa0f650..b8fc78f 100644 --- a/derive_builder_core/src/macro_options/darling_opts.rs +++ b/derive_builder_core/src/macro_options/darling_opts.rs @@ -590,6 +590,11 @@ pub struct Options { #[darling(skip, default)] deprecation_notes: DeprecationNotes, + + /// Suppress the `derive(Clone)` attribute. + /// + /// If `Clone` is needed, it must be generated in some other way. + suppress_derive_clone: Flag, } /// Accessors for parsed properties. @@ -687,7 +692,7 @@ impl Options { .map(|e| *e.validation_error) .unwrap_or(true), no_alloc: cfg!(not(any(feature = "alloc", feature = "lib_has_std"))), - must_derive_clone: self.requires_clone(), + must_derive_clone: self.requires_clone() && !self.suppress_derive_clone.is_present(), doc_comment: None, deprecation_notes: Default::default(), std: !self.no_std.is_present(),