diff --git a/src/expr.rs b/src/expr.rs index 8417475cab..3d89cdd01d 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -224,8 +224,27 @@ ast_enum_of_structs! { /// A yield expression: `yield expr`. Yield(ExprYield), + // The following is the only supported idiom for exhaustive matching of + // this enum. + // + // match expr { + // Expr::Array(e) => {...} + // Expr::Assign(e) => {...} + // ... + // Expr::Yield(e) => {...} + // + // #[cfg(test)] + // Expr::TestExhaustive => unimplemented!(), + // #[cfg(not(test))] + // _ => { /* some sane fallback */ } + // } + // + // This way we fail your tests but don't break your library when adding + // a variant. You will be notified by a test failure when a variant is + // added, so that you can add code to handle it, but your library will + // continue to compile and work for downstream users in the interim. #[doc(hidden)] - __Nonexhaustive, + TestExhaustive, } } @@ -804,7 +823,7 @@ impl Expr { | Expr::TryBlock(ExprTryBlock { attrs, .. }) | Expr::Yield(ExprYield { attrs, .. }) => mem::replace(attrs, new), Expr::Verbatim(_) => Vec::new(), - Expr::__Nonexhaustive => unreachable!(), + Expr::TestExhaustive => unreachable!(), } } } @@ -2303,7 +2322,7 @@ pub(crate) mod parsing { Pat::Type(_) => unreachable!(), Pat::Verbatim(_) => {} Pat::Wild(pat) => pat.attrs = attrs, - Pat::__Nonexhaustive => unreachable!(), + Pat::TestExhaustive => unreachable!(), } Ok(pat) } @@ -2654,7 +2673,7 @@ pub(crate) mod parsing { } for part in float_repr.split('.') { let index = crate::parse_str(part).map_err(|err| Error::new(float.span(), err))?; - let base = mem::replace(e, Expr::__Nonexhaustive); + let base = mem::replace(e, Expr::TestExhaustive); *e = Expr::Field(ExprField { attrs: Vec::new(), base: Box::new(base), diff --git a/src/item.rs b/src/item.rs index c5083d0501..349a096192 100644 --- a/src/item.rs +++ b/src/item.rs @@ -71,8 +71,27 @@ ast_enum_of_structs! { /// Tokens forming an item not interpreted by Syn. Verbatim(TokenStream), + // The following is the only supported idiom for exhaustive matching of + // this enum. + // + // match expr { + // Item::Const(e) => {...} + // Item::Enum(e) => {...} + // ... + // Item::Verbatim(e) => {...} + // + // #[cfg(test)] + // Item::TestExhaustive => unimplemented!(), + // #[cfg(not(test))] + // _ => { /* some sane fallback */ } + // } + // + // This way we fail your tests but don't break your library when adding + // a variant. You will be notified by a test failure when a variant is + // added, so that you can add code to handle it, but your library will + // continue to compile and work for downstream users in the interim. #[doc(hidden)] - __Nonexhaustive, + TestExhaustive, } } @@ -357,7 +376,7 @@ impl Item { | Item::Macro(ItemMacro { attrs, .. }) | Item::Macro2(ItemMacro2 { attrs, .. }) => mem::replace(attrs, new), Item::Verbatim(_) => Vec::new(), - Item::__Nonexhaustive => unreachable!(), + Item::TestExhaustive => unreachable!(), } } } @@ -553,8 +572,27 @@ ast_enum_of_structs! { /// Tokens in an `extern` block not interpreted by Syn. Verbatim(TokenStream), + // The following is the only supported idiom for exhaustive matching of + // this enum. + // + // match expr { + // ForeignItem::Fn(e) => {...} + // ForeignItem::Static(e) => {...} + // ... + // ForeignItem::Verbatim(e) => {...} + // + // #[cfg(test)] + // ForeignItem::TestExhaustive => unimplemented!(), + // #[cfg(not(test))] + // _ => { /* some sane fallback */ } + // } + // + // This way we fail your tests but don't break your library when adding + // a variant. You will be notified by a test failure when a variant is + // added, so that you can add code to handle it, but your library will + // continue to compile and work for downstream users in the interim. #[doc(hidden)] - __Nonexhaustive, + TestExhaustive, } } @@ -641,8 +679,27 @@ ast_enum_of_structs! { /// Tokens within the definition of a trait not interpreted by Syn. Verbatim(TokenStream), + // The following is the only supported idiom for exhaustive matching of + // this enum. + // + // match expr { + // TraitItem::Const(e) => {...} + // TraitItem::Method(e) => {...} + // ... + // TraitItem::Verbatim(e) => {...} + // + // #[cfg(test)] + // TraitItem::TestExhaustive => unimplemented!(), + // #[cfg(not(test))] + // _ => { /* some sane fallback */ } + // } + // + // This way we fail your tests but don't break your library when adding + // a variant. You will be notified by a test failure when a variant is + // added, so that you can add code to handle it, but your library will + // continue to compile and work for downstream users in the interim. #[doc(hidden)] - __Nonexhaustive, + TestExhaustive, } } @@ -731,8 +788,27 @@ ast_enum_of_structs! { /// Tokens within an impl block not interpreted by Syn. Verbatim(TokenStream), + // The following is the only supported idiom for exhaustive matching of + // this enum. + // + // match expr { + // ImplItem::Const(e) => {...} + // ImplItem::Method(e) => {...} + // ... + // ImplItem::Verbatim(e) => {...} + // + // #[cfg(test)] + // ImplItem::TestExhaustive => unimplemented!(), + // #[cfg(not(test))] + // _ => { /* some sane fallback */ } + // } + // + // This way we fail your tests but don't break your library when adding + // a variant. You will be notified by a test failure when a variant is + // added, so that you can add code to handle it, but your library will + // continue to compile and work for downstream users in the interim. #[doc(hidden)] - __Nonexhaustive, + TestExhaustive, } } @@ -1695,7 +1771,7 @@ pub mod parsing { ForeignItem::Type(item) => &mut item.attrs, ForeignItem::Macro(item) => &mut item.attrs, ForeignItem::Verbatim(_) => return Ok(item), - ForeignItem::__Nonexhaustive => unreachable!(), + ForeignItem::TestExhaustive => unreachable!(), }; attrs.extend(item_attrs.drain(..)); *item_attrs = attrs; @@ -2173,7 +2249,7 @@ pub mod parsing { TraitItem::Method(item) => &mut item.attrs, TraitItem::Type(item) => &mut item.attrs, TraitItem::Macro(item) => &mut item.attrs, - TraitItem::Verbatim(_) | TraitItem::__Nonexhaustive => unreachable!(), + TraitItem::Verbatim(_) | TraitItem::TestExhaustive => unreachable!(), }; attrs.extend(item_attrs.drain(..)); *item_attrs = attrs; @@ -2504,7 +2580,7 @@ pub mod parsing { ImplItem::Type(item) => &mut item.attrs, ImplItem::Macro(item) => &mut item.attrs, ImplItem::Verbatim(_) => return Ok(item), - ImplItem::__Nonexhaustive => unreachable!(), + ImplItem::TestExhaustive => unreachable!(), }; attrs.extend(item_attrs.drain(..)); *item_attrs = attrs; diff --git a/src/pat.rs b/src/pat.rs index 5381076944..0b7de0b746 100644 --- a/src/pat.rs +++ b/src/pat.rs @@ -72,8 +72,27 @@ ast_enum_of_structs! { /// A pattern that matches any value: `_`. Wild(PatWild), + // The following is the only supported idiom for exhaustive matching of + // this enum. + // + // match expr { + // Pat::Box(e) => {...} + // Pat::Ident(e) => {...} + // ... + // Pat::Wild(e) => {...} + // + // #[cfg(test)] + // Pat::TestExhaustive => unimplemented!(), + // #[cfg(not(test))] + // _ => { /* some sane fallback */ } + // } + // + // This way we fail your tests but don't break your library when adding + // a variant. You will be notified by a test failure when a variant is + // added, so that you can add code to handle it, but your library will + // continue to compile and work for downstream users in the interim. #[doc(hidden)] - __Nonexhaustive, + TestExhaustive, } } diff --git a/src/ty.rs b/src/ty.rs index c9546a1283..5f1ac54726 100644 --- a/src/ty.rs +++ b/src/ty.rs @@ -63,8 +63,27 @@ ast_enum_of_structs! { /// Tokens in type position not interpreted by Syn. Verbatim(TokenStream), + // The following is the only supported idiom for exhaustive matching of + // this enum. + // + // match expr { + // Type::Array(e) => {...} + // Type::BareFn(e) => {...} + // ... + // Type::Verbatim(e) => {...} + // + // #[cfg(test)] + // Type::TestExhaustive => unimplemented!(), + // #[cfg(not(test))] + // _ => { /* some sane fallback */ } + // } + // + // This way we fail your tests but don't break your library when adding + // a variant. You will be notified by a test failure when a variant is + // added, so that you can add code to handle it, but your library will + // continue to compile and work for downstream users in the interim. #[doc(hidden)] - __Nonexhaustive, + TestExhaustive, } }