Почему глава макета nomicon & Ve c <& 'stati c str> не может использоваться там, где ожидалось & Ve c <&' a str>? - PullRequest
1 голос
/ 05 августа 2020

https://doc.rust-lang.org/nomicon/vec-layout.html

Я не понимаю, когда Ve c определяется как

pub struct Vec<T> {
    ptr: *mut T,
    cap: usize,
    len: usize,
}

И цитирует:

И действительно, это будет компилироваться. К сожалению, это было бы неверно. Во-первых, компилятор даст нам слишком строгую дисперсию. Таким образом, &Vec<&'static str> нельзя было использовать там, где ожидалось &Vec<&'a str>. Что еще более важно, он предоставит некорректную информацию о владельце для средства проверки перетаскивания, поскольку консервативно предполагает, что мы не владеем никакими значениями типа T.

Я пробовал код ниже ( Playground ) но работает.

pub struct TestVec<T> {
    raw: *mut T,
    len: usize,
    cap: usize,
}

impl<T> TestVec<T> {
    pub fn new()->Self {
        TestVec { raw: std::mem::MaybeUninit::uninit().as_mut_ptr(), len:0, cap:0}
    }
}

fn test1(a: &TestVec<&str>) {
}

fn test() {
    let v:TestVec<&'static str> = TestVec::new();
    test1(&v);
}

fn main() {
    test();
}

Где я не прав? Или есть пример кода?

1 Ответ

3 голосов
/ 05 августа 2020

Это утверждение относится к типовой дисперсии, которая представляет собой сложную концепцию отношений между типами, на самом деле это особый вид подтипов.

Ваш пример не содержит дисперсии. Он сокращается до:

fn test1<'x, 'y>(a: &'x TestVec<&'y str>)

И когда вы вызываете эту функцию с помощью v: TestVec<&'static str>, время жизни 'x преобразуется в v, а 'y равно 'static. Здесь нет вариации типов, только обобщения.

Но рассмотрим другой пример, требующий вариации:

fn test2<'x>(a: &TestVec<&'x str>, b: &TestVec<&'x str>) {}

fn test_variance<'a>() {
    let v1:TestVec<&'static str> = TestVec::new();
    let v2:TestVec<&'a str> = TestVec::new();
    test2(&v1, &v2);
}

Теперь компилятор должен решить 'x как самое короткое время жизни 'a и 'static, это должно быть просто 'a из-за дисперсии. Но *mut T в TestVec вызывает эту ошибку:

cannot infer an appropriate lifetime for lifetime parameter 'a in function call due to conflicting requirement
...
   = note: expected `&TestVec<&str>`
              found `&TestVec<&'static str>`

Затем, как объясняет Nomicon, изменение *mut T на *const T заставляет его снова работать.

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