about summary refs log tree commit diff
path: root/src/doc/rustc-dev-guide
diff options
context:
space:
mode:
authorNadrieril <nadrieril+git@gmail.com>2020-10-16 21:59:28 +0100
committerJoshua Nelson <joshua@yottadb.com>2020-10-16 18:26:10 -0400
commitf1e6f2d3f9f42548e0d32b817ec3a17a04232b12 (patch)
treebe4c201b4107e750e5df53d0af96fd188c88aaec /src/doc/rustc-dev-guide
parent8263e7e082fb89a2d864d4d5076639b4c674955d (diff)
downloadrust-f1e6f2d3f9f42548e0d32b817ec3a17a04232b12.tar.gz
rust-f1e6f2d3f9f42548e0d32b817ec3a17a04232b12.zip
Explain pattern exhaustiveness checking
Diffstat (limited to 'src/doc/rustc-dev-guide')
-rw-r--r--src/doc/rustc-dev-guide/src/pat-exhaustive-checking.md82
1 files changed, 81 insertions, 1 deletions
diff --git a/src/doc/rustc-dev-guide/src/pat-exhaustive-checking.md b/src/doc/rustc-dev-guide/src/pat-exhaustive-checking.md
index b29bb1351e8..da4dab3bfd4 100644
--- a/src/doc/rustc-dev-guide/src/pat-exhaustive-checking.md
+++ b/src/doc/rustc-dev-guide/src/pat-exhaustive-checking.md
@@ -4,4 +4,84 @@ In Rust, pattern matching and bindings have a few very helpful properties. The
 compiler will check that bindings are irrefutable when made and that match arms
 are exhaustive.
 
-**TODO**: write this chapter.
+## Pattern usefulness
+
+The central question that usefulness checking answers is:
+"in this match expression, is that branch reachable?".
+More precisely, it boils down to computing whether,
+given a list of patterns we have already seen,
+a given new pattern might match any new value.
+
+For example, in the following match expression,
+we ask in turn whether each pattern might match something
+that wasn't matched by the patterns above it.
+Here we see the 4th pattern is redundant with the 1st;
+that branch will get an "unreachable" warning.
+The 3rd pattern may or may not be useful,
+depending on whether `Foo` has other variants than `Bar`.
+Finally, we can ask whether the whole match is exhaustive
+by asking whether the wildcard pattern (`_`)
+is useful relative to the list of all the patterns in that match.
+Here we can see that `_` is useful (it would catch `(false, None)`);
+this expression would therefore get a "non-exhaustive match" error.
+
+```rust
+// x: (bool, Option<Foo>)
+match x {
+    (true, _) => {} // 1
+    (false, Some(Foo::Bar)) => {} // 2
+    (false, Some(_)) => {} // 3
+    (true, None) => {} // 4
+}
+```
+
+Thus usefulness is used for two purposes:
+detecting unreachable code (which is useful to the user),
+and ensuring that matches are exhaustive (which is important for soundness).
+
+## Where it happens
+
+This check is done to any expression that desugars to a match expression in MIR.
+That includes actual `match` expressions,
+but also anything that looks like pattern matching,
+including `if let`, destructuring `let`, and similar expressions.
+
+```rust
+// `match`
+// Usefulness can detect unreachable branches and forbid non-exhaustive matches.
+match foo() {
+    Ok(x) => x,
+    Err(_) => panic!(),
+}
+
+// `if let`
+// Usefulness can detect unreachable branches.
+if let Some(x) = foo() {
+    // ...
+}
+
+// `while let`
+// Usefulness can detect infinite loops and dead loops.
+while let Some(x) = it.next() {
+    // ...
+}
+
+// Destructuring `let`
+// Usefulness can forbid non-exhaustive patterns.
+let Foo::Bar(x, y) = foo();
+
+// Destructuring function arguments
+// Usefulness can forbid non-exhaustive patterns.
+fn foo(Foo { x, y }: Foo) {
+    // ...
+}
+```
+
+## The algorithm
+
+Exhaustiveness checking is implemented in [check_match].
+The core of the algorithm is in [_match].
+That file contains a detailed description of the algorithm.
+
+[check_match]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_build/thir/pattern/check_match/index.html
+[_match]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_build/thir/pattern/_match/index.html