Отлично, теперь переходим к самому вкусному: написанию макроса! Нам нужно разобрать 
match, так что начнём с этого:
macro_rules! ascii_case_insensitive {
    (match $value:ident {
        $(... ,)*
        _ => $catch_all:expr $(,)?
    }) => { ... }
}
А теперь на минуту остановимся и подумаем, что из себя представляет паттерн, который мы пытаемся разобрать. В 
прошлый раз я совершенно упустил из виду, что обычно мы можем перечислить несколько паттернов, разделив их 
|, равно как и то, что паттерн может также предваряться 
|. Таким образом, корректный кусок макроса для распознавания паттернов должен выглядеть так:
$(|)? $($pattern:literal)|+
$(|)? отвечает за опциональную черту в начале. 
$pattern:literal говорит, что 
$pattern — это литерал, а 
$(...)|+ говорит о том, что то, что внутри скобок, повторяется 
один или более раз, и что повторы разделены 
|. Но постойте-ка, есть же ещё и опциональное охранное выражение! С учётом всего этого паттерн для одной ветви принимает такой вид:
$(|)? $($pattern:literal)|+ $(if $condition:expr)? => $arm:expr,
Отлично, с разбором мы справились (правда, всё так же упустив возможность привязать имена к паттернам). Что мы со всем этим делаем? Мы проверяем, что все строки в нижнем регистре:
#[deny(const_err)]
const _ARE_ALL_ASCII_LOWERCASE: [(); 1] = [(); are_all_ascii_lowercase(&[$($($pattern,)+)*]) as _];
И что они все разные:
#[allow(dead_code)]
fn non_repeating(s: &str) {
    #[deny(unreachable_patterns)]
    match s {
        $($(| $pattern)+ => (),)*
        _ => (),
    }
}
А что нам делать непосредственно самой проверкой? Мы проверяем, что значение равно, за вычетом ASCII-регистра, одному из паттернов... И что охранное выражение также справедливо, если оно есть:
x if ($(x.eq_ignore_ascii_case($pattern))||+) $(&& $condition)? => $arm,
Обратите внимание, здесь мы повторяем (
+) выражения для паттернов, разделив их 
||.
Что ж, давайте опробуем макрос в действии:
#[derive(Debug)]
enum Example {
    Foo,
    Bar,
    FourtyTwo,
}
impl std::str::FromStr for Example {
    type Err = String;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Ok(ascii_case_insensitive!(match s {
            "foo" => Self::Foo,
            "bar" if s.as_bytes()[0].is_ascii_lowercase() => Self::Bar,
            "fourtytwo" | "fourty_two" | "42" => Self::FourtyTwo,
            _ => return Err(s.into()),
        }))
    }
}
fn main() {
    let inputs = [
        "foo",
        "Foo",
        "FOO",
        "bar",
        "bAr",
        "BAR", // ошибка, первый символ в верхнем регистре
        "fourtytwo",
        "Fourtytwo",
        "FOURTYTWO",
        "fourty_two",
        "fOuRtY_tWo",
        "42",
        "bogus",
    ];
    for &input in &inputs[..] {
        println!("{:?}", input.parse::<Example>());
    }
}
Эта программа выдаёт следующее:
Ok(Foo)
Ok(Foo)
Ok(Foo)
Ok(Bar)
Ok(Bar)
Err("BAR")
Ok(FourtyTwo)
Ok(FourtyTwo)
Ok(FourtyTwo)
Ok(FourtyTwo)
Ok(FourtyTwo)
Ok(FourtyTwo)
Err("bogus")
...как и ожидалось. Что будет, если мы попытаемся сделать два одинаковых паттерна? Скажем, так:
            ...
            "foo" | "foo" => Self::Foo,
            ...
Компилятор жалуется:
error: unreachable pattern
А если один из паттернов не в нижнем регистре:
            ...
            "Foo" => Self::Foo,
            ...
то компилятор опять жалуется:
error[E0308]: mismatched types
Всё работает, как и ожидалось! Как всегда, весь код в 
гисте.