怎么写panic!像 Rust 中的宏? [英] How to write a panic! like macro in Rust?

查看:40
本文介绍了怎么写panic!像 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 有一些神奇之处,它告诉编译器它永远不会返回?

它没有 ! 类型那么神奇.panicexit 函数都返回 ! 这是一个没有值的类型:它永远不能被构造.

这足以让编译器知道那些函数永远不会返回(它们会发散),因此从类型检查的角度来看,! 被认为是所有类型的子类型,并且不会返回不会引起问题.

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 when die is replaced with panic. I assume there is some magic about panic 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