为什么Rust编译器不认为Box<FileRotate<_>>是Box<(dyn std::io::Write + Send + 'static)>的有效实现?

3

我正在尝试将旋转日志与 fern 结合使用,通过将一个打包的来自 file-rotate crate 的 FileRotate 实例链接到 fernDispatch 实例上,但是似乎无法满足编译器的要求。下面是代码片段:

let log= Box::new(
    FileRotate::new(
        "log/output.log",
        CountSuffix::new(2),
        ContentLimit::Lines(10),
        Compression::None));

fern::Dispatch::new()
    .level(LevelFilter::Debug)
    .chain(log)
    .apply()?;

编译器发生错误,具体如下:

error[E0277]: the trait bound `fern::Output: From<Box<FileRotate<CountSuffix>>>` is not satisfied
   --> src/main.rs:101:16
    |
101 |         .chain(log)
    |          ----- ^^^ the trait `From<Box<FileRotate<CountSuffix>>>` is not implemented for `fern::Output`
    |          |
    |          required by a bound introduced by this call
    |
    = help: the following implementations were found:
              <fern::Output as From<&'static (dyn log::Log + 'static)>>
              <fern::Output as From<Box<(dyn log::Log + 'static)>>>
              <fern::Output as From<Box<(dyn std::io::Write + Send + 'static)>>>
              <fern::Output as From<Dispatch>>
            and 6 others
    = note: required because of the requirements on the impl of `Into<fern::Output>` for `Box<FileRotate<CountSuffix>>`
note: required by a bound in `Dispatch::chain`
   --> /Users/l203663/.cargo/registry/src/github.com-1ecc6299db9ec823/fern-0.6.0/src/builders.rs:195:21
    |
195 |     pub fn chain<T: Into<Output>>(mut self, logger: T) -> Self {
    |                     ^^^^^^^^^^^^ required by this bound in `Dispatch::chain`

然而,FileRotate 结构体实现了 WriteSend 两个 trait,如此文档所述(这里)(这里)
编译器提供的最接近的实现是我认为:
From<Box<(dyn std::io::Write + Send + 'static)>>
  • 这个问题是否由 'static 生命周期引起?如果是的话,我该如何解决?
  • 如果不是,可能会导致这个问题的原因是什么?

正在使用的 Crates:

log = "0.4.14"
fern = "0.6.0"
file-rotate = "0.5.3" 

1
明确注释 log 的类型为 Box<(dyn std::io::Write + Send + 'static)> 是否提供了任何有用的信息? - Solomon Ucko
1
谢谢@SolomonUcko,看起来这个方法可行。然而,我发现投票答案中的as结构更加简洁。 - keldonin
1个回答

4

我不确定这是否是整个问题(因为没有使用 fern ),但由于 chain() 的输入参数是泛型的,它不会自动将你的 Box<FileRotate> 强制转换为 Box<dyn Write + Send>,因此你必须显式地进行类型转换:

.chain(log as Box<dyn Write + Send>)

您不需要指定'static,因为这是所有Box<dyn ...>(但不包括&dyn ...)的默认值。


1
正如您所提到的,chain方法具有以下签名:pub fn chain<T: Into<Output>>(self, logger: T) -> Self。您关于Rust无法从通用类型强制转换的说法是有道理的,尽管我在在线文档中找不到它。我可能已经忽略了它。 - keldonin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接