如何在`let a:&A =&b;`中将`&b`强制转换为对`b:B`的`&A`?

时间:2019-01-31 17:39:43

标签: reference rust borrow-checker coercion

我具有以下结构:

struct Age(u8);
struct User {
    age: Age,
}

我想将User类型的借入值强制转换为&Age,如以下示例所示:

let s = String::from("abcd");
let z: &str = &s; // This works

let b = Box::new(Age(8));
let a: &Age = &b; // This also works

documentation for Borrow提到如果A实现B,则可以像其他类型的A一样借用Borrow<B>类型,因此我尝试实现{{1 }} Borrow<Age>

User

这是我收到的错误消息:

use std::borrow::Borrow;

impl Borrow<Age> for User {
    fn borrow(&self) -> &Age {
        &self.age
    }
}

fn main() {
    let u = User { age: Age(8) };
    let a: &Age = u.borrow();     // Works
    let a: &Age = &u;             // Error
}

我想念什么吗?如何将error[E0308]: mismatched types --> src/main.rs:23:19 | 23 | let a: &Age = &u; // Error: expected struct `Age`, found struct `User` | ^^ expected struct `example::Age`, found struct `example::User` | = note: expected type `&example::Age` found type `&example::User` 强制转换为&u

1 个答案:

答案 0 :(得分:3)

使用BoxString的两个示例并不是因为Borrow特性,而是因为Deref特性。您的示例中的框&b可以强制插入&Age中,因为Box<Age>实现了Deref<Target = Age>。同样,String具有Deref的实现,因此可以将字符串引用&s强制转换为&str。它将以完全相同的方式为您的User工作:

use std::ops::Deref;

impl Deref for User { // That's bad, don't do that.
    type Target = Age;
    fn deref(&self) -> &Age {
        &self.age
    }
}

在此范围内,现在将编译以下内容:

let u = User { age: Age(8) };
let a: &Age = &u;

请注意,该示例在某种程度上是人为的而不是惯用的:没有人会期望User的行为类似于指向Age的指针类型。同样,没有人会期望user.borrow()借用Age而不是User,这不是Borrow特性的目的。