使用mpd的Query :: and时一次不能多次借用xxx作为可变变量

时间:2019-11-15 13:35:51

标签: rust

我正在尝试实现以下功能,该功能需要3个可选输入并从rust-mpd板条箱中从mpd客户端获取搜索结果。

fn load(
    &mut self,
    track: &Option<String>,
    artist: &Option<String>,
    album: &Option<String>
) -> Result<(), &'static str>{
    println!("mpd, load method is invoked with:");
    let mut query = Query::new();

    if let Some(s) = track {
        println!("  track: {}", &s);
        query.and(Term::Tag(Cow::Borrowed("track")), s);
    }

    if let Some(s) = artist {
        println!("  artist: {}", &s);
        query.and(Term::Tag(Cow::Borrowed("artist")), s);
    }

    if let Some(s) = album {
        println!("  album: {}", &s);
        query.and(Term::Tag(Cow::Borrowed("album")), s);
    }

    //let musics = self.client.search(&query, Window(None));
    let musics = self.client.search(&query, (1,2));
    println!("Search result: {:?}", musics);

    Ok(())
}

但是,当我尝试编译时,它告诉我:

error[E0499]: cannot borrow `query` as mutable more than once at a time
  --> src/player/mpd.rs:62:13
   |
57 |             query.and(Term::Tag(Cow::Borrowed("track")), s);
   |             ----- first mutable borrow occurs here
...
62 |             query.and(Term::Tag(Cow::Borrowed("artist")), s);
   |             ^^^^^
   |             |
   |             second mutable borrow occurs here
   |             first borrow later used here

error[E0499]: cannot borrow `query` as mutable more than once at a time
  --> src/player/mpd.rs:67:13
   |
62 |             query.and(Term::Tag(Cow::Borrowed("artist")), s);
   |             ----- first mutable borrow occurs here
...
67 |             query.and(Term::Tag(Cow::Borrowed("album")), s);
   |             ^^^^^
   |             |
   |             second mutable borrow occurs here
   |             first borrow later used here

error[E0502]: cannot borrow `query` as immutable because it is also borrowed as mutable
  --> src/player/mpd.rs:71:41
   |
67 |             query.and(Term::Tag(Cow::Borrowed("album")), s);
   |             ----- mutable borrow occurs here
...
71 |         let musics = self.client.search(&query, (1,2));
   |                                         ^^^^^^
   |                                         |
   |                                         immutable borrow occurs here
   |                                         mutable borrow later used here

如果我的方法有误,应该如何实现相同的功能?

2 个答案:

答案 0 :(得分:3)

乍一看,可变借用应该以{{1​​}}块结尾,这将允许后续借用。但是,if let中存在一个错误,该错误会导致借用延长到rust-mpd的整个生命周期:Query::and方法声明为:

query

对查询的嵌入生存期都使用相同的生存期fn and<'b: 'a, V: 'b + Into<Cow<'b, str>>>( &'a mut self, // <- Note the 'a lifetime here term: Term<'b>, value: V) -> &'a mut Query<'a> // <- Note the **two** 'a lifetimes here 。该方法应这样声明:

'a

您应该向fn and<'b: 'a, V: 'b + Into<Cow<'b, str>>>( &mut self, term: Term<'b>, value: V) -> &mut Query<'a> 报告一个错误。

答案 1 :(得分:1)

如果您只想在非理想状态下使用库,则可以迭代地更新对Query的可变引用,而不是直接使用它:

use mpd::{Query, Term}; // 0.0.12
use std::borrow::Cow;

fn load(
    track: &Option<String>,
    artist: &Option<String>,
    album: &Option<String>,
) -> Result<(), &'static str> {
    let mut query = Query::new();
    let mut query = &mut query;

    if let Some(s) = track {
        query = query.and(Term::Tag(Cow::Borrowed("track")), s);
    }

    if let Some(s) = artist {
        query = query.and(Term::Tag(Cow::Borrowed("artist")), s);
    }

    if let Some(s) = album {
        query = query.and(Term::Tag(Cow::Borrowed("album")), s);
    }

    let mut client = mpd::Client::new(std::fs::File::open("/tmp/junk").unwrap()).unwrap();
    let _musics = client.search(&query, (1, 2));

    Ok(())
}