"reborrow" -ing 和 "deref" -ing 有什么区别?



Clippy警告我在我的代码中存在"不可变引用上的deref",一个例子是&*ss是一个&String

Clippy建议,

如果您想重新借款,请尝试删除&*

如果您想拒绝引用,请尝试使用&**

这两个建议有什么区别?

首先要了解的是Deref是一种特质。如果T: Deref<Target=U>,则表示T可以被视为指向U的指针(大致)。这意味着 Rust 会在需要时自动将&T转换为&U(即,如果您正在调用T类型的值U的方法)。当您尝试尊重T时,也会触发:Rust 会将其derefU

然而,这里的情况并非如此:你正在取消引用&String,这将给出一个String(甚至不考虑String作为指向str的指针,因为String: Deref<Target=str>),然后你再次借用那个东西。如果你的目标是以&str结束,你就失败了。这就是为什么 Rust 再次提议尊重:&** &String -> &* String -> &* &str -> & str -> &str.


或者,也许你想做一些叫做重新借用的事情,这与取消引用无关。当您有某种借款时,需要再借款,而您需要另一种借款。例如,如果您有&mut T并想要&T,则可以重新借款。请注意,重借总是明确地意味着取消引用借用,只是为了再次借用它:它不会触发 deref 或类似的东西,它只是一个类型检查步骤(在实践中,重借不会产生任何代码,它只是供编译器推理;而 deref 将产生一些代码)。

为什么要这样做的一个示例是更改绑定到借用的隐式生存期:当您重新借入时,您有权为新借款提供较短的生存期,这允许您在完成重新借用的借款后重复使用原始借款。请看@Cerberus在操场上提供的示例:

use core::fmt::Debug;
fn debug(val: impl Debug) {
dbg!(val);
}
fn debug_ref(val: &impl Debug) {
dbg!(val);
}
fn main() {
let mut x = 42;
let x_ref = &mut x;

// fails to compile - `x_ref` is moved into `debug`,
// but later we use it again
// debug(x_ref);

// compiles successfully
debug(&mut *x_ref);

// also compiles successfully, since the target type is reference,
// so `x_ref` is implicitly reborrowed
debug_ref(x_ref);

*x_ref = 84;
debug(x_ref);
}

但是,在您的情况下,您可以将常规借款(Clippy称之为"不可变借款")转换为常规借款:您什么都不做!这就是为什么Clippy建议你完全删除它。

相关内容

  • 没有找到相关文章

最新更新