Suggest never pattern instead of _
for empty types
This commit is contained in:
parent
1ec73d70fa
commit
9f2aa5b85a
6 changed files with 97 additions and 69 deletions
|
@ -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..))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue