diff options
| author | Nadrieril <nadrieril+git@gmail.com> | 2024-02-28 22:37:11 +0100 |
|---|---|---|
| committer | Nadrieril <nadrieril+git@gmail.com> | 2024-03-12 21:38:30 +0100 |
| commit | 9f2aa5b85a2584568f1ad34f23d029eeafb20d4b (patch) | |
| tree | c8a43d2517eb0ffb2d70c25293588473fcd17e4f /compiler/rustc_pattern_analysis/src | |
| parent | 1ec73d70fac58055eb1a2249279fad81b986edc2 (diff) | |
| download | rust-9f2aa5b85a2584568f1ad34f23d029eeafb20d4b.tar.gz rust-9f2aa5b85a2584568f1ad34f23d029eeafb20d4b.zip | |
Suggest never pattern instead of `_` for empty types
Diffstat (limited to 'compiler/rustc_pattern_analysis/src')
| -rw-r--r-- | compiler/rustc_pattern_analysis/src/constructor.rs | 24 | ||||
| -rw-r--r-- | compiler/rustc_pattern_analysis/src/pat.rs | 12 |
2 files changed, 32 insertions, 4 deletions
diff --git a/compiler/rustc_pattern_analysis/src/constructor.rs b/compiler/rustc_pattern_analysis/src/constructor.rs index 66c9e2e1840..b4d32782acf 100644 --- a/compiler/rustc_pattern_analysis/src/constructor.rs +++ b/compiler/rustc_pattern_analysis/src/constructor.rs @@ -1048,10 +1048,32 @@ impl<Cx: TypeCx> ConstructorSet<Cx> { // In a `MaybeInvalid` place even an empty pattern may be reachable. We therefore // add a dummy empty constructor here, which will be ignored if the place is // `ValidOnly`. - missing_empty.push(NonExhaustive); + missing_empty.push(Never); } } SplitConstructorSet { present, missing, missing_empty } } + + /// Whether this set only contains empty constructors. + pub(crate) fn all_empty(&self) -> bool { + match self { + ConstructorSet::Bool + | ConstructorSet::Integers { .. } + | ConstructorSet::Ref + | ConstructorSet::Union + | ConstructorSet::Unlistable => false, + ConstructorSet::NoConstructors => true, + ConstructorSet::Struct { empty } => *empty, + ConstructorSet::Variants { variants, non_exhaustive } => { + !*non_exhaustive + && variants + .iter() + .all(|visibility| matches!(visibility, VariantVisibility::Empty)) + } + ConstructorSet::Slice { array_len, subtype_is_empty } => { + *subtype_is_empty && matches!(array_len, Some(1..)) + } + } + } } diff --git a/compiler/rustc_pattern_analysis/src/pat.rs b/compiler/rustc_pattern_analysis/src/pat.rs index 3395054b7b3..780a386fe65 100644 --- a/compiler/rustc_pattern_analysis/src/pat.rs +++ b/compiler/rustc_pattern_analysis/src/pat.rs @@ -292,18 +292,24 @@ impl<Cx: TypeCx> WitnessPat<Cx> { pub(crate) fn new(ctor: Constructor<Cx>, fields: Vec<Self>, ty: Cx::Ty) -> Self { Self { ctor, fields, ty } } - pub(crate) fn wildcard(ty: Cx::Ty) -> Self { - Self::new(Wildcard, Vec::new(), ty) + /// Create a wildcard pattern for this type. If the type is empty, we create a `!` pattern. + pub(crate) fn wildcard(cx: &Cx, ty: Cx::Ty) -> Self { + let is_empty = cx.ctors_for_ty(&ty).is_ok_and(|ctors| ctors.all_empty()); + let ctor = if is_empty { Never } else { Wildcard }; + Self::new(ctor, Vec::new(), ty) } /// Construct a pattern that matches everything that starts with this constructor. /// For example, if `ctor` is a `Constructor::Variant` for `Option::Some`, we get the pattern /// `Some(_)`. pub(crate) fn wild_from_ctor(cx: &Cx, ctor: Constructor<Cx>, ty: Cx::Ty) -> Self { + if matches!(ctor, Wildcard) { + return Self::wildcard(cx, ty); + } let fields = cx .ctor_sub_tys(&ctor, &ty) .filter(|(_, PrivateUninhabitedField(skip))| !skip) - .map(|(ty, _)| Self::wildcard(ty)) + .map(|(ty, _)| Self::wildcard(cx, ty)) .collect(); Self::new(ctor, fields, ty) } |
