Differentiate between methods and associated functions in diagnostics
Accurately refer to assoc fn without receiver as assoc fn instead of methods. Add `AssocItem::descr` method to centralize where we call methods and associated functions.
Stabilize `min_exhaustive_patterns`
## Stabilisation report
I propose we stabilize the [`min_exhaustive_patterns`](https://github.com/rust-lang/rust/issues/119612) language feature.
With this feature, patterns of empty types are considered unreachable when matched by-value. This allows:
```rust
enum Void {}
fn foo() -> Result<u32, Void>;
fn main() {
let Ok(x) = foo();
// also
match foo() {
Ok(x) => ...,
}
}
```
This is a subset of the long-unstable [`exhaustive_patterns`](https://github.com/rust-lang/rust/issues/51085) feature. That feature is blocked because omitting empty patterns is tricky when *not* matched by-value. This PR stabilizes the by-value case, which is not tricky.
The not-by-value cases (behind references, pointers, and unions) stay as they are today, e.g.
```rust
enum Void {}
fn foo() -> Result<u32, &Void>;
fn main() {
let Ok(x) = foo(); // ERROR: missing `Err(_)`
}
```
The consequence on existing code is some extra "unreachable pattern" warnings. This is fully backwards-compatible.
### Comparison with today's rust
This proposal only affects match checking of empty types (i.e. types with no valid values). Non-empty types behave the same with or without this feature. Note that everything below is phrased in terms of `match` but applies equallly to `if let` and other pattern-matching expressions.
To be precise, a visibly empty type is:
- an enum with no variants;
- the never type `!`;
- a struct with a *visible* field of a visibly empty type (and no #[non_exhaustive] annotation);
- a tuple where one of the types is visibly empty;
- en enum with all variants visibly empty (and no `#[non_exhaustive]` annotation);
- a `[T; N]` with `N != 0` and `T` visibly empty;
- all other types are nonempty.
(An extra change was proposed below: that we ignore #[non_exhaustive] for structs since adding fields cannot turn an empty struct into a non-empty one)
For normal types, exhaustiveness checking requires that we list all variants (or use a wildcard). For empty types it's more subtle: in some cases we require a `_` pattern even though there are no valid values that can match it. This is where the difference lies regarding this feature.
#### Today's rust
Under today's rust, a `_` is required for all empty types, except specifically: if the matched expression is of type `!` (the never type) or `EmptyEnum` (where `EmptyEnum` is an enum with no variants), then the `_` is not required.
```rust
let foo: Result<u32, !> = ...;
match foo {
Ok(x) => ...,
Err(_) => ..., // required
}
let foo: Result<u32, &!> = ...;
match foo {
Ok(x) => ...,
Err(_) => ..., // required
}
let foo: &! = ...;
match foo {
_ => ..., // required
}
fn blah(foo: (u32, !)) {
match foo {
_ => ..., // required
}
}
unsafe {
let ptr: *const ! = ...;
match *ptr {} // allowed
let ptr: *const (u32, !) = ...;
match *ptr {
(x, _) => { ... } // required
}
let ptr: *const Result<u32, !> = ...;
match *ptr {
Ok(x) => { ... }
Err(_) => { ... } // required
}
}
```
#### After this PR
After this PR, a pattern of an empty type can be omitted if (and only if):
- the match scrutinee expression has type `!` or `EmptyEnum` (like before);
- *or* the empty type is matched by value (that's the new behavior).
In all other cases, a `_` is required to match on an empty type.
```rust
let foo: Result<u32, !> = ...;
match foo {
Ok(x) => ..., // `Err` not required
}
let foo: Result<u32, &!> = ...;
match foo {
Ok(x) => ...,
Err(_) => ..., // required because `!` is under a dereference
}
let foo: &! = ...;
match foo {
_ => ..., // required because `!` is under a dereference
}
fn blah(foo: (u32, !)) {
match foo {} // allowed
}
unsafe {
let ptr: *const ! = ...;
match *ptr {} // allowed
let ptr: *const (u32, !) = ...;
match *ptr {
(x, _) => { ... } // required because the matched place is under a (pointer) dereference
}
let ptr: *const Result<u32, !> = ...;
match *ptr {
Ok(x) => { ... }
Err(_) => { ... } // required because the matched place is under a (pointer) dereference
}
}
```
### Documentation
The reference does not say anything specific about exhaustiveness checking, hence there is nothing to update there. The nomicon does, I opened https://github.com/rust-lang/nomicon/pull/445 to reflect the changes.
### Tests
The relevant tests are in `tests/ui/pattern/usefulness/empty-types.rs`.
### Unresolved Questions
None that I know of.
try-job: dist-aarch64-apple
Cache supertrait outlives of impl header for soundness check
This caches the results of computing the transitive supertraits of an impl and filtering it to its outlives obligations. This is purely an optimization to improve https://github.com/rust-lang/rust/pull/124336.
Stop unnecessarily taking GenericPredicates by `&self`
This results in overcapturing in edition 2024, and is unnecessary since `GenericPredicates: Copy`.
WF-check struct field types at construction site
Fixes#126272.
Fixes#127299.
Rustc of course already WF-checked the field types at the definition
site, but for error tainting of consts to work properly, there needs to
be an error emitted at the use site. Previously, with no use-site error,
we proceeded with CTFE and ran into ICEs since we are running code with
type errors.
Emitting use-site errors also brings struct-like constructors more in
line with fn-like constructors since they already emit use-site errors
for WF issues.
r? `@BoxyUwU`
Accurately refer to assoc fn without receiver as assoc fn instead of methods.
Add `AssocItem::descr` method to centralize where we call methods and associated functions.
Enable zstd for debug compression.
Set LLVM_ENABLE_ZSTD alongside LLVM_ENABLE_ZLIB so that --compress-debug-sections=zstd is an option.
See #120953
try-job: x86_64-gnu-tools
Subtree sync for rustc_codegen_cranelift
The main highlight this time is support for raw-dylib on Windows thanks to `@dpaoliello.` Compiling the ring crate for arm64 macOS has been fixed too.
r? `@ghost`
`@rustbot` label +A-codegen +A-cranelift +T-compiler
Ensure let stmt compound assignment removal suggestion respect codepoint boundaries
Previously we would try to issue a suggestion for `let x <op>= 1`, i.e.
a compound assignment within a `let` binding, to remove the `<op>`. The
suggestion code unfortunately incorrectly assumed that the `<op>` is an
exactly-1-byte ASCII character, but this assumption is incorrect because
we also recover Unicode-confusables like `➖=` as `-=`. In this example,
the suggestion code used a `+ BytePos(1)` to calculate the span of the
`<op>` codepoint that looks like `-` but the mult-byte Unicode
look-alike would cause the suggested removal span to be inside a
multi-byte codepoint boundary, triggering a codepoint boundary
assertion.
The fix is to use `SourceMap::start_point(token_span)` which properly accounts for codepoint boundaries.
Fixes#128845.
cc #128790
r? ````@fmease````
Use `SourceMap::end_point` instead of `- BytePos(1)` in arg removal suggestion
Previously, we tried to remove extra arg commas when providing extra arg removal suggestions. One of
the edge cases is having to account for an arg that has a closing delimiter `)` following it.
However, the previous suggestion code assumed that the delimiter is in fact exactly the 1-byte `)`
character. This assumption was proven incorrect, because we recover from Unicode-confusable
delimiters in the parser, which means that the ending delimiter could be a multi-byte codepoint
that looks *like* a `)`. Subtracing 1 byte could land us in the middle of a codepoint, triggering a
codepoint boundary assertion.
This is fixed by using `SourceMap::end_point` which properly accounts for codepoint boundaries.
Fixes#128717.
cc ````@fmease```` and #128790
use stable sort to sort multipart diagnostics
I think a stable sort should be used to sort the different parts of a multipart selection. The current unstable sort uses the text of the suggestion as a tie-breaker. That just doesn't seem right, and the order of the input is a better choice I think, because it gives the diagnostic author more control.
This came up when I was building a suggestion where
```rust
fn foo() {}
```
must be turned into an unsafe function, and an attribute must be added
```rust
#[target_feature(enable = "...")]
unsafe fn foo() {}
```
In this example, the two suggestions occur at the same position, but the order is extremely important: unsafe must come after the attribute. But the situation changes if there is a pub/pub(crate), and if the unsafe is already present. It just out that because of the suggestion text, there is no way for me to order the suggestions correctly.
This change probably should be tested, but are there tests of the diagnostics code itself in the tests?
r? ```@estebank```
Add `Steal::is_stolen()`
Writers of rustc drivers (such as myself) often encounter stealing issues. It is currently impossible to gracefully handle them. This PR adds a `Steal::is_stolen()` function for that purpose.
Set LLVM_ENABLE_ZSTD alongside LLVM_ENABLE_ZLIB so that --compress-debug-sections=zstd is an option.
Use static linking to avoid a new runtime dependency. Add an llvm.libzstd bootstrap option for LLVM
with zstd. Set it off by default except for the dist builder. Handle llvm-config --system-libs output
that contains static libraries.
Miscellaneous improvements to struct tail normalization
1. Make checks for foreign tails more accurate by normalizing the struct tail. I didn't write a test for this one.
2. Normalize when computing struct tail for `offset_of` for slice/str. This fixes the new solver only.
3. Normalizing when computing tails for disaligned reference check. This fixes both solvers.
r? lcnr