1
Fork 0

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`
This commit is contained in:
Guillaume Gomez 2024-02-29 17:08:37 +01:00 committed by GitHub
commit 9df7f26b1b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 98 additions and 88 deletions

View file

@ -688,6 +688,9 @@ pub enum Constructor<Cx: TypeCx> {
/// Fake extra constructor for constructors that are not seen in the matrix, as explained at the
/// top of the file.
Missing,
/// Fake extra constructor that indicates and empty field that is private. When we encounter one
/// we skip the column entirely so we don't observe its emptiness. Only used for specialization.
PrivateUninhabited,
}
impl<Cx: TypeCx> Clone for Constructor<Cx> {
@ -709,6 +712,7 @@ impl<Cx: TypeCx> Clone for Constructor<Cx> {
Constructor::NonExhaustive => Constructor::NonExhaustive,
Constructor::Hidden => Constructor::Hidden,
Constructor::Missing => Constructor::Missing,
Constructor::PrivateUninhabited => Constructor::PrivateUninhabited,
}
}
}
@ -763,6 +767,8 @@ impl<Cx: TypeCx> Constructor<Cx> {
}
// Wildcards cover anything
(_, Wildcard) => true,
// `PrivateUninhabited` skips everything.
(PrivateUninhabited, _) => true,
// Only a wildcard pattern can match these special constructors.
(Missing { .. } | NonExhaustive | Hidden, _) => false,