This removes special-casing of boxes from `rustc_pattern_analysis`, as a
first step in replacing `box_patterns` with `deref_patterns`.
Incidentally, it fixes a bug caused by box patterns being represented as
structs rather than pointers, where `exhaustive_patterns` could generate
spurious `unreachable_patterns` lints on arms required for
exhaustiveness; following the lint's advice would result in an error.
Without adding proper support for mixed exhaustiveness, mixing deref
patterns with normal constructors would either violate
`ConstructorSet::split`'s invariant 4 or 7. We'd either be ignoring rows
with normal constructors or we'd have problems in unspecialization from
non-disjoint constructors. Checking mixed exhaustivenss similarly to how
unions are currently checked should work, but the diagnostics for unions
are confusing. Since mixing deref patterns with normal constructors is
pretty niche (currently it only makes sense for `Cow`), emitting an
error lets us avoid committing to supporting mixed exhaustiveness
without a good answer for the diagnostics.
This does not yet handle the case of mixed deref patterns with normal
constructors; it'll ICE in `Constructor::is_covered_by`. That'll be
fixed in a later commit.
Add new `PatKind::Missing` variants
To avoid some ugly uses of `kw::Empty` when handling "missing" patterns, e.g. in bare fn tys. Helps with #137978. Details in the individual commits.
r? ``@oli-obk``
"Missing" patterns are possible in bare fn types (`fn f(u32)`) and
similar places. Currently these are represented in the AST with
`ast::PatKind::Ident` with no `by_ref`, no `mut`, an empty ident, and no
sub-pattern. This flows through to `{hir,thir}::PatKind::Binding` for
HIR and THIR.
This is a bit nasty. It's very non-obvious, and easy to forget to check
for the exceptional empty identifier case.
This commit adds a new variant, `PatKind::Missing`, to do it properly.
The process I followed:
- Add a `Missing` variant to `{ast,hir,thir}::PatKind`.
- Chang `parse_param_general` to produce `ast::PatKind::Missing`
instead of `ast::PatKind::Missing`.
- Look through `kw::Empty` occurrences to find functions where an
existing empty ident check needs replacing with a `PatKind::Missing`
check: `print_param`, `check_trait_item`, `is_named_param`.
- Add a `PatKind::Missing => unreachable!(),` arm to every exhaustive
match identified by the compiler.
- Find which arms are actually reachable by running the test suite,
changing them to something appropriate, usually by looking at what
would happen to a `PatKind::Ident`/`PatKind::Binding` with no ref, no
`mut`, an empty ident, and no subpattern.
Quite a few of the `unreachable!()` arms were never reached. This makes
sense because `PatKind::Missing` can't happen in every pattern, only
in places like bare fn tys and trait fn decls.
I also tried an alternative approach: modifying `ast::Param::pat` to
hold an `Option<P<Pat>>` instead of a `P<Pat>`, but that quickly turned
into a very large and painful change. Adding `PatKind::Missing` is much
easier.
Consider fields to be inhabited if they are unstable
Fixes#133885 with a simple heuristic
r? Nadrieril
Not totally certain if this needs T-lang approval or a crater run.
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.
It's similar to the other limits, e.g. obtained via `get_limit`. So it
makes sense to handle it consistently with the other limits. We now use
`Limit`/`usize` in most places instead of `Option<usize>`, so we use
`Limit::new(usize::MAX)`/`usize::MAX` to emulate how `None` used to work.
The commit also adds `Limit::unlimited`.
Point at `const` definition when used instead of a binding in a `let` statement
Modify `PatKind::InlineConstant` to be `ExpandedConstant` standing in not only for inline `const` blocks but also for `const` items. This allows us to track named `const`s used in patterns when the pattern is a single binding. When we detect that there is a refutable pattern involving a `const` that could have been a binding instead, we point at the `const` item, and suggest renaming. We do this for both `let` bindings and `match` expressions missing a catch-all arm if there's at least one single binding pattern referenced.
After:
```
error[E0005]: refutable pattern in local binding
--> $DIR/bad-pattern.rs:19:13
|
LL | const PAT: u32 = 0;
| -------------- missing patterns are not covered because `PAT` is interpreted as a constant pattern, not a new variable
...
LL | let PAT = v1;
| ^^^ pattern `1_u32..=u32::MAX` not covered
|
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
= note: the matched value is of type `u32`
help: introduce a variable instead
|
LL | let PAT_var = v1;
| ~~~~~~~
```
Before:
```
error[E0005]: refutable pattern in local binding
--> $DIR/bad-pattern.rs:19:13
|
LL | let PAT = v1;
| ^^^
| |
| pattern `1_u32..=u32::MAX` not covered
| missing patterns are not covered because `PAT` is interpreted as a constant pattern, not a new variable
| help: introduce a variable instead: `PAT_var`
|
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
= note: the matched value is of type `u32`
```
CC #132582.
the behavior of the type system not only depends on the current
assumptions, but also the currentnphase of the compiler. This is
mostly necessary as we need to decide whether and how to reveal
opaque types. We track this via the `TypingMode`.
After:
```
error[E0005]: refutable pattern in local binding
--> $DIR/bad-pattern.rs:19:13
|
LL | const PAT: u32 = 0;
| -------------- missing patterns are not covered because `PAT` is interpreted as a constant pattern, not a new variable
...
LL | let PAT = v1;
| ^^^
| |
| pattern `1_u32..=u32::MAX` not covered
| help: introduce a variable instead: `PAT_var`
|
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
= note: the matched value is of type `u32`
```
Before:
```
error[E0005]: refutable pattern in local binding
--> $DIR/bad-pattern.rs:19:13
|
LL | let PAT = v1;
| ^^^
| |
| pattern `1_u32..=u32::MAX` not covered
| missing patterns are not covered because `PAT` is interpreted as a constant pattern, not a new variable
| help: introduce a variable instead: `PAT_var`
|
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
= note: the matched value is of type `u32`
```
Depend on rustc_abi in compiler crates that use it indirectly but have
not yet taken on that dependency, and are not entangled in my other PRs.
This leaves an "excise rustc_target" step after the dust settles.
Replace calls to `ty::Const::{try_}eval` in mir build/pattern analysis
We normalize consts in writeback: #130645. This means that consts are gonna be as normalized as they're ever gonna get in MIR building and pattern analysis. Therefore we can just use `try_to_target_usize` rather than calling `eval_target_usize`.
Regarding the `.expect` calls, I'm not totally certain whether they're correct given rigid unevaluated consts. But this PR shouldn't make *more* ICEs occur; we may have to squash these ICEs when mGCE comes around, tho 😺
Remove `print::Pat` from the printing of `WitnessPat`
After the preliminary work done in #128536, we can now get rid of `print::Pat` entirely.
- First, we introduce a variant `PatKind::Print(String)`.
- Then we incrementally remove each other variant of `PatKind`, by having the relevant code produce `PatKind::Print` instead.
- Once `PatKind::Print` is the only remaining variant, it becomes easy to remove `print::Pat` and replace it with `String`.
There is more cleanup that I have in mind, but this seemed like a natural stopping point for one PR.
r? ```@Nadrieril```
Shrink `TyKind::FnPtr`.
By splitting the `FnSig` within `TyKind::FnPtr` into `FnSigTys` and `FnHeader`, which can be packed more efficiently. This reduces the size of the hot `TyKind` type from 32 bytes to 24 bytes on 64-bit platforms. This reduces peak memory usage by a few percent on some benchmarks. It also reduces cache misses and page faults similarly, though this doesn't translate to clear cycles or wall-time improvements on CI.
r? `@compiler-errors`
Preliminary cleanup of `WitnessPat` hoisting/printing
Follow-up to #128430.
The eventual goal is to remove `print::Pat` entirely, but in the course of working towards that I made so many small improvements that it seems wise to let those be reviewed/merged on their own first.
Best reviewed commit-by-commit, most of which should be pretty simple and straightforward.
r? ``@Nadrieril``
By splitting the `FnSig` within `TyKind::FnPtr` into `FnSigTys` and
`FnHeader`, which can be packed more efficiently. This reduces the size
of the hot `TyKind` type from 32 bytes to 24 bytes on 64-bit platforms.
This reduces peak memory usage by a few percent on some benchmarks. It
also reduces cache misses and page faults similarly, though this doesn't
translate to clear cycles or wall-time improvements on CI.