Parser error recovery in `syn` for better IDE support with proc-macros
Rust Internals [Unofficial]
May 31, 2026
kpreid:
For many macros, that would mean that they produce no errors but fail to have their intended effects. That seems like it would be very confusing.
Some macros do enough code transformation that, if the inputs failing to parse caused the macro to just output the input verbatim, then that would render the IDE close to useless, e.g. I have a macro that translates:
#[hdl]
match output_integer_mode {
OutputIntegerMode::Full64 => do_mode(64, false),
OutputIntegerMode::DupLow32 => {
let shifted = shifted.cast_to_static::<UInt<32>>();
connect_any(extended, shifted | (shifted << 32));
connect(x86_sf, shifted[31]);
}
OutputIntegerMode::ZeroExt32 => do_mode(32, false),
OutputIntegerMode::SignExt32 => do_mode(32, true),
OutputIntegerMode::ZeroExt16 => do_mode(16, false),
OutputIntegerMode::SignExt16 => do_mode(16, true),
OutputIntegerMode::ZeroExt8 => do_mode(8, false),
OutputIntegerMode::SignExt8 => do_mode(8, true),
}
to:
{
type __MatchTy<T> = <T as ::fayalite::ty::Type>::MatchVariant;
let __match_expr = ::fayalite::expr::ToExpr::to_expr(&(output_integer_mode));
::fayalite::expr::check_match_expr(__match_expr, |__match_value, __infallible| {
#[allow(unused_variables)]
match __match_value {
__MatchTy::<OutputIntegerMode>::Full64 {} => match __infallible {},
__MatchTy::<OutputIntegerMode>::DupLow32 {} => match __infallible {},
__MatchTy::<OutputIntegerMode>::ZeroExt32 {} => match __infallible {},
__MatchTy::<OutputIntegerMode>::SignExt32 {} => match __infallible {},
__MatchTy::<OutputIntegerMode>::ZeroExt16 {} => match __infallible {},
__MatchTy::<OutputIntegerMode>::SignExt16 {} => match __infallible {},
__MatchTy::<OutputIntegerMode>::ZeroExt8 {} => match __infallible {},
__MatchTy::<OutputIntegerMode>::SignExt8 {} => match __infallible {},
}
});
for __match_variant in ::fayalite::module::match_(__match_expr) {
let (__match_variant, __scope) =
::fayalite::ty::MatchVariantAndInactiveScope::match_activate_scope(
__match_variant,
);
match __match_variant {
__MatchTy::<OutputIntegerMode>::Full64 => do_mode(64, false),
__MatchTy::<OutputIntegerMode>::DupLow32 => {
let shifted = shifted.cast_to_static::<UInt<32>>();
connect_any(extended, shifted | (shifted << 32));
connect(x86_sf, shifted[31]);
}
__MatchTy::<OutputIntegerMode>::ZeroExt32 => do_mode(32, false),
__MatchTy::<OutputIntegerMode>::SignExt32 => do_mode(32, true),
__MatchTy::<OutputIntegerMode>::ZeroExt16 => do_mode(16, false),
__MatchTy::<OutputIntegerMode>::SignExt16 => do_mode(16, true),
__MatchTy::<OutputIntegerMode>::ZeroExt8 => do_mode(8, false),
__MatchTy::<OutputIntegerMode>::SignExt8 => do_mode(8, true),
}
}
}
Discussion in the ATmosphere