Как заставить ссылку `& b` на` & A` для `b: B` в` let a: & A = & b; `? - PullRequest
0 голосов
/ 31 января 2019

У меня есть следующие структуры:

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

В документации для Borrow упоминается, что тип A может быть заимствован как некоторый другой тип B, если A реализует Borrow<B>, поэтому я попытался реализовать 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 в &Age?

1 Ответ

0 голосов
/ 31 января 2019

Два примера с Box и String работают не из-за черты Borrow, а из-за черты Deref.Поле &b в вашем примере может быть приведено к &Age, потому что Box<Age> реализует Deref<Target = Age>.Аналогично, String имеет реализацию Deref, так что ссылка String &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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...