Clippy警告我在我的代码中存在"不可变引用上的deref",一个例子是&*s
s
是一个&String
。
Clippy建议,
如果您想重新借款,请尝试删除
&*
或
如果您想拒绝引用,请尝试使用
&**
这两个建议有什么区别?
首先要了解的是Deref
是一种特质。如果T: Deref<Target=U>
,则表示T
可以被视为指向U
的指针(大致)。这意味着 Rust 会在需要时自动将&T
转换为&U
(即,如果您正在调用T
类型的值U
的方法)。当您尝试尊重T
时,也会触发:Rust 会将其deref
U
。
然而,这里的情况并非如此:你正在取消引用&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建议你完全删除它。