怎么写恐慌!像Rust中的宏?

时间:2017-04-06 11:48:31

标签: rust

对于致命的错误处理,我正在使用panic!宏,但我更喜欢有一个没有打印文件/行信息的宏,只有错误信息。

我看了the macro documentation,但我的理解有点不稳定。

我查看了panic!宏的来源,但它正在调用函数来完成它的工作,其中文件和行信息是操作的一个组成部分,所以我不能只调整它。

我查看了println!宏,看起来更有前景,但我有两个问题,我不知道如何解决。

macro_rules! die {
    () => (print!("\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) {
    Err(why) => die!("Couldn't open {}: {}", display, why.description()),
    Ok(file) => file,
};

die!替换为panic!时,它会编译。我假设有一些关于panic!的魔法告诉编译器它永远不会返回?

1 个答案:

答案 0 :(得分:3)

  

首先,如果我将exit()调用放在最后一行,就像我在调用它时遇到语法错误一样。

这是因为宏应该扩展为单个项目,并在此处扩展为两个。您可以简单地将调用包装在一个{}块中,只要您将调用限定为exit,它就会正常工作。

({ print!(concat!($fmt, "\n"), $($arg)*); std::process::exit(-1) });
  

如果我删除exit(),我就不会抱怨宏,但此代码无法编译。而die替换为panic时会编译。我假设有一些关于panic的魔法告诉编译器它永远不会返回?

它不像!类型那么神奇。 panicexit函数都返回!这是一个没有值的类型:它无法构造。

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