コンパイルエラーとなるべきテスト項目の作成方法について。

背景情報

コンパイルエラーとなるかの確認は、型により自明なため、殆どの場合は不要である。

しかし稀に、ポカヨケ確認、不用意な修正防止、などのために必要になる。

特に Rustでは、マクロにおける入力構文のエラー検証に使える。

実現方法

以下の知識を組み合わせる。

サンプル

以下では、for_loop マクロが for-in 構文を模倣している。ここでループアイテムは元の構文と同じくパターンで、それは論駁不可能でなければならない。関数 _dummy_for_doc_test の文書化テストでは、それについての確認が含まれている (もしマクロを while-let 構文で実装していれば、ここでエラーになっただろう)。


/// For-loop macro.
///
/// ```
/// # use rust_test::for_loop;
/// let values = vec![Some(1), Some(2), None];
/// let mut summary = 0;
/// for_loop!((&x in values.iter()) {
///     summary += x.unwrap_or(0);
/// });
///
/// assert_eq!(summary, 3);
/// ```
#[macro_export]
macro_rules! for_loop {
    (($item:pat in $iter:expr) $block:block) => {{
        let mut iter = IntoIterator::into_iter($iter);
        loop {
            match Iterator::next(&mut iter) {
                None => break,
                Some($item) => $block,
            }
        }
    }};
}

/// Compilation error test.
///
/// Loop item should be irrefutable pattern.
///
/// ```compile_fail
/// # use rust_test::for_loop;
/// let values = vec![Some(1), Some(2), None];
/// let mut summary = 0;
/// for_loop!((&Some(x) in values.iter()) {
///     summary += x;
/// });
/// ```
#[doc(hidden)]
fn _dummy_for_doc_test() {
    // nop.
}