简体   繁体   中英

Is there a way to have a function for a implementation for a struct that moves self instead of borrowing it as &self or &mut self?

I have been dealing with this because I want to create a style of configuration that is somewhat of functional as it would be used like:

struct.set_config(myConfig)
      .set_other_config(myOtherConfig)

And to do this I need to return a owned version of the struct or another type that is similar to it in my case.

And to do this I would actually need to borrow that into a implemented function of that struct. My thought would be that it would look something like:

impl MyStruct {
  fn set_config(self, ...) -> Self {
    (...do something with self)

    self // return the mutated self
  }
}

But when trying something similar to this the Rust compiler did not like that very much.

Is there any way to kind of implement this? Or at least another way to get what I want without this?

EDIT:

My problem with just adding "mut self" is the Rust compiler seemed to complain with a warning:

warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #35203 <https://github.com/rust-lang/rust/issues/35203>
    = note: `#[deny(patterns_in_fns_without_body)]` on by default

And I wanted to avoid that. This error originates in the trait that defines that function not in the implementation.

EDIT 2:

I am working on a Machine Learning crate and I have layers for a Model, there is a Layer trait and I want to have Initializers for instantiating the parameters depending on how the user wants to initialize them.

Another important thing is that I have a enum that can be all of the layers currently implemented in the crate, this enum has that same trait implemented and each method has a match for each possible type of Layer.

Currently in the crate, to define the layers for a model you currently need to do something like:

let layers = vec![
  Dense::new(...),
  TanH::new(...)
];

(The "new" method returns that enum that has all the implemented layers as variants)

I want to set the initializers (which are now a field of these layers's structs) as such:

let layers = vec![
  Dense::new(...).set_initializer(...),
  TanH::new(...)
];

Then the set_initializer would need to return that enum owning the Dense layer for example. Hence my problem.

The important part of my Layer trait definition would need to look like this:

pub trait Layer<'a> {
    (...)

    fn set_initializer(mut self, initializer: Initializer) -> ModelLayer<'a>; // This is the enum I mentioned

    (...)
}

The pattern_in_fns_without_body error triggers on mut self parameters in body-less function signatures. This includes functions without bodies in trait definitions.

All you need to do to resolve the error is change mut self to just self in your trait definition:

pub trait Layer<'a> {
    // ...

    fn set_initializer(self, initializer: Initializer) -> ModelLayer<'a>;

    // ...
}

This restriction only applies to body-less functions. Your actual trait implementation can still have the mut self if necessary:

impl<'a> Layer<'a> for SomeThing<'a> {
    // ...

    fn set_initializer(mut self, initializer: Initializer) -> ModelLayer<'a> {
        // ...
    }

    // ...
}

I'm not sure what version of Rust you're working with, but recent versions of the compiler have a hint recommending just that:

error: patterns aren't allowed in functions without bodies
 --> src/lib.rs:7:24
  |
7 |     fn set_initializer(mut self, initializer: Initializer) -> ModelLayer<'a>;
  |                        ^^^^^^^^ help: remove `mut` from the parameter: `self`
  |
  = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
  = note: for more information, see issue #35203 <https://github.com/rust-lang/rust/issues/35203>
  = note: `#[deny(patterns_in_fns_without_body)]` on by default

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM