При использовании Future
в Rust обычно передается право собственности на объект (например, соединение, обработанные данные и т. д.) между последовательными этапами обработки, реализованными с помощью лямбда-выражений. Я понимаю концепцию и сделал это уже много без проблем.
Я пытаюсь сделать то же самое, но на этот раз частичным результатом является ссылочный тип. Я не могу убедить средство проверки заимствования Rust принять следующий (слишком упрощенный) код:
extern crate futures;
use futures::prelude::*;
// Parsed data with attribute values that might be not owned, only referenced
trait Data<'a> {
fn attribute<'s, 'n>(&'s self, name: &'n str) -> &'a str;
}
fn async_load_blob() -> Box<Future<Item = Vec<u8>, Error = ()>> {
Box::new(futures::future::err(())) // Dummy impl to compile
}
fn parse<'a>(_blob: &'a [u8]) -> Result<Box<Data<'a> + 'a>, ()> {
Err(()) // Dummy impl just to compile fine
}
fn resolve_attribute<'a, 'n>(
name: &'n str,
) -> Box<Future<Item = (Vec<u8>, &'a str), Error = ()> + 'a> {
let owned_name = name.to_owned(); // move attribute name into lambda
let fut = async_load_blob().and_then(move |blob| {
// COMPILE ERROR: how to convince borrow checker that the
// owned data is properly moved out together with the reference?
let data_res = parse(blob.as_slice());
match data_res {
Ok(data) => {
let attr = data.attribute(owned_name.as_str());
futures::future::ok((blob, attr))
}
Err(e) => futures::future::err(e),
}
});
Box::new(fut)
}
Проблемная часть — это кортеж, возвращенный в успешной ветке. Если я попытаюсь вернуть (таким образом, удалить) собственные данные из области видимости, средство проверки заимствования не сможет понять корреляцию между ними и сообщит об ошибке.
Я также пытался использовать Rc
и другие трюки уже и каждый раз терпел неудачу. Можно ли это выразить и исправить в Rust, или вся концепция в корне ошибочна и должна быть реализована по-другому, например. возвращая атрибуты как собственные значения, таким образом копируя вместо ссылки?