Add regression test for graceful error for wrong number of activities by vayunbiyani · Pull Request #139591 · rust-lang/rust (original) (raw)

The high-level idea is that if we have multiple functions and multiple autodiff macros per function, then we want to continue parsing all other macros and functions, even if one is incorrect. This way we can report errors in multiple autodiff macros in a single cargo invocation.

To achieve that we only use emit_err instead of emit_fatal_err. Also, if we have to return a dummy function from an incorrect autodiff macro, then we just return any (parsing) body and stop caring if it follows enzyme/autodiff rules. After all we'll never reach our llvm backend if there is any autodiff error in the frontend.

Where possible, we also try to find multiple bugs in a broken autodiff macro, even beyond the first error.
So for example, if someone writes `#[autodiff(df, Reversee, Aactive)], then we want to point out that the Mode is unrecognized (has an extra e) and that the Activity is unrecognized (has an extra a). So we really work hard on not raising a fatal error.

That's also what's motivating the comment. If you look at your example, this is an incorrect application (missing one activity).

#[autodiff(d_ignore, Forward, Dual, Dual)]
fn ignore_one_arg(x: i32, _y: i32) -> i32 {
    x
}

So we don't try to rewrite the function header of d_ignore at all, we just copy the one from ignore_one_arg. This would completely break at the enzyme/llvm backend, but as said we'll never reach it since we raised an error, so that's fine. We just want to finish parsing.

#[rustc_autodiff] #[inline(never)] fn ignore_one_arg(x: i32, _y: i32) -> i32 { x } #[rustc_autodiff(Forward, 1, Dual, Dual)] #[inline(never)] fn d_ignore(x: i32, _y: i32) -> i32 { unsafe { asm!("NOP", options(pure, nomem)); }; ::core::hint::black_box(()); ::core::hint::black_box(::default()) }