Rust 不使用';我不在乎拥有它

Rust 不使用';我不在乎拥有它,rust,ownership,borrowing,Rust,Ownership,Borrowing,我经常想在Rust中定义递归数据类型。我们需要某种程度的间接寻址,以避免使用大小无限的类型。经典的解决方案是使用Box(): 但它失败了 错误[E0275]:评估需求的溢出'IntList` =注意:必需,因为它出现在类型“std::borrow::Cow”中>` =注意:枚举变量的任何字段都不能具有动态大小的类型 我创建了一种类似于Cow的数据类型,我称之为Cowish。如果已经有类似的事情发生,请告诉我 pub enum Cowish<'a, T, O> where T:

我经常想在Rust中定义递归数据类型。我们需要某种程度的间接寻址,以避免使用大小无限的类型。经典的解决方案是使用
Box
():

但它失败了

错误[E0275]:评估需求的溢出'IntList`
=注意:必需,因为它出现在类型“std::borrow::Cow”中>`
=注意:枚举变量的任何字段都不能具有动态大小的类型

我创建了一种类似于
Cow
的数据类型,我称之为
Cowish
。如果已经有类似的事情发生,请告诉我

pub enum Cowish<'a, T, O>
where
    T: 'a,
{
    Borrowed(&'a T),
    Owned(O),
}

impl<'a, T, O> Borrow<T> for Cowish<'a, T, O>
where
    T: 'a,
    O: Borrow<T>,
{
    fn borrow(&self) -> &T {
        match self {
            Borrowed(b) => b,
            Owned(o) => o.borrow(),
        }
    }
}

impl<'a, T, O> Cowish<'a, T, O>
where
    T: ToOwned<Owned=O> + 'a,
    O: Borrow<T>,
{
    pub fn into_owned(self) -> O {
        match self {
            Borrowed(b) => b.to_owned(),
            Owned(o) => o,
        }
    }
}
pub enum Cowish借用Cowish&T{
匹配自我{
借用(b)=>b,
拥有(o)=>o.借用(),
}
}
}
恳求
哪里
T:Toowed+a,
O:借,
{
pub fn in_own(self)->O{
匹配自我{
借来的(b)=>b.给拥有的(),
拥有(o)=>o,
}
}
}
利用它,我可以做我想做的事:

enum IntList<'a> {
    Empty,
    Cons(i32, Cowish<'a, IntList<'a>, Box<IntList<'a>>>),
}
enum IntList>>),
}

可以找到一个更大的例子。

这可能太旧了,但只是为了记录,如果您想制作一个链表,可以使用
std::rc::rc
。它就像
Box
,但是可以对单个对象有多个引用。唯一需要注意的是,一旦列表包含在Rc中,就不能对其进行变异。以下是来自以下方面的示例:

枚举列表{
Cons(i32,Rc),
无
}
使用板条箱::列表:{Cons,Nil};
使用std::rc::rc;
fn main(){
设a=Rc::new(Cons(5,Rc::new)(Cons(10,Rc::new(Nil '));//[10,5]
设b=Cons(3,Rc::clone(&a));/[10,5,3]
设c=Cons(4,Rc::clone(&a));/[10,5,4]
}

错误消息令人困惑,但您正在尝试创建一种无限大小的类型。请参见将
Cow
包装在
框中是解决此问题的一种方法。我知道无限大小的类型是不好的,但我的理解是
Cow>
代表
Box@JJW5432
Cow
不装箱。它将是
intlist,那么为什么它会为字符串设置“框”?它是
&str
字符串
,大致是
(如果不是这样,请纠正我)。这就是我想要的行为,或者是一个
盒子或者是一个
盒子“如果已经有类似的东西了,请让我知道!”-这不完全一样,但是你可以使用。结果可能是这样的:
#[derive(Clone)]
enum IntList<'a> {
    Empty,
    Cons(i32, Cow<'a, IntList<'a>),
}
pub enum Cowish<'a, T, O>
where
    T: 'a,
{
    Borrowed(&'a T),
    Owned(O),
}

impl<'a, T, O> Borrow<T> for Cowish<'a, T, O>
where
    T: 'a,
    O: Borrow<T>,
{
    fn borrow(&self) -> &T {
        match self {
            Borrowed(b) => b,
            Owned(o) => o.borrow(),
        }
    }
}

impl<'a, T, O> Cowish<'a, T, O>
where
    T: ToOwned<Owned=O> + 'a,
    O: Borrow<T>,
{
    pub fn into_owned(self) -> O {
        match self {
            Borrowed(b) => b.to_owned(),
            Owned(o) => o,
        }
    }
}
enum IntList<'a> {
    Empty,
    Cons(i32, Cowish<'a, IntList<'a>, Box<IntList<'a>>>),
}
enum List {
    Cons(i32, Rc<List>),
    Nil,
}

use crate::List::{Cons, Nil};
use std::rc::Rc;

fn main() {
    let a = Rc::new(Cons(5, Rc::new(Cons(10, Rc::new(Nil))))); // [10, 5]
    let b = Cons(3, Rc::clone(&a)); // [10, 5, 3]
    let c = Cons(4, Rc::clone(&a)); // [10, 5, 4]
}