diff options
Diffstat (limited to 'src/expr.rs')
-rw-r--r-- | src/expr.rs | 31 |
1 files changed, 27 insertions, 4 deletions
diff --git a/src/expr.rs b/src/expr.rs index 8417475c..8e054cc7 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -224,8 +224,31 @@ 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. + // + // Once `deny(reachable)` is available in rustc, Expr will be + // reimplemented as a non_exhaustive enum. + // https://github.com/rust-lang/rust/issues/44109#issuecomment-521781237 #[doc(hidden)] - __Nonexhaustive, + __TestExhaustive(crate::private), } } @@ -804,7 +827,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 +2326,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 +2677,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(crate::private(()))); *e = Expr::Field(ExprField { attrs: Vec::new(), base: Box::new(base), |