Suggest never pattern instead of _ for empty types

This commit is contained in:
Nadrieril 2024-02-28 22:37:11 +01:00
parent 1ec73d70fa
commit 9f2aa5b85a
6 changed files with 97 additions and 69 deletions

View file

@ -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..))
}
}
}
}

View file

@ -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)
}