为什么在结构分解后会有一个挂断电话?

时间:2019-04-08 21:38:13

标签: rust destructuring

我正在包装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

1 个答案:

答案 0 :(得分:5)

如果将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中。