diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2024-04-03 22:11:01 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-04-03 22:11:01 +0200 |
| commit | 5f74403c8ef13f7af4275c078aaa0db31679f470 (patch) | |
| tree | 6bec70a8df76a01b33f38cce56156d6551a81bd9 /compiler/rustc_pattern_analysis/src/constructor.rs | |
| parent | 0c8c18fcc6f1a717f6af6a7c3b6a27421c24da85 (diff) | |
| parent | 27704c7f9eea6e8ffaedac04ae1c932da7422fb7 (diff) | |
| download | rust-5f74403c8ef13f7af4275c078aaa0db31679f470.tar.gz rust-5f74403c8ef13f7af4275c078aaa0db31679f470.zip | |
Rollup merge of #123301 - Nadrieril:unions, r=compiler-errors
pattern analysis: fix union handling Little known fact: rust supports union patterns. Exhaustiveness handles them soundly but reports nonsensical missing patterns. This PR fixes the reported patterns and documents what we're doing. r? `@compiler-errors`
Diffstat (limited to 'compiler/rustc_pattern_analysis/src/constructor.rs')
| -rw-r--r-- | compiler/rustc_pattern_analysis/src/constructor.rs | 29 |
1 files changed, 28 insertions, 1 deletions
diff --git a/compiler/rustc_pattern_analysis/src/constructor.rs b/compiler/rustc_pattern_analysis/src/constructor.rs index 1c9a9ab0f72..44f09b66bf6 100644 --- a/compiler/rustc_pattern_analysis/src/constructor.rs +++ b/compiler/rustc_pattern_analysis/src/constructor.rs @@ -140,6 +140,34 @@ //! [`ConstructorSet::split`]. The invariants of [`SplitConstructorSet`] are also of interest. //! //! +//! ## Unions +//! +//! Unions allow us to match a value via several overlapping representations at the same time. For +//! example, the following is exhaustive because when seeing the value as a boolean we handled all +//! possible cases (other cases such as `n == 3` would trigger UB). +//! +//! ```rust +//! # fn main() { +//! union U8AsBool { +//! n: u8, +//! b: bool, +//! } +//! let x = U8AsBool { n: 1 }; +//! unsafe { +//! match x { +//! U8AsBool { n: 2 } => {} +//! U8AsBool { b: true } => {} +//! U8AsBool { b: false } => {} +//! } +//! } +//! # } +//! ``` +//! +//! Pattern-matching has no knowledge that e.g. `false as u8 == 0`, so the values we consider in the +//! algorithm look like `U8AsBool { b: true, n: 2 }`. In other words, for the most part a union is +//! treated like a struct with the same fields. The difference lies in how we construct witnesses of +//! non-exhaustiveness. +//! //! //! ## Opaque patterns //! @@ -974,7 +1002,6 @@ impl<Cx: PatCx> ConstructorSet<Cx> { /// any) are missing; 2/ split constructors to handle non-trivial intersections e.g. on ranges /// or slices. This can get subtle; see [`SplitConstructorSet`] for details of this operation /// and its invariants. - #[instrument(level = "debug", skip(self, ctors), ret)] pub fn split<'a>( &self, ctors: impl Iterator<Item = &'a Constructor<Cx>> + Clone, |
