Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

const fn doesn't work #84

Open
StackOverflowExcept1on opened this issue May 26, 2023 · 5 comments
Open

const fn doesn't work #84

StackOverflowExcept1on opened this issue May 26, 2023 · 5 comments

Comments

@StackOverflowExcept1on
Copy link

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
@idanarye
Copy link
Owner

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)].

@StackOverflowExcept1on
Copy link
Author

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
    }
}

@idanarye
Copy link
Owner

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.

@idanarye
Copy link
Owner

Due to the way I parse things, it's going to have to be #[builder(const_)] and not #[builder(const)].

@idanarye
Copy link
Owner

idanarye commented Jun 4, 2023

Problem - I can't implement this until const traits get stabilized (rust-lang/rust#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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants