Skip to content

Owned pattern does not compile with custom default function. #298

@Wasabi375

Description

@Wasabi375
struct V(u32);

#[derive(Builder)]
#[builder(pattern = "owned")]
struct Foo {
    a: V,
    #[builder(default = "self.calc_b()")]
    b: V,
}

impl FooBuilder {
    fn calc_b(&self) -> V {
        V(self.a.as_ref().unwrap().0 + 5)
    }
}

This fails to compile with

borrow of partially moved value: `self`
 --> src/lib.rs:9:25
  |
3 | #[derive(Builder)]
  |          ------- value partially moved here
...
7 |     #[builder(default = "self.calc_b()")]
  |                         ^^^^^^^^^^^^^^^ value borrowed here after partial move

Looking at cargo expand it's easy to see why:

fn build(
        self,
    ) -> ::derive_builder::export::core::result::Result<Foo, FooBuilderError> {
        Ok(Foo {
            a: match self.a {
                // partial move here
                Some(value) => value,
                None => {
                    return ::derive_builder::export::core::result::Result::Err(
                        ::derive_builder::export::core::convert::Into::into(
                            ::derive_builder::UninitializedFieldError::from("a"),
                        ),
                    );
                }
            },
            b: match self.b {
                Some(value) => value,
                // borrow after partial move here
                None => self.calc_b(),
            },
        })
    }

A possible fix would be to calculate custom default values before the match expression.
A small issue with that is, that the default value will be calculated even if not needed, but I don't think that is a big problem here and can be ignored, except for maybe mentioning it in the documentation.

I'd be willing to create a PR for this if this solution is acceptable.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions