怎么写panic!像 Rust 中的宏? [英] How to write a panic! like macro in Rust?
问题描述
对于致命错误处理,我使用了 panic!
宏,但我更喜欢有一个不打印文件/行信息,只打印错误消息的宏.
我阅读了宏文档,但我的理解是有点摇晃.
我查看了 panic!
宏的来源,但它调用函数来完成它的工作,其中文件和行信息是操作的一个组成部分,所以我不能只是调整
我查看了 println!
宏,它看起来更有希望,但有两个问题我不知道如何解决.
macro_rules!死 {() =>(打印!("\n"));($fmt:expr) =>(print!(concat!($fmt, "\n")));($fmt:expr, $($arg:tt)*) =>(print!(concat!($fmt, "\n"), $($arg)*); exit(-1));}
如果我像最后一行那样输入 exit()
调用,在尝试调用它时会出现语法错误.
如果我删除 exit()
,我不会收到关于宏的投诉,但此代码无法编译:
let file = match File::open(&path) {错误(为什么)=>死!(无法打开{}:{}",显示,why.description()),好的(文件)=>文件,};
当 die!
替换为 panic!
时,它确实会编译.我认为 panic!
有一些神奇之处,它告诉编译器它永远不会返回?
首先,如果我将
exit()
调用放入,就像我在最后一行所做的那样,在尝试调用它时会出现语法错误.
那是因为宏应该扩展为单个项目,而这里扩展为两个.您可以简单地将调用包装在 {}
块中,它就会起作用……一旦您限定对 exit
的调用.
({ print!(concat!($fmt, "\n"), $($arg)*); std::process::exit(-1) });
<块引用>
如果我删除 exit()
,我不会收到关于宏的投诉,但此代码无法编译.而当 die
替换为 panic
时,它确实会编译.我认为 panic
有一些神奇之处,它告诉编译器它永远不会返回?
它没有 !
类型那么神奇.panic
和 exit
函数都返回 !
这是一个没有值的类型:它永远不能被构造.
这足以让编译器知道那些函数永远不会返回(它们会发散),因此从类型检查的角度来看,!
被认为是所有类型的子类型,并且不会返回不会引起问题.
For fatal error handling, I'm using the panic!
macro, but I would prefer to have a macro that did not print the file/line information, only the error message.
I read the macro documentation, but my understanding is a bit shaky.
I looked at the source of the panic!
macro, but it's calling functions to do its work where the file and line information is an integral part of the operation, so I can't just tweak that.
I looked at the println!
macro, which looks more promising, but I have two problems I an unaware of how to solve.
macro_rules! die {
() => (print!("\n"));
($fmt:expr) => (print!(concat!($fmt, "\n")));
($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*); exit(-1));
}
If I put the exit()
call in, as I have on the last line, I get syntax errors when trying to call it.
If I remove the exit()
, I don't get complaints about the macro, but this code fails to compile:
let file = match File::open(&path) {
Err(why) => die!("Couldn't open {}: {}", display, why.description()),
Ok(file) => file,
};
Whereas it does compile when die!
is replaced with panic!
. I assume there is some magic about panic!
which tells the compiler that it never returns?
First, if I put the
exit()
call in, as I have on the last line, I get syntax errors when trying to call it.
That is because a macro should expand to a single item, and here it expands to two. You can simply wrap the invocation in a block {}
and it'll just work... once you qualify the call to exit
.
({ print!(concat!($fmt, "\n"), $($arg)*); std::process::exit(-1) });
If I remove the
exit()
, I don't get complaints about the macro, but this code fails to compile. Whereas it does compile whendie
is replaced withpanic
. I assume there is some magic aboutpanic
which tells the compiler that it never returns?
It's not so much magic as the !
type. The panic
and exit
functions both return !
which is a type with no value: it cannot ever be constructed.
This is sufficient for the compiler to know that those functions will never return (they diverge), so from the point of view of type-checking, !
is considered a subtype of all types and does not cause issues.
这篇关于怎么写panic!像 Rust 中的宏?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!