Skip to content

Commit be520c1

Browse files
authored
Merge pull request #1067 from dtolnay/nonexhaustive
Switch non exhaustive syntax tree enums to use #[non_exhaustive]
2 parents 390e0c1 + c6ce512 commit be520c1

19 files changed

+167
-113
lines changed

build.rs

+4
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ fn main() {
1919
println!("cargo:rustc-cfg=syn_no_const_vec_new");
2020
}
2121

22+
if compiler.minor < 40 {
23+
println!("cargo:rustc-cfg=syn_no_non_exhaustive");
24+
}
25+
2226
if compiler.minor < 56 {
2327
println!("cargo:rustc-cfg=syn_no_negative_literal_parse");
2428
}

codegen/src/clone.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,16 @@ fn expand_impl_body(defs: &Definitions, node: &Node) -> TokenStream {
4242
});
4343
let nonexhaustive = if node.exhaustive {
4444
None
45+
} else if node.ident == "Expr" {
46+
Some(quote! {
47+
#[cfg(any(syn_no_non_exhaustive, not(feature = "full")))]
48+
_ => unreachable!(),
49+
})
4550
} else {
46-
Some(quote!(_ => unreachable!()))
51+
Some(quote! {
52+
#[cfg(syn_no_non_exhaustive)]
53+
_ => unreachable!(),
54+
})
4755
};
4856
quote! {
4957
match self {

codegen/src/debug.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,16 @@ fn expand_impl_body(defs: &Definitions, node: &Node) -> TokenStream {
4242
});
4343
let nonexhaustive = if node.exhaustive {
4444
None
45+
} else if node.ident == "Expr" {
46+
Some(quote! {
47+
#[cfg(any(syn_no_non_exhaustive, not(feature = "full")))]
48+
_ => unreachable!(),
49+
})
4550
} else {
46-
Some(quote!(_ => unreachable!()))
51+
Some(quote! {
52+
#[cfg(syn_no_non_exhaustive)]
53+
_ => unreachable!(),
54+
})
4755
};
4856
quote! {
4957
match self {

codegen/src/fold.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,10 @@ fn node(traits: &mut TokenStream, impls: &mut TokenStream, s: &Node, defs: &Defi
154154
let nonexhaustive = if s.exhaustive {
155155
None
156156
} else {
157-
Some(quote!(_ => unreachable!()))
157+
Some(quote! {
158+
#[cfg(syn_no_non_exhaustive)]
159+
_ => unreachable!(),
160+
})
158161
};
159162

160163
fold_impl.extend(quote! {

codegen/src/hash.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,16 @@ fn expand_impl_body(defs: &Definitions, node: &Node) -> TokenStream {
7878
});
7979
let nonexhaustive = if node.exhaustive {
8080
None
81+
} else if node.ident == "Expr" {
82+
Some(quote! {
83+
#[cfg(any(syn_no_non_exhaustive, not(feature = "full")))]
84+
_ => unreachable!(),
85+
})
8186
} else {
82-
Some(quote!(_ => unreachable!()))
87+
Some(quote! {
88+
#[cfg(syn_no_non_exhaustive)]
89+
_ => unreachable!(),
90+
})
8391
};
8492
quote! {
8593
match self {

codegen/src/visit.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,10 @@ fn node(traits: &mut TokenStream, impls: &mut TokenStream, s: &Node, defs: &Defi
166166
let nonexhaustive = if s.exhaustive {
167167
None
168168
} else {
169-
Some(quote!(_ => unreachable!()))
169+
Some(quote! {
170+
#[cfg(syn_no_non_exhaustive)]
171+
_ => unreachable!(),
172+
})
170173
};
171174

172175
visit_impl.extend(quote! {

codegen/src/visit_mut.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,10 @@ fn node(traits: &mut TokenStream, impls: &mut TokenStream, s: &Node, defs: &Defi
166166
let nonexhaustive = if s.exhaustive {
167167
None
168168
} else {
169-
Some(quote!(_ => unreachable!()))
169+
Some(quote! {
170+
#[cfg(syn_no_non_exhaustive)]
171+
_ => unreachable!(),
172+
})
170173
};
171174

172175
visit_mut_impl.extend(quote! {

src/expr.rs

+9-16
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ ast_enum_of_structs! {
8787
/// see names getting repeated in your code, like accessing
8888
/// `receiver.receiver` or `pat.pat` or `cond.cond`.
8989
#[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
90+
#[cfg_attr(not(syn_no_non_exhaustive), non_exhaustive)]
9091
pub enum Expr {
9192
/// A slice literal expression: `[a, b, c, d]`.
9293
Array(ExprArray),
@@ -224,31 +225,27 @@ ast_enum_of_structs! {
224225
/// A yield expression: `yield expr`.
225226
Yield(ExprYield),
226227

227-
// The following is the only supported idiom for exhaustive matching of
228-
// this enum.
228+
// Not public API.
229+
//
230+
// For testing exhaustiveness in downstream code, use the following idiom:
229231
//
230232
// match expr {
231233
// Expr::Array(expr) => {...}
232234
// Expr::Assign(expr) => {...}
233235
// ...
234236
// Expr::Yield(expr) => {...}
235237
//
236-
// #[cfg(test)]
237-
// Expr::__TestExhaustive(_) => unimplemented!(),
238-
// #[cfg(not(test))]
238+
// #[cfg_attr(test, deny(non_exhaustive_omitted_patterns))]
239239
// _ => { /* some sane fallback */ }
240240
// }
241241
//
242242
// This way we fail your tests but don't break your library when adding
243243
// a variant. You will be notified by a test failure when a variant is
244244
// added, so that you can add code to handle it, but your library will
245245
// continue to compile and work for downstream users in the interim.
246-
//
247-
// Once `deny(reachable)` is available in rustc, Expr will be
248-
// reimplemented as a non_exhaustive enum.
249-
// https://github.com/rust-lang/rust/issues/44109#issuecomment-521781237
246+
#[cfg(syn_no_non_exhaustive)]
250247
#[doc(hidden)]
251-
__TestExhaustive(crate::private),
248+
__NonExhaustive,
252249
}
253250
}
254251

@@ -838,9 +835,7 @@ impl Expr {
838835
| Expr::Yield(ExprYield { attrs, .. }) => mem::replace(attrs, new),
839836
Expr::Verbatim(_) => Vec::new(),
840837

841-
#[cfg(test)]
842-
Expr::__TestExhaustive(_) => unimplemented!(),
843-
#[cfg(not(test))]
838+
#[cfg(syn_no_non_exhaustive)]
844839
_ => unreachable!(),
845840
}
846841
}
@@ -2510,9 +2505,7 @@ pub(crate) mod parsing {
25102505
Pat::Verbatim(_) => {}
25112506
Pat::Wild(pat) => pat.attrs = attrs,
25122507

2513-
#[cfg(test)]
2514-
Pat::__TestExhaustive(_) => unimplemented!(),
2515-
#[cfg(not(test))]
2508+
#[cfg(syn_no_non_exhaustive)]
25162509
_ => unreachable!(),
25172510
}
25182511
Ok(pat)

src/gen/clone.rs

+7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/gen/debug.rs

+7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/gen/fold.rs

+7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/gen/hash.rs

+7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)