Skip to content

Commit

Permalink
Updates workflows to use alloc and adds error when derive cannot use …
Browse files Browse the repository at this point in the history
…alloc.
  • Loading branch information
red1bluelost committed Jan 20, 2024
1 parent 547cde6 commit 4c008cb
Show file tree
Hide file tree
Showing 8 changed files with 81 additions and 72 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
- 1.56.0 # MSRV
features:
- ""
- --no-default-features
- --no-default-features --features alloc
- --features clippy

env:
Expand Down
4 changes: 2 additions & 2 deletions derive_builder/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ readme = "README.md"

[features]
default = ["std"]
std = []
std = ["derive_builder_macro/lib_has_std"]
clippy = ["derive_builder_macro/clippy"]
alloc = []
alloc = ["derive_builder_macro/alloc"]

[dependencies]
derive_builder_macro = { version = "=0.12.0", path = "../derive_builder_macro" }
Expand Down
2 changes: 2 additions & 0 deletions derive_builder_core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ license = "MIT OR Apache-2.0"
readme = "README.md"

[features]
alloc = []
clippy = []
lib_has_std = []

[dependencies]
darling = "0.14.0"
Expand Down
140 changes: 71 additions & 69 deletions derive_builder_core/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ use BuilderPattern;
use DeprecationNotes;
use Setter;

const ALLOC_NOT_ENABLED_ERROR: &str = r#"`alloc` is disabled within 'derive_builder', consider one of the following:
* enable feature `alloc` on 'dervie_builder' if a `global_allocator` is present
* use a custom error `#[builder(build_fn(error = "path::to::Error"))]
* disable the validation error `#[builder(build_fn(error(validation_error = false)))]"#;

/// Builder, implementing `quote::ToTokens`.
///
/// # Examples
Expand Down Expand Up @@ -135,6 +140,8 @@ pub struct Builder<'a> {
/// This would be `false` when `build_fn.error.as_validation_error() == Some((false, _))`. This
/// has no effect when `generate_error` is `false`.
pub generate_validation_error: bool,
/// Indicator of `cfg!(not(any(feature = "alloc", feature = "std")))`, as a field for tests
pub no_alloc: bool,
/// Whether this builder must derive `Clone`.
///
/// This is true even for a builder using the `owned` pattern if there is a field whose setter
Expand Down Expand Up @@ -233,7 +240,10 @@ impl<'a> ToTokens for Builder<'a> {
));
}

