Skip to content

Commit

Permalink
refactor: simplify yes/no logic, fix README.md doctest
Browse files Browse the repository at this point in the history
  • Loading branch information
MingweiSamuel committed Sep 13, 2024
1 parent 03f670b commit f075c93
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 12 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,25 @@ let v: &Value = todo!();
matchbox::matchbox!{
match v {
Nil => todo!(),
Cons(Deref @ Symbol(Deref @ "quote"), Deref @ Cons(x, Deref @ Nil)) => todo!(),
Cons(deref!(Symbol(deref!("quote"))), deref!(Cons(x, deref! @ Nil))) => todo!(),
_ => todo!(),
}
}
```

But there is a problem in my crate: all arms with `Deref @` are ignored when compiler performs exhaustiveness checking. So sometimes you will need to add `_ => unreachable!()` to the end.
But there is a problem in my crate: all arms with `deref! @` are ignored when compiler performs exhaustiveness checking. So sometimes you will need to add `_ => unreachable!()` to the end.

I.e. it is possible that your arms are exhaustive, but the compiler will not be able to check this. But it is not possible that you arms are not exhaustive and the compiler will falsely report them as exhaustive.

(I decided not to implement full exhaustiveness checking, because I hope that truly native support for deref patterns will be implemented in the rustc soon, so my work will be unneeded anyway. But if you want to implement similar macro with full exhaustiveness checking, go ahead, I can even link to your project here.)

The macro calls `Deref::deref` internally. Keep in mind that `Deref::deref` takes REFERENCE to smart pointer and returns REFERENCE to pointee. So this code will work: `match &Nil { Deref @ x => ... }`, but this will not: `match Nil { Deref @ x => ... }`.
The macro calls `Deref::deref` internally. Keep in mind that `Deref::deref` takes REFERENCE to smart pointer and returns REFERENCE to pointee. So this code will work: `match &Nil { deref! @ x => ... }`, but this will not: `match Nil { deref! @ x => ... }`.

Consider this code:
```rust,ignore
matchbox::matchbox!{
match v {
Symbol(Deref @ x) => {
Symbol(deref! @ x) => {
// some_code_here
}
_ => {
Expand Down
16 changes: 8 additions & 8 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,15 +155,15 @@ fn matchbox_impl(mut m: syn::ExprMatch) -> syn::ExprMatch {
arm.pat = my_fold.fold_pat(arm.pat);

if !my_fold.binds.is_empty() {
let (yes, no) = if let Some((_if_token, src_guard)) = arm.guard {
(*src_guard, syn::parse_quote_spanned! {span=> false })
} else {
(
syn::parse_quote_spanned! {span=> true },
syn::parse_quote_spanned! {span=> false },
)
let t = {
let yes = if let Some((_if_token, src_guard)) = arm.guard {
*src_guard
} else {
syn::parse_quote_spanned! {span=> true }
};
let no = syn::parse_quote_spanned! {span=> false };
tower(&my_fold.binds, yes, &no, true)
};
let t = tower(&my_fold.binds, yes, &no, true);
arm.guard = Some((
syn::Token![if](span),
Box::new(syn::parse_quote_spanned! {span=> { #[allow(unused_variables)] #t } }),
Expand Down

0 comments on commit f075c93

Please sign in to comment.