Error the method `take` exists for struct `Rc<Cell<&'a Vec<>>>

pub struct Block<'a> {
    pub index: u32,
    pub timestamp: u128,
    pub hash: Hash,
    pub prev_block_hash: Hash,
    pub nonce: u64,
    pub option_transactions: Rc<Cell<&'a Vec<OptionTransaction>>>,
    pub difficulty: u128, 
}



impl<'a> Debug for Block<'a> {
    fn fmt (&self, f: &mut Formatter) -> fmt::Result {
        let y=self.option_transactions.take();
        write!(f, "Prev hash of {} the Block[{}]: {} at: {} trx.len: {} nonce: {}",
            &hex::encode(&self.prev_block_hash),
            &self.index,
            &hex::encode(&self.hash),
            &self.timestamp,
            self.option_transactions.take().len(),
            &self.nonce,
        )
    }
}

Error:

the method `take` exists for struct `Rc<Cell<&'a Vec<OptionTransaction>>>`, but its trait bounds were not satisfied
the following trait bounds were not satisfied:
`Rc<Cell<&'a Vec<OptionTransaction>>>: Iterator`
which is required by `&mut Rc<Cell<&'a Vec<OptionTransaction>>>: Iterator`
`&'a Vec<OptionTransaction>: Default`
`Cell<&'a Vec<OptionTransaction>>: Iterator`
which is required by `&mut Cell<&'a Vec<OptionTransaction>>: Iterator`

Final goal is to have Vec How can I have Vec?
Because of move out error ' maked_transactions_of_a_block' I had to pass &Vec to funcation:

let rc_maked_transactions_of_a_block= move |maked_transactions_of_a_block|  {Rc::new(Cell::new(
            maked_transactions_of_a_block
        ))};
        //let refcell_trx=rc_maked_transactions_of_a_block;        
    
      if i==1{
            let mut genesis_block = Block::new(0, now(),vec![0; 32], rc_maked_transactions_of_a_block(&maked_transactions_of_a_block).clone(), difficulty);    
            prev_hash=genesis_block.mine().unwrap().into_boxed_slice();                
            let _=&blockchain.update_with_block(genesis_block);                
        }

Open Source Code

I change it to follow code but it does not worked:

pub struct Block<'a> {
    pub index: u32,
    pub timestamp: u128,
    pub hash: Hash,
    pub prev_block_hash: Hash,
    pub nonce: u64,
    pub option_transactions: &'a mut Rc<Cell<&'a Vec<OptionTransaction>>>,
    pub difficulty: u128, 
}



impl<'a> Debug for Block<'a> {
    fn fmt (&self, f: &mut Formatter) -> fmt::Result {
        let y=self.option_transactions.take().to_vec();
        write!(f, "Prev hash of {} the Block[{}]: {} at: {} trx.len: {} nonce: {}",
            &hex::encode(&self.prev_block_hash),
            &self.index,
            &hex::encode(&self.hash),
            &self.timestamp,
            self.option_transactions.take().len(),
            &self.nonce,
        )
    }
}

Take Error:

Vec<OptionTransaction>>>`, but its trait bounds were not satisfied
the following trait bounds were not satisfied:
`Rc<Cell<&'a Vec<OptionTransaction>>>: Iterator`
which is required by `&mut Rc<Cell<&'a Vec<OptionTransaction>>>: Iterator`
`&'a mut Rc<Cell<&'a Vec<OptionTransaction>>>: Iterator`
which is required by `&mut &'a mut Rc<Cell<&'a Vec<OptionTransaction>>>: Iterator`
`&'a Vec<OptionTransaction>: Default`
`Cell<&'a Vec<OptionTransaction>>: Iterator`
which is required by `&mut Cell<&'a Vec<OptionTransaction>>: Iterator`rustcE0599
cell.rs(236, 1): doesn't satisfy `Cell<&'a Vec<OptionTransaction>>: Iterator`
rc.rs(309, 1): doesn't satisfy `Rc<Cell<&'a Vec<OptionTransaction>>>: Iterator`

The problem is that Cell::take is only available if the type in the cell implements Default. Because the way that take works is it takes the value out, and replaces it with a default value.

That's what this line in the error message is complaining about:
&'a Vec<OptionTransaction>: Default
The type &'a Vec... must implement Default, but it doesn't.

The error message is pretty hard to understand here, but you can check out the doc page for the function here, and at the top of the page (in tiny little letters) it says: where T: Default, that's how you can tell the restriction exists.

So, how to fix it?
1) You have to make sure that OptionTransaction implements Default (it might already, I'm not familiar with it). For a Vec to be Default, the elements in it must also be Default.
2) Instead of storing a &Vec<OptionTransaction>, just store a normal non-borrowed Vec<OptionTransaction>

I know at the bottom you said you needed a &Vec, can you elaborate more on the code you need this for? Because unfortunately, take can't work for a borrowed type. They need to borrow something, so there's no way to make a default borrow.

1 Like

Ho can I convert default FnOnce to Fn?

         let mut rc_maked_transactions_of_a_block=   ||  {Rc::new(Cell::new(
            maked_transactions_of_a_block
        ))};
  let  rc_maked_transactions_of_a_block=  call_maked_trx(|| {{Rc::new(Cell::new(
            maked_transactions_of_a_block
        ))}}); 
        //let refcell_trx=rc_maked_transactions_of_a_block;        
    
      if i==1{
            let mut genesis_block = Block::new(0, now(),vec![0; 32], rc_maked_transactions_of_a_block.clone(), difficulty);    
            prev_hash=genesis_block.mine().unwrap().into_boxed_slice();                
            let _=&blockchain.update_with_block(genesis_block);                
        }
        else if i >1{
            let mut maked_block:Block = Block::new(i as u32, now(), prev_hash.to_vec(), rc_maked_transactions_of_a_block.clone(), difficulty);                                     
            prev_hash=maked_block.mine().unwrap().into_boxed_slice();
            let _=&blockchain.update_with_block(maked_block);
            //println!("**maked_hash:**\n{:?}\n",&blockchain.blocks[i].prev_block_hash.clone());                
        }    
   });
                                         
    Ok(()) 
}          
 
fn call_maked_trx<F>(f: F) ->  Rc<Cell<Vec<OptionTransaction>>>
    where F: Fn() -> Rc<Cell<Vec<OptionTransaction>>> {
    f()
}

Error:

cannot move out of `maked_transactions_of_a_block`, a captured variable in an `Fn` closure
move occurs because `maked_transactions_of_a_block` has type `Vec<OptionTransaction>`, which does not implement the `Copy` trait

This isn't true, a Default Vec contains 0 elements and so doesn't require anything special from T:

impl Default for Vec

1 Like

Yep, you're totally right. My bad!

2 Likes

Oh my friend both of you are in wrong :smiling_face_with_tear:
I have not got a correct solution that is possible follow link help you for making a challenge because it is related to the problem. something that stretches you.
except that where I impl vec for default?

Ho can I convert default FnOnce to Fn?

Here you fundamentally can't. Presumably your code looks like this:

         let maked_transactions_of_a_block = ...;
         ...
         let mut rc_maked_transactions_of_a_block=   ||  {Rc::new(Cell::new(
            maked_transactions_of_a_block
        ))};

When this closure runs, it takes the data out of maked_transactions_of_a_block and puts it inside a Cell. So you can only run it once, because after it finishes, maked_transactions_of_a_block doesn't exist anymore. You can't take it a second time. That's why this function has to be FnOnce, and that's what your error message is saying by cannot move out ...

I'd have to see more of your code to fully understand what's going on, but one thing to try is using a RefCell instead of a Cell. RefCell is a cell that hands out references instead of owned values. And the line that was causing you trouble is:

// With `Cell`: permanently takes the value.
self.option_transactions.take().len()

// With `RefCell`: borrows `option_transactions` temporarily.
self.option_transactions.borrow().len()
1 Like

I change the code based on you said:
I Added:

#[derive(Debug,Deserialize,Serialize)]
pub struct VecOptionTransaction {
    pub vecoptrx: Vec<OptionTransaction>
}
impl Default for VecOptionTransaction{
    fn default () ->  Self{   
        VecOptionTransaction{vecoptrx: vec![OptionTransaction::default()]}
  }
}

    let  rc_maked_transactions_of_a_block:Rc<Cell<transaction::VecOptionTransaction>>=  call_maked_trx(|| {{Rc::new(Cell::new(
            vecopt
        ))}}); // Error Line----------***-----------------------------//
      if i==1{
          //let u=rc_maked_transactions_of_a_block(vecopt);
          let y=(|| rc_maked_transactions_of_a_block(vecopt))();

            let mut genesis_block = Block::new(0, now(),vec![0; 32], rc_maked_transactions_of_a_block(vecopt).clone(), difficulty);    
            prev_hash=genesis_block.mine().unwrap().into_boxed_slice();                
            let _=&blockchain.update_with_block(genesis_block);                
        }
        else if i >1{
            let mut maked_block:Block = Block::new(i as u32, now(), prev_hash.to_vec(), rc_maked_transactions_of_a_block(vecopt).clone(), difficulty);                                     
            prev_hash=maked_block.mine().unwrap().into_boxed_slice();
            let _=&blockchain.update_with_block(maked_block);
            //println!("**maked_hash:**\n{:?}\n",&blockchain.blocks[i].prev_block_hash.clone());                
        }    
   });
                                         
    Ok(()) 
}          
//  fn pp(v:Vec<OptionTransaction>)->Rc<Cell<Vec<OptionTransaction>>>{
//     Rc::new(Cell::new(v))
//  }
// fn call_maked_trx<F>(f: F) 
//     where F: Fn() > Rc<Cell<Vec<OptionTransaction>>> {
//     f();
// }
fn call_maked_trx<F>(f: F) ->  Rc<Cell<transaction::VecOptionTransaction>>
    where F: Fn() -> Rc<Cell<transaction::VecOptionTransaction>> {
    f()
}

