rust-typed-builder
rust-typed-builder copied to clipboard
`const fn` doesn't work
use typed_builder::TypedBuilder;
#[derive(TypedBuilder)]
struct Foo {
// Mandatory Field:
x: i32,
// #[builder(default)] without parameter - use the type's default
// #[builder(setter(strip_option))] - wrap the setter argument with `Some(...)`
#[builder(default, setter(strip_option))]
y: Option<i32>,
// Or you can set the default
#[builder(default=20)]
z: i32,
}
fn f() {
const X: Foo = Foo::builder().z(1).x(2).y(3).build();
}
fn main() {}
error[E0015]: cannot call non-const fn `Foo::builder` in constants
--> src/main.rs:19:20
|
19 | const X: Foo = Foo::builder().z(1).x(2).y(3).build();
| ^^^^^^^^^^^^^^
|
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot call non-const fn `FooBuilder::z` in constants
--> src/main.rs:19:35
|
19 | const X: Foo = Foo::builder().z(1).x(2).y(3).build();
| ^^^^
|
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
I can try adding a top-level #[builder(const)]
attribute to make all the generated functions const
. Keep in mind though that with the current version of Rust this example could never work, because Default::default
is not const
. So having a const
builder would forbid bare #[builder(default)]
s - the one for y
will have to change to #[builder(default = None)]
.
also there are some problems with const fn
:
struct Foo {
s: Option<String>,
}
impl Foo {
const fn new() -> Self {
Self { s: None }
}
const fn s(mut self, s: String) -> Self {
self.s = Some(s); //error[E0493]: destructor of `Option<String>` cannot be evaluated at compile-time
self
}
}
I don't think that'd be a problem. Typed builder's setters do not override fields, so they don't need to invoke destructors.
Due to the way I parse things, it's going to have to be #[builder(const_)]
and not #[builder(const)]
.
Problem - I can't implement this until const traits get stabilized (https://github.com/rust-lang/rust/issues/67792)
The issue is that I'm using traits in the build
method. Unset fields are represented as ()
and set fields as (T,)
, and I define a trait that allows me to return a default for the former and the contained value for the latter. With current stable Rust, the method from that trait cannot be const
.