2017-04-06 5 views
-1

致命的なエラー処理については、panic!マクロを使用していますが、ファイル/行情報を出力しないマクロを使用することをお勧めします。エラーメッセージのみです。パニックを書く方法!錆のようなマクロですか?

私はthe macro documentationを読みましたが、私の理解は少し不安です。

私はpanic!マクロのソースを見ましたが、ファイルと行の情報が操作の不可欠な部分であるため、関数を呼び出すことができます。

私はprintln!マクロを見ましたが、それはより有望に見えますが、私は解決する方法を知らない2つの問題があります。

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!についていくつかの魔法があると仮定し、それはコンパイラに返すことはないと伝えていますか?

+2

*これを呼び出すときに構文エラーが表示されます。*表示されていないと悪い** **これらのエラーは表示されません。 *このコードはコンパイルに失敗します* - あまりにも悪い**表示**どのように失敗するか。 – Shepmaster

+2

私は2番目の@Shepmasterを提供してください。[MCVE]を提供してください、私はどのタイプ/特性を持って来るのかを推測しなければなりませんでした。 –

+0

ええ、私が見た*最初のエラーは、 'exit'が範囲にないことです。だから今OPに自分自身の' exit'か何かがあるかどうか推測しなければなりませんでした。 – Shepmaster

答えて

3

まず、exit()をコールすると、最後の行にあるように、コールしようとすると構文エラーが発生します。

これは、マクロが1つの項目に展開され、ここでは2つに拡大されるためです。あなたはブロック内の呼び出しを単にラップすることができます{}これはexitへの呼び出しに適格になるとすぐに機能します。

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

私はexit()を削除した場合、私は、マクロについての苦情を得ることはありませんが、このコードはコンパイルに失敗します。一方、diepanicに置き換えられたときにコンパイルされます。私はpanicに関するいくつかの魔法があると仮定し、それはコンパイラに返さないことを伝えていますか?

!タイプと同じくらい魔法ではありません。 panicexitの両方の関数は、値を持たない型の戻り値!を返します。これは構築できません。

これは、これらの関数が決して返されない(分岐する)ことをコンパイラが知るには十分であるため、型チェックの観点から、!はすべての型のサブタイプとみなされ、問題は発生しません。

関連する問題