我被所有权困住了;我却做不到 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 crate,编译器在 if let Some
中失败区域。我试着借wake_pin
, 得到 Option
作为引用和其他一些东西,但我不完全理解所有权规则。
最佳答案
我相信我已经复制了您的设置。如果有什么地方不对,请使用相关详细信息编辑您的问题。
源/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
。如果我们只是借用它,那么使 self 后面的数据无效是相当粗鲁的。然而,编译器告诉我们一个解决方案。 帮助:考虑在这里借用:`&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();
}
}
关于rust - 可变的可选 OutputPin,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58366181/