Заимствованное значение не живет достаточно долго для результата `AsRef`, даже если его` self` живет достаточно долго - PullRequest
0 голосов
/ 22 ноября 2018

У меня есть структура, которая оборачивает некоторые функции вокруг среза:

use std::fmt::Debug;

struct SliceWrapper<'a, T: Debug + Copy + 'a> {
    slice: &'a [T],
    pos: usize,
}

Я хочу реализовать черту From для каждого элемента, который поддерживает AsRef<T: Debug + Copy + 'a>, например:

impl<'a, T: Debug + Copy + 'a, R: AsRef<[T]> + 'a> From<R> for SliceWrapper<'a, T> {
    fn from(slice: R) -> Self {
        Self {
            slice: slice.as_ref(),
            pos: 0,
        }
    }
}

Я получаю ошибку:

error[E0597]: `slice` does not live long enough
  --> src/lib.rs:11:20
   |
11 |             slice: slice.as_ref(),
   |                    ^^^^^ borrowed value does not live long enough
...
14 |     }
   |     - borrowed value only lives until here
   |
note: borrowed value must be valid for the lifetime 'a as defined on the impl at 8:6...
  --> src/lib.rs:8:6
   |
8  | impl<'a, T: Debug + Copy + 'a, R: AsRef<[T]> + 'a> From<R> for SliceWrapper<'a, T> {
   |      ^^

Я не понимаю этого, потому что я говорю, что R (slice) должен жить столько же, сколько и мой SliceWrapper - и насколько яПоймите, AsRef<_> наследует время жизни от self (slice) ...

Ответы [ 2 ]

0 голосов
/ 24 ноября 2018

Вы можете ограничить преобразование ссылочными аргументами, и тогда у вас есть хороший способ выразить заимствование, которое вам нужно - время жизни берется из входной ссылки:

impl<'a, T, R> From<&'a R> for SliceWrapper<'a, T>
where
    T: Debug + Copy + 'a,
    R: AsRef<[T]>
{
    fn from(slice: &'a R) -> Self {
        Self {
            slice: slice.as_ref(),
            pos: 0,
        }
    }
}

Теперь вы можете следовать своим первоначальным рассуждениям,У вас есть AsRef, дающий вам: &'x self -> &'x [T] для любого 'x, и вы вводите в него &'a R, так что вы получаете &'a [T].

Ссылочный взятие From иногда существует, я думаю, этоособенно уместно при преобразованиях типа «ссылка-ссылка».Пример в std это impl<'a> From<&'a str> for Cow<'a, str>

0 голосов
/ 22 ноября 2018

Полное сообщение об ошибке на ночных состояниях совершенно ясно показывает, что здесь происходит.Вы перемещаете slice в функцию from(), затем одалживаете ее, используя as_ref(), и затем она сбрасывается в конце области действия:

8  | impl<'a, T: Debug + Copy + 'a, R: AsRef<[T]> + 'a> From<R> for SliceWrapper<'a, T> {
   |      -- lifetime `'a` defined here
9  |     fn from(slice: R) -> Self {
10 |         Self{ slice: slice.as_ref(), pos: 0 }
   |                      ^^^^^---------
   |                      |
   |                      borrowed value does not live long enough
   |                      argument requires that `slice` is borrowed for `'a`
11 |     }
   |     - `slice` dropped here while still borrowed

Вы пытаетесь создать заем, который живетв течение жизни 'a, но владелец, у которого вы заимствуете, slice, не живет достаточно долго.

Черта From не подходит для данного варианта использования.Идея этой черты состоит в том, чтобы переместить владение некоторыми данными в новый тип, но ваше SliceWrapper не вступает во владение.Вместо этого я предлагаю написать собственный конструктор, который берет R по ссылке.

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