1
Fork 0

Add helper methods checking for "#[non_exhaustive] that's active"

A check for `#[non_exhaustive]` is often done in combination with
checking whether the type is local to the crate, in a variety of ways.
Create a helper method and standardize on it as the way to check for
this.
This commit is contained in:
Maja Kądziołka 2025-03-03 12:54:26 +01:00
parent 59a9b9e9d7
commit 61f70003c2
No known key found for this signature in database
15 changed files with 46 additions and 46 deletions

View file

@ -329,11 +329,22 @@ impl<'tcx> AdtDef<'tcx> {
}
/// Returns `true` if the variant list of this ADT is `#[non_exhaustive]`.
///
/// Note that this function will return `true` even if the ADT has been
/// defined in the crate currently being compiled. If that's not what you
/// want, see [`Self::variant_list_has_applicable_non_exhaustive`].
#[inline]
pub fn is_variant_list_non_exhaustive(self) -> bool {
self.flags().contains(AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE)
}
/// Returns `true` if the variant list of this ADT is `#[non_exhaustive]`
/// and has been defined in another crate.
#[inline]
pub fn variant_list_has_applicable_non_exhaustive(self) -> bool {
self.is_variant_list_non_exhaustive() && !self.did().is_local()
}
/// Returns the kind of the ADT.
#[inline]
pub fn adt_kind(self) -> AdtKind {

View file

@ -107,7 +107,7 @@ impl<'tcx> Ty<'tcx> {
// For now, unions are always considered inhabited
Adt(adt, _) if adt.is_union() => InhabitedPredicate::True,
// Non-exhaustive ADTs from other crates are always considered inhabited
Adt(adt, _) if adt.is_variant_list_non_exhaustive() && !adt.did().is_local() => {
Adt(adt, _) if adt.variant_list_has_applicable_non_exhaustive() => {
InhabitedPredicate::True
}
Never => InhabitedPredicate::False,

View file

@ -1206,12 +1206,23 @@ impl VariantDef {
}
}
/// Is this field list non-exhaustive?
/// Returns `true` if the field list of this variant is `#[non_exhaustive]`.
///
/// Note that this function will return `true` even if the type has been
/// defined in the crate currently being compiled. If that's not what you
/// want, see [`Self::field_list_has_applicable_non_exhaustive`].
#[inline]
pub fn is_field_list_non_exhaustive(&self) -> bool {
self.flags.intersects(VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE)
}
/// Returns `true` if the field list of this variant is `#[non_exhaustive]`
/// and the type has been defined in another crate.
#[inline]
pub fn field_list_has_applicable_non_exhaustive(&self) -> bool {
self.is_field_list_non_exhaustive() && !self.def_id.is_local()
}
/// Computes the `Ident` of this variant by looking up the `Span`
pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident {
Ident::new(self.name, tcx.def_ident_span(self.def_id).unwrap())