Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Section 18.3- Misleading phrasing says the opposite of what is true #162

Closed
Tomer-Eliahu opened this issue Jan 31, 2024 · 1 comment
Closed

Comments

@Tomer-Eliahu
Copy link

In the Extra Conditionals with Match Guards section, it says regarding match guards:

"The downside of this additional expressiveness is that the compiler doesn't try to check for exhaustiveness when match guard expressions are involved".

However, this phrasing is misleading- it makes you believe that Rust will no longer insist that match expressions are exhaustive when you use a match guard.
So you would expect the following code to compile, but it does not:

  fn main() {

            let a = 0;
            
            let b = 0;
            
            //Rust still gives us a complier error telling us :
            //error[E0004]: non-exhaustive patterns: `i32::MIN..=-1_i32` not covered
            //if we remove the match guard of if b==0 the code complies
            match a{
                i32::MIN..=-1 if b==0 => println!("negative"),
                0..=i32::MAX => println!("zero or positive")
            }
        
        }

In reality, match arms with guards don't count towards exhaustivity.

This is because Because the Rust compiler cannot take guard expressions into account when determining if a match is exhaustive.
As soon as you have a guard, it assumes that guard could fail (I got this from this post on stack overflow).

So the following code will not compile even though all patterns are covered and Rust will give you a false positive non-exhaustive patterns error:

        fn main() {
            let number: i32 = 4;

            match number {
                i if i == 0 => println!("Zero"),
                i if i > 0 => println!("Greater than zero"),
                i if i < 0 => println!("less than zero"),
                //_ => println!("Should never happen."),
                // ^ uncomment to fix compilation
            }
        }

you get the following error message (note the line in bold):

error[E0004]: non-exhaustive patterns: _ not covered
--> src/main.rs:4:19
|
4 | match number {
| ^^^^^^ pattern _ not covered
|
= note: the matched value is of type i32
= note: match arms with guards don't count towards exhaustivity
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
7 ~ i if i < 0 => println!("less than zero"),
8 ~ _ => todo!(),
|

For more information about this error, try rustc --explain E0004.

I think it is important to fix this phrasing in the book to make it clear that:
Rust will sometimes tell you a match is non-exhaustive when in reality it is, but will never tell you a match is exhaustive when it isn't.

It is my understanding that matches are always exhaustive. if I am missing something please let me know.

@willcrichton
Copy link
Collaborator

Great suggestion, I'll modify this wording.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants