我很不熟悉,一直坚持所有权主题。我以为可以,但是无法使函数中的Option<OutputPin>
可用。您能告诉我应该如何吗?
struct Chip {
wake_pin: Option<OutputPin>
}
impl Chip {
pub fn new(wake_pin: Option<Pin>) -> Chip {
Chip {
wake_pin: wake_pin.map(|pin| pin.into_output())
}
}
pub fn awake(&self) {
// Fails
if let Some(pin) = self.wake_pin {
pin.set_low();
}
}
}
fn main() {
let wake_pin = Gpio::new().expect("Can not init gpio")
.get(255).expect("Could not attach to wake pin");
let chip = Chip::new(Some(wake_pin));
}
我正在使用rppal板条箱,并且编译器在if let Some
区域中失败。我尝试借用了ake_pin,获得了作为参考的选项以及其他一些东西,但是直到现在我还没有完全理解所有权规则。
谢谢
我相信我已经复制了您的设置。如果有问题,请编辑您的问题以及相关详细信息。
src / main.rs:
use rppal::gpio::{Gpio, OutputPin, Pin};
struct Chip {
wake_pin: Option<OutputPin>,
}
impl Chip {
pub fn new(wake_pin: Option<Pin>) -> Chip {
Chip {
wake_pin: wake_pin.map(|pin| pin.into_output()),
}
}
pub fn awake(&self) {
// Fails
if let Some(pin) = self.wake_pin {
pin.set_low();
}
}
}
fn main() {
let wake_pin = Gpio::new()
.expect("Can not init gpio")
.get(255)
.expect("Could not attach to wake pin");
let chip = Chip::new(Some(wake_pin));
}
Cargo.toml:
[package]
name = "tmp"
version = "0.0.1"
edition = "2018"
[dependencies]
rppal = "0.11.3"
尝试编译此代码(使用cargo check
或类似的代码,我们得到一个警告和两个错误。
warning: unused variable: `chip`
--> src/main.rs:28:9
|
28 | let chip = Chip::new(Some(wake_pin));
| ^^^^ help: consider prefixing with an underscore: `_chip`
|
= note: `#[warn(unused_variables)]` on by default
error[E0507]: cannot move out of `self.wake_pin.0` which is behind a shared reference
--> src/main.rs:16:28
|
16 | if let Some(pin) = self.wake_pin {
| --- ^^^^^^^^^^^^^ help: consider borrowing here: `&self.wake_pin`
| |
| data moved here
| move occurs because `pin` has type `rppal::gpio::pin::OutputPin`, which does not implement the `Copy` trait
error[E0596]: cannot borrow `pin` as mutable, as it is not declared as mutable
--> src/main.rs:17:13
|
16 | if let Some(pin) = self.wake_pin {
| --- help: consider changing this to be mutable: `mut pin`
17 | pin.set_low();
| ^^^ cannot borrow as mutable
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0507, E0596.
For more information about an error, try `rustc --explain E0507`.
error: Could not compile `tmp`.
To learn more, run the command again with --verbose.
由于您可能稍后要使用chip
,因此可以通过暂时将其重命名为_chip
来使警告静音。
let _chip = Chip::new(Some(wake_pin));
第一个错误告诉我们,由于仅借用了self
,因此无法将引脚移出self
。如果我们只是借用它,那么使自身背后的数据无效将是很不礼貌的。但是,编译器正在告诉我们一个解决方案。 help: consider borrowing here: `&self.wake_pin`
最终结果不是很正确,但这是正确的方向。
if let Some(pin) = &self.wake_pin {
pin.set_low();
}
现在不是类型为pin
(拥有值)的OutputPin
,而是类型为&OutputPin
(借入值)。
尽管,我们仍然遇到第二个错误(措辞略有不同)。关键是pin.set_low()
要求pin
是可变参考。现在,我们将self
作为不可变的参考(pub fn awake(&self)
)。如果我们要更改self
或其任何字段,则需要将其可变。这也意味着我们需要确保pin
是可变借用的。
pub fn awake(&mut self) {
if let Some(pin) = &mut self.wake_pin {
pin.set_low();
}
}