0
votes

I have a chain of Rust futures which needs to take ownership of a variable outside of the future, however, I don't understand how I can pass the ownership of the variable into one of the chains.

The issue seems to be on the 'address' variable being used by 'let domain = DNSNameRef::try_from_ascii_str(&address).unwrap()', as replacing &address with a string will make it work.

I have looked up putting the variable into a Arc/Mutex and Rc/RefCell, but they don't seem to help (maybe I'm just doing it wrong). I feel like I understand that I need to basically give ownership of all the variable to future closures, since they are going to outlive the current function, but I don't have a clue how to do that...

let address = inner.address().unwrap();

state.check_net(&address)?;

let op = resolve_addr(&address)
    .and_then(move |socket_address| {
      TcpStream::connect(&socket_address)
        .map_err(ErrBox::from)
    })
    .and_then(move |socket| {
      let mut config = ClientConfig::new();
      config
        .root_store
        .add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS);
      let config = TlsConnector::from(Arc::new(config));
      let domain = DNSNameRef::try_from_ascii_str(&address).unwrap();
      config.connect(domain, socket)
        .map_err(ErrBox::from)
    })
    .and_then(move |tls_stream| new_tls_conn(cmd_id, tls_stream));
  if base.sync() {
    let buf = op.wait()?;
    Ok(Op::Sync(buf))
  } else {
    Ok(Op::Async(Box::new(op)))
  }

And the error I get:

error[E0621]: explicit lifetime required in the type of `base`
    --> ../../cli/ops.rs:1748:18
     |
1716 |   base: &msg::Base<'_>,
     |         -------------- help: add explicit lifetime `'static` to the type of `base`: `&msg::Base<'static>`
...
1748 |     Ok(Op::Async(Box::new(op)))
     |                  ^^^^^^^^^^^^ lifetime `'static` required
1

1 Answers

0
votes

I seem to have gotten it to work by basically cloning the address variable with address.to_owned() like so:

let address = inner.address().unwrap();
let domain = address.to_owned();

state.check_net(&address)?;

let op = resolve_addr(&address)
    .and_then(move |socket_address| {
      TcpStream::connect(&socket_address)
        .map_err(ErrBox::from)
    })
    .and_then(move |socket| {
      let mut config = ClientConfig::new();
      config
        .root_store
        .add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS);
      let config = TlsConnector::from(Arc::new(config));
      let domain = DNSNameRef::try_from_ascii_str(&domain).unwrap();
      config.connect(domain, socket)
        .map_err(ErrBox::from)
    })
    .and_then(move |tls_stream| new_tls_conn(cmd_id, tls_stream));
if base.sync() {
    let buf = op.wait()?;
    Ok(Op::Sync(buf))
} else {
    Ok(Op::Async(Box::new(op)))
}

I'm not too sure why this works though. If anyone could explain that would be greatly appreciated!