Skip to content

rustc suggest adding "ref" before trait in derive attribute #122919

Closed
@Wasabi375

Description

@Wasabi375

Code

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

Current output

error[E0382]: borrow of partially moved value: `self`
 --> src/main.rs:9:25
  |
5 | #[derive(Builder)]
  |          ------- value partially moved here
...
9 |     #[builder(default = "self.calc_b()")]
  |                         ^^^^^^^^^^^^^^^ value borrowed here after partial move
  |
  = note: partial move occurs because value has type `V`, which does not implement the `Copy` trait
help: borrow this binding in the pattern to avoid moving the value
  |
5 | #[derive(ref Builder)]
  |          +++

Desired output

error[E0382]: borrow of partially moved value: `self`
 --> src/main.rs:9:25
  |
5 | #[derive(Builder)]
  |          ------- value partially moved here
...
9 |     #[builder(default = "self.calc_b()")]
  |                         ^^^^^^^^^^^^^^^ value borrowed here after partial move
  |
  = note: partial move occurs because value has type `V`, which does not implement the `Copy` trait

Rationale and extra context

I encountered the error while using the rust-dervie-builder crate. The above code is invalid as explained in this issue here: colin-kiegel/rust-derive-builder#298
Basically the expansion of this derive macro leads to self being referenced after a partial move.
The first part of the error message is correct. The suggested fix however is just wrong.

For context, the expansion of the relevant code is the following

struct FooBuilder {
    a: ::derive_builder::export::core::option::Option<V>,
    b: ::derive_builder::export::core::option::Option<V>,
}
impl FooBuilder {
    fn build(
        self,
    ) -> ::derive_builder::export::core::result::Result<Foo, FooBuilderError> {
        Ok(Foo {
            a: match self.a {
                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,
                None => self.calc_b(),
            },
        })
    }
}

Other cases

No response

Rust Version

rustc 1.77.0 (aedd173a2 2024-03-17)
binary: rustc
commit-hash: aedd173a2c086e558c2b66d3743b344f977621a7
commit-date: 2024-03-17
host: x86_64-unknown-linux-gnu
release: 1.77.0
LLVM version: 17.0.6

Anything else?

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lintsD-invalid-suggestionDiagnostics: A structured suggestion resulting in incorrect code.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions