Rust、Copy Trait 在使用泛型时不适用于类型

Dan*_*elV 4 generics pointers copy rust

Rust 不会编译以下内容:

#[derive(Copy, Clone)]
struct WhateverStruct<T> {
    field : T
}

trait WhateverStructTrait<T> {
    fn to(self) -> WhateverStruct<T>;
}
impl<T> WhateverStructTrait<T> for *mut WhateverStruct<T> {
    fn to(self) -> WhateverStruct<T> {
        unsafe {* self }
    }
}

fn test() {
    let x = WhateverStruct { field : 7u32 };
    let _y = x;
    let _z = x;
    println!("Copying is fine");
}

fn main() {
    test();
}
Run Code Online (Sandbox Code Playgroud)

它抱怨不安全的{* self }部分说

*self有 type WhateverStruct<T>,它没有实现该Copy特征

然而,它很明显确实实现了复制特征。测试功能没有错误。如果您将代码的其余部分更改为并删除,则一切都会编译并运行得struct WhateverStruct<T> { field : T }很好struct WhateverStruct { field : u32 }<T>所以 Rust 不喜欢泛型。

在这里你可以在操场上看到:https://play.rust-lang.org/? version=stable&mode=debug&edition=2018&gist=5d5c3a0f0e6e0153ec286ce38f0f3a2d

这是一个错误吗?有解决办法吗?

SCa*_*lla 9

对于任何泛型类型,Foo<T>当您派生Copy和时Clone,特征始终必须T分别为CopyClone。有时,尽管您实际上并不需要T为整个结构实现这些特征,使其成为CopyClone

下面的结构就是一个例子。

#[derive(Copy, Clone)]
struct Foo<T> {
    _marker: std::marker::PhantomData<T>,
}
Run Code Online (Sandbox Code Playgroud)

如果我们查看派生生成的代码(cargo-expand用于此目的),我们会得到类似的内容

use std::prelude::v1::*;
#[macro_use]
extern crate std;

struct Foo<T> {
    _marker: std::marker::PhantomData<T>,
}

#[automatically_derived]
#[allow(unused_qualifications)]
impl<T: ::core::marker::Copy> ::core::marker::Copy for Foo<T> {}

#[automatically_derived]
#[allow(unused_qualifications)]
impl<T: ::core::clone::Clone> ::core::clone::Clone for Foo<T> {
    #[inline]
    fn clone(&self) -> Foo<T> {
        match *self {
            Foo {
                _marker: ref __self_0_0,
            } => Foo {
                _marker: ::core::clone::Clone::clone(&(*__self_0_0)),
            },
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

看看它的实现Copy(并稍微清理一下)

impl<T: Copy> Copy for Foo<T> {}
Run Code Online (Sandbox Code Playgroud)

因此,尽管Foo<T>不需要,TCopy无论如何它都会限制它。

在这些情况下,您需要自己简单地Copy实施Clone。只要结构体的实际字段为 ,就有一个相当简单的实现Copy

struct Foo<T> {
    _marker: std::marker::PhantomData<T>,
}

impl<T> Copy for Foo<T> {}

impl<T> Clone for Foo<T> {
    fn clone(&self) -> Self {
        *self
    }
}
Run Code Online (Sandbox Code Playgroud)