简体   繁体   中英

the trait bound `&'a chain::Chain<'a>: Deserialize<'_>` is not satisfied

I'm very new to rust and I want to access a parent struct from a children. I want to use Chain from its childs Chain.blocks . So I'm trying to store a reference to the parent Chain .

But I'm encountering this error.

the trait bound `&'a chain::Chain<'a>: Deserialize<'_>` is not satisfied
the following implementations were found:
  <chain::Chain<'a> as Deserialize<'de>>rustcE0277

This is my code.

// Chain
#[derive(Default, Serialize, Deserialize)]
pub struct Chain<'a> {
    pub blocks: Vec<Block<'a>>,
}

// Block
#[derive(Deserialize, Serialize)]
pub struct Block<'a> {
    pub id: String,
    pub prev_hash: String,
    pub timestamp: u64,
    pub nonce: i32,
    pub proof: String,
    pub miner: String,
    pub documents: Vec<String>,
    pub merkel_root: String,
    chain: &'a Chain<'a>,
}

impl<'a> Default for Block<'a> {
    fn default() -> Self {
        Self {
            ..Default::default()
        }
    }
}

Sorry if I reply too late.

Problems

What you're trying to make is a self-referential structure, which is troublesome in Rust. See these answers, for example. It's not necessarily impossible, but it would be best if you try to find a different model for your data.

Also: serde 's derive mechanism doesn't care whether your field is pub or not, it will deserialize to it anyway. And it has no way to know that you want chain to contain a reference to its parent. In fact, it will generate a deserializer for block which can be used stand-alone. If you do wat @PitaJ suggests ( chain: Box<Chain> ), you'll get a deserializer that expects data like

{
  "id": "foo",
  …
  "merkel_root": "You're thinking of Merkle, Merkel is the German chancellor a. D.",
  "chain": {
    "blocks": [
      {
        "id": "bar",
        …
        "chain": {
          "blocks": []
        }
      }
    ]
  }
}

Lastly:

impl<'a> Default for Block<'a> {
    fn default() -> Self {
        Self {
            ..Default::default()
        }
    }
}

is infinite recursion. But rustc would have warned you about this if you'd managed to get past the compiler errors.

warning: function cannot return without recursing
  --> src/lib.rs:25:5
   |
25 |     fn default() -> Self {
   |     ^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
26 |         Self {
27 |             ..Default::default()
   |               ------------------ recursive call site
   |

If you absolutely want this

… against better advice, then you can get something close with reference counting (and my favourite serde trick ):

First, you need to solve the problem that serde won't know what to store in chain in Block . You could make it an Option and mark it #[serde(skip)] , but I prefer having a second struct with only the fields you actually want to be deserialized:

#[derive(Deserialize)]
pub struct ChainSerde {
    pub blocks: Vec<BlockSerde>,
}

#[derive(Deserialize)]
pub struct BlockSerde {
    pub id: String,
    // … - doesn't contain chain
}

The actual struct you want to work with then looks like this

#[derive(Deserialize, Serialize, Debug)]
#[serde(from = "ChainSerde")]
pub struct Chain {
    pub blocks: Rc<RefCell<Vec<Block>>>,
}

#[derive(Debug, Serialize)]
pub struct Block {
    pub id: String,
    // …
    #[serde(skip)] // Serialization would crash without
    // If you wanted Chain instead of Vec<Block>, you'd need another
    // #[serde(transparent, from = "ChainSerde")]
    // struct ChainParent(Rc<RefCell<Chain>>)
    chain: Weak<RefCell<Vec<Block>>>,
}

Now, all you need to do is to tell serde how to turn the deserialized struct into the struct you actually want to work with.

impl From<ChainSerde> for Chain {
    fn from(t: ChainSerde) -> Self {
        let b: Rc<RefCell<Vec<Block>>> = Default::default();
        let bc: Vec<Block> = t
            .blocks
            .into_iter()
            .map(|block| Block {
                id: block.id,
                chain: Rc::downgrade(&b),
            })
            .collect::<Vec<Block>>();
        *RefCell::borrow_mut(&b) = bc;
        Chain { blocks: b }
    }
}

If you want to wait for Rust 1.60, you can do it a bit more neatly and without the RefCell by using Rc::new_cyclic :

#[derive(Deserialize, Debug)]
#[serde(from = "ChainSerde")]
pub struct ChainNightly {
    pub blocks: Rc<Vec<BlockNightly>>,
}

#[derive(Debug)]
pub struct BlockNightly {
    pub id: String,
    // …
    chain: Weak<Vec<BlockNightly>>,
}

impl From<ChainSerde> for ChainNightly {
    fn from(t: ChainSerde) -> Self {
        ChainNightly {
            blocks: Rc::new_cyclic(|blocks| {
                t.blocks
                    .into_iter()
                    .map(|block| BlockNightly {
                        id: block.id,
                        chain: blocks.clone(),
                    })
                    .collect()
            }),
        }
    }
}

Playground

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM