Hi all I am getting "cannot move out of an Arc
in here:
error[E0507]: cannot move out of an `Arc`
--> src/fetch/fetch_job.rs:94:18
|
94 | .zip(lock.clone().uri_iter)
| ^^^^^^^^^^^^^^^^^^^^^ cannot move out of an `Arc`
let mut lock = Arc::new(self.clone());
let requests: Vec<_> = (0..self.chunk)
.zip(lock.clone().uri_iter)
not sure how to fix this.
2 Likes
You can use *lock
to dereference the Arc and get at the value inside it. Then you can clone that value, instead of cloning the Arc:
.zip((*lock).clone().uri_iter)
Though it might make more sense in this case to clone only the one field you need, instead of the whole struct:
.zip(lock.uri_iter.clone())
1 Like
error[E0507]: cannot move out of borrowed content
--> src/fetch/fetch_job.rs:94:18
|
94 | .zip((*lock).clone().uri_iter)
| ^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
let mut lock = Arc::new(self.clone());
let requests: Vec<_> = (0..self.chunk)
.zip((*lock).clone().uri_iter)
.map(move |(_, uri)| {
What is the type of self
? Is it a reference? (Does this function take an &self
argument?) Does the Self
type implement Clone
?
impl<'a, S, I> WeatherStream<'a, S, I>
where
S: StoreWeather ,
I: Iterator<Item = Uri> + Send,
{
fn new(uri_iter: I, chunk: u64, duration: Duration, storage_client: S) -> Self {
Self {
uri_iter,
chunk,
interval: Interval::new_interval(duration),
fetch_future: None,
storage_client: Arc::new(Mutex::new(Box::new(storage_client))),
time_pass: TimePass::Ready,
}
}
//change number of requests to a parameter.
pub fn fetch_chunk(&self) -> impl Future<Item = bool, Error = ()> {
let client = build_https_client().unwrap(); //TODO catch error
let chunk = Arc::new(self.chunk);
let mut lock = Arc::new(self.clone());
let requests: Vec<_> = (0..self.chunk)
.zip(lock.uri_iter.clone())
.map(move |(_, uri)| {
client
.clone()
.get(uri)
.map(|res| {
println!("Response: {}", res.status());
println!("Headers: {:#?}", res.headers());
})
.map_err(|_| ())
})
.collect();
future::join_all(requests)
.map(move |res: Vec<()>| res.len() as u64 == *chunk)
.map_err(|_| ())
}
}
No self does not implement clone, that is why I am using Arc
Then you should probably clone the member variable (uri_iter
) instead of trying to clone the unclonable inner lock.
.zip(lock.uri_iter.clone())
error[E0599]: no method named `clone` found for type `I` in the current scope
--> src/fetch/fetch_job.rs:94:32
|
94 | .zip(lock.uri_iter.clone())
| ^^^^^
|
= help: items from traits can only be used if the trait is implemented and in scope
= note: the following trait defines an item `clone`, perhaps you need to implement it:
candidate #1: `std::clone::Clone`
= help: did you mean `cloned`?
but I did implement it:
#[derive(Clone,Copy)]
pub struct DarkSky {
pub base: &'static str,
pub coordinates: &'static str,
pub start: DateTime<Local>,
pub end: DateTime<Local>,
pub current: DateTime<Local>,
}
impl DarkSky {
pub fn new(
base: &'static str,
coordinates: &'static str,
start: DateTime<Local>,
end: DateTime<Local>,
) -> Self {
Self {
base,
coordinates,
start,
end,
current: start,
}
}
}
impl Iterator for DarkSky {
type Item = hyper::Uri;
fn next(&mut self) -> Option<Self::Item> {
let date = self.current - chrono::Duration::days(1);
if date > self.end {
None
} else {
self.current = date.clone();
Some(
format!("{}/{} {}", self.base, self.coordinates, date.timestamp())
.parse::<hyper::Uri>()
.unwrap(),
)
}
}
}
self
here has type &WeatherStream
. When you write self.clone()
, since it can't clone the WeatherStream
, it clones the &WeatherStream
, returning an identical &WeatherStream
value. You then put this in an Arc, creating an Arc<&WeatherStream>
. The Arc doesn't add anything here. (I'm also not clear why chunk
is an Arc
.)
If you want to be able to create multiple copies of the uri_iter
field, you will at least need to require a Clone
bound on its type I
. Or perhaps you can instead take &mut self
and return a future that captures a mutable reference to self.uri_iter
so you do not need to clone it.
Or your function could take self: Arc<Self>
if you want it to be able to return a future with shared ownership of the whole WeatherStream. In this case you'll need to add some more Mutex or RwLock for fields like the iterator that need to be mutable.
4 Likes
Ok makes sense I will try some things around and will let you know of the progress
Okay so here is what I did:
//change number of requests to a parameter.
pub fn fetch_chunk(self: Arc<Self>) -> impl Future<Item = bool, Error = ()> + 'a {
let client = build_https_client().unwrap(); //TODO catch error
let iter = self.clone().uri_iter.lock().unwrap();
let requests: Vec<_> = (0..self.chunk)
.zip(*iter)
.map(move |(_, uri)| {
client
.clone()
.get(uri)
.map(|res| {
println!("Response: {}", res.status());
println!("Headers: {:#?}", res.headers());
})
.map_err(|_| ())
})
.collect();
future::join_all(requests)
.map(move |res: Vec<()>| res.len() as u64 == self.clone().chunk)
.map_err(|_| ())
}
}
impl<'a, S, I> Stream for WeatherStream<'a, S, I>
where
S: StoreWeather + 'a,
I: Iterator<Item = Uri> + Send + 'a,
{
type Item = bool;
type Error = ();
fn poll(&mut self) -> Poll<Option<Self::Item>, ()> {
loop {
match self.time_pass {
TimePass::Ready => {
if let Some(_) = self.fetch_future {
try_ready!(self.fetch_future.poll().map_err(|_| ()));
} else {
self.fetch_future: Option<Box<Future<Item=bool, Error=()> + 'a + Send>> = Some(Box::new(self.fetch_chunk()));
try_ready!(self.fetch_future.poll().map_err(|_| ()));
}
self.time_pass = TimePass::Waiting;
self.fetch_future = None;
}
TimePass::Waiting => {
match self.interval.poll() {
Ok(Async::Ready(value)) => {
self.time_pass = TimePass::Ready;
return Ok(Async::Ready(Some(false)));
}
Ok(Async::NotReady) => return Ok(Async::NotReady),
Err(err) => return Err(()),
}
}
};
}
}
}
and I get this:
error[E0599]: no method named `fetch_chunk` found for type `std::sync::Arc<&mut fetch::fetch_job::WeatherStream<'a, S, I>>` in the current scope
--> src/fetch/fetch_job.rs:126:128
|
126 | self.fetch_future: Option<Box<Future<Item=bool, Error=()> + 'a + Send>> = Some(Box::new(Arc::new(self).fetch_chunk()));
| ^^^^^^^^^^^
error: aborting due to previous error