Error:

expected function, found `Rc<Cell<VecOptionTransaction>>`rustcE0618
factory.rs(54, 21): call expression requires function
factory.rs(49, 14): `rc_maked_transactions_of_a_block` has type `Rc<Cell<VecOptionTransaction>>`

I only skimmed this thread, but note that

  • Storing or taking &Vec<T> as a function input is unidiomatic; you can't grow the immutably borrowed Vec, so you might as well take/store &[T] instead
  • &[T] does implement Default

So you can

 pub struct Block<'a> {
     // ...
-    pub option_transactions: &'a mut Rc<Cell<&'a Vec<OptionTransaction>>>,
+    pub option_transactions: &'a mut Rc<Cell<&'a [OptionTransaction]>>,
     pub difficulty: u128, 
 }

 impl<'a> Debug for Block<'a> {
     fn fmt (&self, f: &mut Formatter) -> fmt::Result {
         let y=self.option_transactions.take();
-        write!(f, "Prev hash of {} the Block[{}]: {} at: {} trx.len: {} nonce: {}",
+        let result = write!(f, "Prev hash of {} the Block[{}]: {} at: {} trx.len: {} nonce: {}",
             // ...
-            self.option_transactions.take().len(),
+            y.len(),
             // ...
-        )
+        );
+        self.option_transactions.set(y);
+        result
 }

Playground.

Edited: To properly handle the error case.

Very Good. I change the code but I do not know how to change caller function skimmed your thread!

use std::rc::Rc;
use std::cell::{RefCell, Ref, Cell};
use std::borrow::{BorrowMut, Borrow};
use super::*;
use library_blockchain::transaction::{Value as ModelValue, OptionTransaction};
use library_blockchain::{*};
use serde_json::Value;


#[allow(dead_code)]
#[allow(unused_mut)]
pub fn blockchain_factory<F>(difficulty:u128, f : F) -> Result<(),CustomError>
    where   
    F: FnOnce()->  Result<serde_json::Value,CustomError>    
{
    let serde_values_transactions:serde_json::Value= serde_json::from_value(f().unwrap()).unwrap();
    let blocks_val:serde_json::Value=serde_values_transactions["blocks"].clone();   
    let mut blockchain=Blockchain::new();
    let mut prev_hash:Box<[u8]>=Box::default();
    let mut maked_transactions_of_a_block:Vec<OptionTransaction>=Vec::new();
        
    blocks_val[0].as_object().unwrap().into_iter().enumerate().for_each(|(i, block)| {
      //....
        for c in 1..length{
             //.....
            maked_transactions_of_a_block.push(puts);            
        }        
        
      });   
    
      
      //let dd=pp(maked_transactions_of_a_block);   
      //let  rc_maked_transactions_of_a_block=  call_maked_trx(|| dd);
        //let refcell_trx=rc_maked_transactions_of_a_block;        
        let mut c=Cell::new(maked_transactions_of_a_block.as_slice());
        let mut r=Rc::new(c);
        let mut rc=&mut r;        
      if i==1{
          //let u=rc_maked_transactions_of_a_block(vecopt);
        //  let y=(||rc_maked_transactions_of_a_block(vecopt);

            let mut genesis_block = Block::new(0, now(),vec![0; 32], rc, difficulty);    
            prev_hash=genesis_block.mine().unwrap().into_boxed_slice();                
            let _=&blockchain.update_with_block(genesis_block);                
        }
        else if i >1{
            let mut maked_block:Block = Block::new(i as u32, now(), prev_hash.to_vec(), rc, difficulty);                                     
            prev_hash=maked_block.mine().unwrap().into_boxed_slice();
            let _=&blockchain.update_with_block(maked_block);
            //println!("**maked_hash:**\n{:?}\n",&blockchain.blocks[i].prev_block_hash.clone());                
        }    
   });
                                         
    Ok(()) 
}          

OpensourceCode-Early

If you have a question, I don't understand what it is.

I did notice that my previous reply didn't really handle the error case properly. The change from last time is basically

-        write!(
+        let result = write!(
             f,
             // ...
-        )?;
+        );
         self.option_transactions.set(y);
-        Ok(())
+        result
 }

So you always restore the contents of the Cell.

I'll update my other comment now. Done, here's the playground.

1 Like