if self.generate_error {
if self.no_alloc && self.generate_error && self.generate_validation_error {
let err = syn::Error::new_spanned(&self.ident, ALLOC_NOT_ENABLED_ERROR);
tokens.append_all(err.to_compile_error());
} else if self.generate_error {
let builder_error_ident = format_ident!("{}Error", builder_ident);
let builder_error_doc = format!("Error type for {}", builder_ident);

Expand Down Expand Up @@ -385,6 +395,7 @@ macro_rules! default_builder {
functions: vec![quote!(fn bar() -> { unimplemented!() })],
generate_error: true,
generate_validation_error: true,
no_alloc: false,
must_derive_clone: true,
doc_comment: None,
deprecation_notes: DeprecationNotes::default(),
Expand All @@ -400,6 +411,43 @@ mod tests {
use proc_macro2::TokenStream;
use syn::Ident;

fn add_simple_foo_builder(result: &mut TokenStream) {
#[cfg(not(feature = "clippy"))]
result.append_all(quote!(#[allow(clippy::all)]));

result.append_all(quote!(
#[derive(Clone)]
pub struct FooBuilder {
foo: u32,
}
));

#[cfg(not(feature = "clippy"))]
result.append_all(quote!(#[allow(clippy::all)]));

result.append_all(quote!(
#[allow(dead_code)]
impl FooBuilder {
fn bar () -> {
unimplemented!()
}

/// Create an empty builder, with all fields set to `None` or `PhantomData`.
fn create_empty() -> Self {
Self {
foo: ::db::export::core::default::Default::default(),
}
}
}

impl ::db::export::core::default::Default for FooBuilder {
fn default() -> Self {
Self::create_empty()
}
}
));
}

fn add_generated_error(result: &mut TokenStream) {
result.append_all(quote!(
#[doc="Error type for FooBuilder"]
Expand Down Expand Up @@ -446,40 +494,7 @@ mod tests {
{
let mut result = quote!();

#[cfg(not(feature = "clippy"))]
result.append_all(quote!(#[allow(clippy::all)]));

result.append_all(quote!(
#[derive(Clone)]
pub struct FooBuilder {
foo: u32,
}
));

#[cfg(not(feature = "clippy"))]
result.append_all(quote!(#[allow(clippy::all)]));

result.append_all(quote!(
#[allow(dead_code)]
impl FooBuilder {
fn bar () -> {
unimplemented!()
}

/// Create an empty builder, with all fields set to `None` or `PhantomData`.
fn create_empty() -> Self {
Self {
foo: ::db::export::core::default::Default::default(),
}
}
}

impl ::db::export::core::default::Default for FooBuilder {
fn default() -> Self {
Self::create_empty()
}
}
));
add_simple_foo_builder(&mut result);

add_generated_error(&mut result);

Expand Down Expand Up @@ -797,40 +812,7 @@ mod tests {
{
let mut result = quote!();

#[cfg(not(feature = "clippy"))]
result.append_all(quote!(#[allow(clippy::all)]));

result.append_all(quote!(
#[derive(Clone)]
pub struct FooBuilder {
foo: u32,
}
));

#[cfg(not(feature = "clippy"))]
result.append_all(quote!(#[allow(clippy::all)]));

result.append_all(quote!(
#[allow(dead_code)]
impl FooBuilder {
fn bar () -> {
unimplemented!()
}

/// Create an empty builder, with all fields set to `None` or `PhantomData`.
fn create_empty() -> Self {
Self {
foo: ::db::export::core::default::Default::default(),
}
}
}

impl ::db::export::core::default::Default for FooBuilder {
fn default() -> Self {
Self::create_empty()
}
}
));
add_simple_foo_builder(&mut result);

result.append_all(quote!(
#[doc="Error type for FooBuilder"]
Expand Down Expand Up @@ -860,6 +842,26 @@ mod tests {

result
}
.to_string()
);
}

#[test]
fn no_alloc_bug_using_string() {
let mut builder = default_builder!();
builder.no_alloc = true;

assert_eq!(
quote!(#builder).to_string(),
{
let mut result = quote!();

add_simple_foo_builder(&mut result);

result.append_all(quote!(compile_error! { #ALLOC_NOT_ENABLED_ERROR }));

result
}
.to_string()
);
}
Expand Down
1 change: 1 addition & 0 deletions derive_builder_core/src/macro_options/darling_opts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -803,6 +803,7 @@ impl Options {
.as_ref()
.and_then(BuildFnError::as_validation_error)
.map_or(true, |(b, _)| b),
no_alloc: cfg!(not(any(feature = "alloc", feature = "lib_has_std"))),
must_derive_clone: self.requires_clone(),
doc_comment: None,
deprecation_notes: Default::default(),
Expand Down
2 changes: 2 additions & 0 deletions derive_builder_macro/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ readme = "README.md"
proc-macro = true

[features]
alloc = ["derive_builder_core/alloc"]
clippy = ["derive_builder_core/clippy"]
lib_has_std = ["derive_builder_core/lib_has_std"]

[dependencies]
syn = { version = "1.0.91", features = ["full", "extra-traits"] }
Expand Down
1 change: 1 addition & 0 deletions derive_builder_no_alloc_tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ edition = "2018"
publish = false

[features]
alloc = [] # To satify workflows which set `alloc`
clippy = ["derive_builder/clippy"]

[dependencies]
Expand Down
1 change: 1 addition & 0 deletions derive_builder_no_std_tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ edition = "2018"
publish = false

[features]
alloc = [] # To satify workflows which set `alloc`
clippy = ["derive_builder/clippy"]

[dependencies]
Expand Down

0 comments on commit 4c008cb

Please sign in to comment.