함수로 옮겨진 impl 특성이 아직 차용 된 상태에서 드롭되지 않도록하려면 어떻게해야합니까?

리치 아포 다카

메서드를 Holder통해 일부를 반복 할 수 있는 특성을 정의하고 싶습니다 items. 가능한 경우 정적 디스패치 및 스택 할당을 고수하고 싶기 때문에이 메서드에서 특성 개체를 반환하고 싶지 않습니다. 내가 가진 시스템은 잘 작동하지만 일종의 놀라운 상황에서 실패합니다.

코드는 다음과 같습니다.

pub trait Holder<'a, N: 'a> {
    type Items: Iterator<Item=&'a N>;

    fn items(&'a self) -> Self::Items;
}

struct Impl<N> {
    items: Vec<N>
}

impl<'a, N: 'a> Holder<'a, N> for Impl<N> {
    type Items = std::slice::Iter<'a, N>;

    fn items(&'a self) -> Self::Items {
        self.items.iter()
    }
}

fn use_holder<'a, N: 'a>(holder: impl Holder<'a, N>) {
    // COMPILE ERROR
    for item in holder.items() {

    }
}

오류는 다음과 같습니다.

error[E0309]: the parameter type `impl Holder<'a, N>` may not live long enough
  --> src/graph/test.rs:20:17
   |
19 | fn use_holder<'a, N: 'a>(holder: impl Holder<'a, N>) {
   |                                  ------------------ help: consider adding an explicit lifetime bound...: `impl Holder<'a, N> + 'a`
20 |     for item in holder.items() {
   |                 ^^^^^^
   |
note: ...so that the type `impl Holder<'a, N>` is not borrowed for too long
  --> src/graph/test.rs:20:17
   |
20 |     for item in holder.items() {
   |                 ^^^^^^

error[E0309]: the parameter type `impl Holder<'a, N>` may not live long enough
  --> src/graph/test.rs:20:24
   |
19 | fn use_holder<'a, N: 'a>(holder: impl Holder<'a, N>) {
   |                                  ------------------ help: consider adding an explicit lifetime bound...: `impl Holder<'a, N> + 'a`
20 |     for item in holder.items() {
   |                        ^^^^^
   |
note: ...so that the reference type `&'a impl Holder<'a, N>` does not outlive the data it points at
  --> src/graph/test.rs:20:24
   |
20 |     for item in holder.items() {
   |                        ^^^^^

error: aborting due to 2 previous errors; 4 warnings emitted

For more information about this error, try `rustc --explain E0309`.

컴파일러의 조언을 따르고 명시 적 수명을 추가합니다.

pub trait Holder<'a, N: 'a> {
    type Items: Iterator<Item=&'a N>;

    fn items(&'a self) -> Self::Items;
}

struct Impl<N> {
    items: Vec<N>
}

impl<'a, N: 'a> Holder<'a, N> for Impl<N> {
    type Items = std::slice::Iter<'a, N>;

    fn items(&'a self) -> Self::Items {
        self.items.iter()
    }
}

fn use_holder<'a, N: 'a>(holder: impl Holder<'a, N> + 'a) {
    for item in holder.items() {

    }
}

오류가 발생합니다.

error[E0597]: `holder` does not live long enough
  --> src/graph/test.rs:20:17
   |
19 | fn use_holder<'a, N: 'a>(holder: impl Holder<'a, N> + 'a) {
   |               -- lifetime `'a` defined here
20 |     for item in holder.items() {
   |                 ^^^^^^--------
   |                 |
   |                 borrowed value does not live long enough
   |                 argument requires that `holder` is borrowed for `'a`
...
23 | }
   | - `holder` dropped here while still borrowed

나는 이 질문 과이 문제 와 접선 적으로 관련된 몇 가지 다른 것을 보았지만 앞으로 나아가는 방법을 이해할 수 없습니다.

에서 특성 개체를 반환하는 것 외에 Hoder#items루프를 use_hodler작동 시키는 옵션은 무엇 입니까?

리처드 매더슨

이것은 실제로 매우 어려웠습니다. 수명과 관련 유형은 (아직) 잘 지원되지 않는 Rust의 이상한 코너 케이스 중 하나 인 것처럼 보입니다. 오류의 원인을 제대로 이해했다고 말하면 거짓말 이겠지만, Higher Ranked Trait Bounds 사용 하여이 특정 예제 에서 작동하도록 관리했습니다 .

한 줄만 변경하면됩니다.

fn use_holder<N>(holder: impl for<'a> Holder<'a, N>) {

수명 매개 변수가 for<'a>. 이것이 의미하는 바는 holder매개 변수 가 최소한 함수만큼 오래 지속 되는 특정 항목 아니라 Holder<'a, N>가능한 모든 수명 동안 구현 'a된다는 것입니다 'a.

for<'a> ... 이 특성 을 사용하는 대부분의 장소를 사용해야하므로 매우 빨리 지저분해질 것입니다. 그리고 더 높은 등급의 특성 경계는 일반적으로 사용되는 기능이 아닙니다. 꽤 틈새 시장이고 가장 일반적인 경우에서 제외되었으므로 가독성이나 유지 관리에 도움이되지 않습니다.

가능하다면이 구성을 피하기 위해 아키텍처를 변경하는 것이 좋습니다.

이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.

침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제

에서 수정
0

몇 마디 만하겠습니다

0리뷰
로그인참여 후 검토

관련 기사

Related 관련 기사

뜨겁다태그

보관