无法使用format_args!由于此语句末尾释放了临时值

时间:2019-05-25 11:18:44

标签: rust

我正在尝试构建自己的自定义LogRecord并将其传递到log板条箱中。

use log::RecordBuilder;

fn main() {
    let msg = format_args!("Completed: {}, Elapsed={:?}", "blah", 20);
    //let msg = format_args!("This is OK");
    let mut builder = RecordBuilder::new();
    let _log_rec = builder
        .args(msg)
        .build();
}

调用args方法遇到了一个临时的生命周期问题。错误是

 --> src/main.rs:4:28
  |
4 |     let msg = format_args!("Completed: {}, Elapsed={:?}", "blah", 20);
  |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^             - temporary value is freed at the end of this statement
  |                            |
  |                            creates a temporary which is freed while still in use
...
8 |         .args(msg)
  |               --- borrow later used here
  |
  = note: consider using a `let` binding to create a longer lived value

通常,这很容易解决-只需将临时变量放入本地变量即可。但是在这种情况下,我不知道如何解决它,因为我已经将所有可以想到的东西都放入了局部变量中(这就是为什么我不认为这个问题是其他问题的重复)。这似乎是format_args!宏所特有的。

有趣的是,如果在对{}的调用中不使用任何format_args!()占位符,问题就会消失。

实际解决方案

E_net4中的解决方案是正确的。在我的实际代码中,它不能立即起作用:

impl Drop for ExecutionTimer2 {
    fn drop(&mut self) {
        let elapsed = self.start_time.elapsed();

        let mut builder = RecordBuilder::new();
        let log_rec = builder
            .level(Level::Debug)
            .target("ExecutionTimer")
            .file(Some(self.file))
            .module_path(Some(self.module_path))
            .line(Some(self.line))
            .args(format_args!("Completed: {}, Elapsed={:?}", self.name, elapsed))
            .build();

        let logger = log::logger();
        logger.log(&log_rec);
    }
}

但是我再次应用了“内联”技术来产生这段代码,该代码可以编译:

impl Drop for ExecutionTimer2 {
    fn drop(&mut self) {
        let elapsed = self.start_time.elapsed();
        let mut builder = RecordBuilder::new();
        let logger = log::logger();

        logger.log(&
            builder
                .level(Level::Debug)
                .target("ExecutionTimer")
                .file(Some(self.file))
                .module_path(Some(self.module_path))
                .line(Some(self.line))
                .args(format_args!("Completed: {}, Elapsed={:?}", self.name, elapsed))
                .build()
        );
    }
}

1 个答案:

答案 0 :(得分:2)

预计

format_args!将在将使用返回值的确切位置被调用。

let mut builder = RecordBuilder::new();
let _log_rec = builder
    .args(format_args!("Completed: {}, Elapsed={:?}", "blah", 20))
    .build();

这是因为,宏的实现方式(对于其他构造而言)扩展为一系列给定参数的范围狭窄的值,并且Arguments值的创建只有足够长的生存期捕获它们。