about summary refs log tree commit diff
path: root/compiler/rustc_pattern_analysis/src/lib.rs
diff options
context:
space:
mode:
authorGuillaume Gomez <guillaume1.gomez@gmail.com>2024-02-29 17:08:37 +0100
committerGitHub <noreply@github.com>2024-02-29 17:08:37 +0100
commit9df7f26b1b0b3cfe7dc8224514d1685d11b1e495 (patch)
tree0a9bed0e22c89fb8ca780d823177872a7f9bcc6f /compiler/rustc_pattern_analysis/src/lib.rs
parent36bd9ef5a841a41a1889ce0c74e1bacc6874dafc (diff)
parentc918893b63022c1d810a71e8b7fa211b6aecd782 (diff)
downloadrust-9df7f26b1b0b3cfe7dc8224514d1685d11b1e495.tar.gz
rust-9df7f26b1b0b3cfe7dc8224514d1685d11b1e495.zip
Rollup merge of #121000 - Nadrieril:keep_all_fields, r=compiler-errors
pattern_analysis: rework how we hide empty private fields

Consider this:
```rust
mod foo {
  pub struct Bar {
    pub a: bool,
    b: !,
  }
}

fn match_a_bar(bar: foo::Bar) -> bool {
  match bar {
    Bar { a, .. } => a,
  }
}
```

Because the field `b` is private, matches outside the module are not allowed to observe the fact that `Bar` is empty. In particular `match bar {}` is valid within the module `foo` but an error outside (assuming `exhaustive_patterns`).

We currently handle this by hiding the field `b` when it's both private and empty. This means that the pattern `Bar { a, .. }` is lowered to `Bar(a, _)` if we're inside of `foo` and to `Bar(a)` outside. This involves a bit of a dance to keep field indices straight. But most importantly this makes pattern lowering depend on the module.

In this PR, I instead do nothing special when lowering. Only during analysis do we track whether a place must be skipped.

r? `@compiler-errors`
Diffstat (limited to 'compiler/rustc_pattern_analysis/src/lib.rs')
-rw-r--r--compiler/rustc_pattern_analysis/src/lib.rs10
1 files changed, 7 insertions, 3 deletions
diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs
index 164dc36b679..d4b38d260e7 100644
--- a/compiler/rustc_pattern_analysis/src/lib.rs
+++ b/compiler/rustc_pattern_analysis/src/lib.rs
@@ -82,6 +82,11 @@ use crate::usefulness::{compute_match_usefulness, ValidityConstraint};
 pub trait Captures<'a> {}
 impl<'a, T: ?Sized> Captures<'a> for T {}
 
+/// `bool` newtype that indicates whether this is a privately uninhabited field that we should skip
+/// during analysis.
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+pub struct PrivateUninhabitedField(pub bool);
+
 /// Context that provides type information about constructors.
 ///
 /// Most of the crate is parameterized on a type that implements this trait.
@@ -105,13 +110,12 @@ pub trait TypeCx: Sized + fmt::Debug {
     /// The number of fields for this constructor.
     fn ctor_arity(&self, ctor: &Constructor<Self>, ty: &Self::Ty) -> usize;
 
-    /// The types of the fields for this constructor. The result must have a length of
-    /// `ctor_arity()`.
+    /// The types of the fields for this constructor. The result must contain `ctor_arity()` fields.
     fn ctor_sub_tys<'a>(
         &'a self,
         ctor: &'a Constructor<Self>,
         ty: &'a Self::Ty,
-    ) -> impl Iterator<Item = Self::Ty> + ExactSizeIterator + Captures<'a>;
+    ) -> impl Iterator<Item = (Self::Ty, PrivateUninhabitedField)> + ExactSizeIterator + Captures<'a>;
 
     /// The set of all the constructors for `ty`.
     ///