Почему происходит сброс после деструктуризации структуры?

Я оборачиваю C API. Чтобы упростить этот вопрос, я вместо этого использую NonNull::dangling.

use std::ptr::NonNull;

struct Foo(NonNull<i32>);

impl Drop for Foo {
    fn drop(&mut self) {
        println!("Foo::drop: {:?}", self.0);
    }
}

struct Moo(NonNull<i32>);
//impl Drop for Moo exists, but not important for question

fn f1() -> Result<Foo, String> {
    Ok(Foo(unsafe { NonNull::dangling() }))
}

fn f2() -> Result<Moo, String> {
    f1().map(|Foo(x)| Moo(x))//1
}

fn main() {
    f2();
}

В точке (1) я распаковываю/деструктурирую Foo. Я ожидаю, что после этого Foo::drop не должно вызываться, а печатается почему-то Foo::drop.

Я ошибаюсь, что деструктуризация (let Struct1 { field1, field2, .. } = struct1;) должна предотвращать вызов Struct1::drop?

Почему Python в конце концов умрет
Почему Python в конце концов умрет
Последние 20 лет были действительно хорошими для Python. Он прошел путь от "просто языка сценариев" до основного языка, используемого для написания...
2
0
208
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Если вы замените NonNull на структуру, которая не реализует Copy, поведение станет более понятным:

#[derive(Debug)]
struct NoCopy;

struct Foo(NoCopy);

impl Drop for Foo {
    fn drop(&mut self) {
        println!("Foo::drop: {:?}", self.0);
    }
}

struct Moo(NoCopy);
//impl Drop for Moo exists, but not important for question

fn f1() -> Result<Foo, String> {
    Ok(Foo(NoCopy))
}

fn f2() -> Result<Moo, String> {
    f1().map(|Foo(x)| Moo(x))//1
}

fn main() {
    f2();
}

Это приводит к этой ошибке:

error[E0509]: cannot move out of type `Foo`, which implements the `Drop` trait
  --> src/main.rs:20:15
   |
20 |     f1().map(|Foo(x)| Moo(x))//1
   |               ^^^^-^
   |               |   |
   |               |   data moved here
   |               cannot move out of here
   |
note: move occurs because `x` has type `NoCopy`, which does not implement the `Copy` trait
  --> src/main.rs:20:19
   |
20 |     f1().map(|Foo(x)| Moo(x))//1
   |            

Следовательно, в (1) вы копируете NonNull из Foo, а Foo отбрасывается.

Кстати. вы не можете выйти из Foo (f1().map(|x| Moo(x.0))), так как Foo реализует Drop

Tim Diekmann 09.04.2019 00:26

Другие вопросы по теме