Rust 是否有一种安全、符合人体工程学的方法来改变复杂结构中的幻影类型?

Rust 是否有一种安全、符合人体工程学的方法来改变复杂结构中的幻影类型?,rust,phantom-types,Rust,Phantom Types,假设我们定义了一个具有许多字段的泛型结构,它表示使用幻象类型的类型安全状态机: structfoo{ a:a, b:b, c:c, //... 状态:幻影数据, } 然后,我们可以编写类型安全状态转换: impl Foo<SourceState> { fn transition(self, extra: X) -> Foo<DestinationState> { let Foo {a, b, c, state: _} = self;

假设我们定义了一个具有许多字段的泛型结构,它表示使用幻象类型的类型安全状态机:

structfoo{
a:a,
b:b,
c:c,
//...
状态:幻影数据,
}
然后,我们可以编写类型安全状态转换:

impl Foo<SourceState> {
    fn transition(self, extra: X) -> Foo<DestinationState> {
        let Foo {a, b, c, state: _} = self;
        // do lots of stuff
        Foo { a, b, c, state: PhantomData } 
    }
}
impl-Foo{
fn转换(自身,额外:X)->Foo{
设Foo{a,b,c,state:{}=self;
//做很多事情
Foo{a,b,c,state:PhantomData}
}
}
但我们需要笨拙地将每个字段解包,并以不同的结构重新打包

我们也可以使用
mem::transmute
,尽管我的理解是,同一结构的不同单体不能保证具有相同的内存布局

我希望,
Foo{state:PhantomData,…self}
能起作用;唉,它无法编译


有没有什么规范的、符合人体工程学的、安全的方法来写这篇文章?

没有直接的方法来写,因为它们有两种不同的类型:实际上,这就是代码的全部要点。为了简化它,我将分两步进行,第二步是一般转换:

use core::marker::PhantomData;

struct Foo<State> {
    a: i32,
    b: i32,
    c: i32,
    //...
    state: PhantomData<State>,
}

struct SourceState;
struct DestinationState;

impl<Src> Foo<Src> {
    fn transition<Dest>(self) -> Foo<Dest> {
        let Foo {a, b, c, state: _} = self;

        Foo { a, b, c, state: PhantomData } 
    }
}

impl Foo<SourceState> {
    fn to_destination_state(mut self, extra: ()) -> Foo<DestinationState> {
        // Do whatever you want with self

        self.transition()
    }
}
使用core::marker::PhantomData;
结构Foo{
a:i32,
b:i32,
c: i32,
//...
状态:幻影数据,
}
结构源状态;
结构目标状态;
impl-Foo{
fn转换(自)->Foo{
设Foo{a,b,c,state:{}=self;
Foo{a,b,c,state:PhantomData}
}
}
impl-Foo{
fn到目的地状态(多个自身,额外:())->Foo{
//你想怎么做就怎么做
self.transition()
}
}
或者,您可以抽象出您拥有一个状态的事实:

mod stateful {
    use core::marker::PhantomData;

    pub struct Stateful<T, State> {
        pub data: T,
        state: PhantomData<State>,
    }

    impl<T, SrcState> Stateful<T, SrcState> {
        pub fn transform<DestState>(self) -> Stateful<T, DestState> {
            let Stateful { data, state: _ } = self;

            Stateful {
                data,
                state: Default::default(),
            }
        }
    }
}

struct Data {
    a: i32,
    b: i32,
    c: i32,
}

struct SourceState;
struct DestinationState;

type Foo<State> = stateful::Stateful<Data, State>;

impl Foo<SourceState> {
    fn to_destination_state(mut self, extra: ()) -> Foo<DestinationState> {
        // Do whatever you want with self.data

        self.transform()
    }
}
mod stateful{
使用core::marker::PhantomData;
pub结构有状态{
发布数据:T,
状态:幻影数据,
}
有状态的{
pub-fn转换(自)->有状态{
设有状态{data,state:{}=self;
有状态{
数据,
状态:Default::Default(),
}
}
}
}
结构数据{
a:i32,
b:i32,
c:i32,
}
结构源状态;
结构目标状态;
类型Foo=stateful::stateful;
impl-Foo{
fn到目的地状态(多个自身,额外:())->Foo{
//用self.data做任何你想做的事情
self.transform()
}
}

如果你的状态类型是零大小的,你不需要一个
幻影数据
,或者我不明白什么请添加
SourceState
DestinationState
@Boiethios的定义你是对的,在这种情况下我的状态类型是单位类型,但是使用PhantomData比为我所有的状态实现默认值要短。第一个解决方案是我最终要做的。一个次要问题是:为什么结构省略语法需要类型的标识?它是否可以取消一组访问并删除此约束?或者这会在实践中破坏太多的类型推断吗?因此,如果不复制数据,就无法做到这一点?@user1685095你是什么意思?我的代码片段中没有一个副本。