aboutsummaryrefslogtreecommitdiffstats
path: root/src/expr.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/expr.rs')
-rw-r--r--src/expr.rs31
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),