我在让miette给予一致的输出时遇到了问题。
我希望下面的程序无论传入“good”(给出我想要的花哨格式)还是“bad”(打印更像调试的错误消息)都会给予相同的输出,但有一种方法我可以打印得很漂亮,另一种方法我可以得到一个更基本的消息,我不知道为什么--这是怎么回事?
(This大量复制自本示例-注意,开头有一条dbg!()
语句,我希望与结尾的Error: ...
输出不同。)
use std::error::Error;
use miette::{Diagnostic, SourceSpan};
use miette::{NamedSource, Result as MietteResult};
use thiserror::Error;
#[derive(Error, Debug, Diagnostic)]
#[error("oops!")]
#[diagnostic(
code(oops::my::bad),
url(docsrs),
help("try doing it better next time?")
)]
struct MyBad {
// The Source that we're gonna be printing snippets out of.
// This can be a String if you don't have or care about file names.
#[source_code]
src: NamedSource,
// Snippets and highlights can be included in the diagnostic!
#[label("This bit here")]
bad_bit: SourceSpan,
}
fn this_gives_correct_formatting() -> MietteResult<()> {
let res: Result<(), MyBad> = Err(MyBad {
src: NamedSource::new("bad_file.rs", "source\n text\n here".to_string()),
bad_bit: (9, 4).into(),
});
res?;
Ok(())
}
fn main() -> Result<(), Box<dyn Error>> {
if std::env::args().nth(1).unwrap() == "bad" {
let res: Result<(), MyBad> = Err(MyBad {
src: NamedSource::new("bad_file.rs", "source\n text\n here".to_string()),
bad_bit: (9, 4).into(),
});
dbg!(&res);
res?;
Ok(())
} else if std::env::args().nth(1).unwrap() == "good" {
let res = this_gives_correct_formatting();
dbg!(&res);
res?;
Ok(())
} else {
panic!("Pass either 'good' or 'bad'");
}
}
在我的Cargo.toml
中:
[dependencies]
miette = { version = "5.5.0", features = ["fancy"] }
thiserror = "1.0.39"
会话的输出:
$ cargo run good
Finished dev [unoptimized + debuginfo] target(s) in 0.02s
Running `target/debug/rust-play good`
[src/main.rs:50] &res = Err(
MyBad {
src: NamedSource {
name: "bad_file.rs",
source: "<redacted>",
,
bad_bit: SourceSpan {
offset: SourceOffset(
9,
),
length: SourceOffset(
4,
),
},
},
)
Error: oops::my::bad (https://docs.rs/rust-play/0.1.0/rust_play/struct.MyBad.html)
× oops!
╭─[bad_file.rs:1:1]
1 │ source
2 │ text
· ──┬─
· ╰── This bit here
3 │ here
╰────
help: try doing it better next time?
$ cargo run bad
Finished dev [unoptimized + debuginfo] target(s) in 0.03s
Running `target/debug/rust-play bad`
[src/main.rs:42] &res = Err(
MyBad {
src: NamedSource {
name: "bad_file.rs",
source: "<redacted>",
,
bad_bit: SourceSpan {
offset: SourceOffset(
9,
),
length: SourceOffset(
4,
),
},
},
)
Error: MyBad { src: NamedSource { name: "bad_file.rs", source: "<redacted>", bad_bit: SourceSpan { offset: SourceOffset(9), length: SourceOffset(4) } }
1条答案
按热度按时间u3r8eeie1#
“好”的情况会产生
miette::Error
类型的错误,而“坏”的情况会产生MyBad
类型的错误,据推测,前一种类型具有Display
实现,它会产生漂亮的人类可读输出。请注意,
?
运算符不仅在Err
情况下返回错误,它还尝试使用Into::into()
进行转换。x?
通常等效于:因此,如果
x
的类型为Result<_, E>
,函数声明的返回类型为Result<_, F>
,并且E
有一个Into<F>
的实现,那么?
操作符将透明地执行此转换,这很容易被忽略,所以您没有捕捉到它是可以理解的。如果将
main()
的返回类型替换为MietteResult<()>
,则会出现编译时错误,即两个条件块的返回类型不匹配。您可以通过将“bad”情况下的错误值转换为
miette::Error
来解决此问题: