| Age | Commit message (Collapse) | Author | Lines |
|
|
|
|
|
|
|
This attempts to bring better error messages to invalid method calls, by applying some heuristics to identify common mistakes.
The algorithm is inspired by Levenshtein distance and longest common sub-sequence. In essence, we treat the types of the function, and the types of the arguments you provided as two "words" and compute the edits to get from one to the other.
We then modify that algorithm to detect 4 cases:
- A function input is missing
- An extra argument was provided
- The type of an argument is straight up invalid
- Two arguments have been swapped
- A subset of the arguments have been shuffled
(We detect the last two as separate cases so that we can detect two swaps, instead of 4 parameters permuted.)
It helps to understand this argument by paying special attention to terminology: "inputs" refers to the inputs being *expected* by the function, and "arguments" refers to what has been provided at the call site.
The basic sketch of the algorithm is as follows:
- Construct a boolean grid, with a row for each argument, and a column for each input. The cell [i, j] is true if the i'th argument could satisfy the j'th input.
- If we find an argument that could satisfy no inputs, provided for an input that can't be satisfied by any other argument, we consider this an "invalid type".
- Extra arguments are those that can't satisfy any input, provided for an input that *could* be satisfied by another argument.
- Missing inputs are inputs that can't be satisfied by any argument, where the provided argument could satisfy another input
- Swapped / Permuted arguments are identified with a cycle detection algorithm.
As each issue is found, we remove the relevant inputs / arguments and check for more issues. If we find no issues, we match up any "valid" arguments, and start again.
Note that there's a lot of extra complexity:
- We try to stay efficient on the happy path, only computing the diagonal until we find a problem, and then filling in the rest of the matrix.
- Closure arguments are wrapped in a tuple and need to be unwrapped
- We need to resolve closure types after the rest, to allow the most specific type constraints
- We need to handle imported C functions that might be variadic in their inputs.
I tried to document a lot of this in comments in the code and keep the naming clear.
|
|
|
|
|
|
|
|
|
|
Format core and std macro rules, removing needless surrounding blocks
Many of the asserting and printing macros in `core` and `std` are written with prehistoric-looking formatting, like this:
https://github.com/rust-lang/rust/blob/335ffbfa547df94ac236f5c56130cecf99c8d82b/library/std/src/macros.rs#L96-L101
In modern Rust style this would conventionally be written as follows instead, always using braces and a trailing semicolon on the macro arms:
https://github.com/rust-lang/rust/blob/af53809c874e0afb7be966df4d3cfcaa05277c53/library/std/src/macros.rs#L98-L105
Getting rid of the unneeded braces inside the expansion reduces extraneous indentation in macro-expanded code. For example:
```rust
println!("repro {}", true);
```
```rust
// before:
{
::std::io::_print(
::core::fmt::Arguments::new_v1(
&["repro ", "\n"],
&[::core::fmt::ArgumentV1::new_display(&true)],
),
);
};
```
```rust
// after:
::std::io::_print(
::core::fmt::Arguments::new_v1(
&["repro ", "\n"],
&[::core::fmt::ArgumentV1::new_display(&true)],
),
);
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
`span_label`
This makes the order of the output always consistent:
1. Place of the `match` missing arms
2. The `enum` definition span
3. The structured suggestion to add a fallthrough arm
|
|
Given
```rust
match Some(42) {
Some(0) => {}
Some(1) => {}
}
```
suggest
```rust
match Some(42) {
Some(0) => {}
Some(1) => {}
None | Some(_) => todo!(),
}
```
|
|
Given
```rust
match Some(42) {
Some(0) => {}
}
```
suggest
```rust
match Some(42) {
Some(0) => {}
None | Some(_) => todo!(),
}
```
|
|
Given
```rust
match Some(42) {}
```
suggest
```rust
match Some(42) { None | Some(_) => todo!(), }
```
|
|
|
|
|
|
Fixes #92074
This allows us to insert an `ExprKind::Err` when an invalid expression
is used in a literal pattern, preventing later stages of compilation
from seeing an unexpected literal pattern.
|
|
|
|
Fix stack overflow in `usefulness.rs`
Fix #88747
Applied the suggestion from `@nbdd0121,` not sure if this has any drawbacks. The first call to `ensure_sufficient_stack` is not needed to fix the test case, but I added it to be safe.
|
|
Print associated types on opaque `impl Trait` types
This PR generalizes #91021, printing associated types for all opaque `impl Trait` types instead of just special-casing for future.
before:
```
error[E0271]: type mismatch resolving `<impl Iterator as Iterator>::Item == u32`
```
after:
```
error[E0271]: type mismatch resolving `<impl Iterator<Item = usize> as Iterator>::Item == u32`
```
---
Questions:
1. I'm kinda lost in binders hell with this one. Is all of the `rebind`ing necessary?
2. Is there a map collection type that will give me a stable iteration order? Doesn't seem like TraitRef is Ord, so I can't just sort later..
3. I removed the logic that suppresses printing generator projection types. It creates outputs like this [gist](https://gist.github.com/compiler-errors/d6f12fb30079feb1ad1d5f1ab39a3a8d). Should I put that back?
4. I also added spaces between traits, `impl A+B` -> `impl A + B`. I quite like this change, but is there a good reason to keep it like that?
r? ````@estebank````
|
|
|
|
|
|
|
|
Improve suggestions for compatible variants on type mismatch.
Fixes #90553.
Before:

After:

r? `````@estebank`````
|
|
|
|
|
|
|
|
|
|
|
|
Edit explanation of test for nested type ascriptions
Fixes typo ("an ascribing") and removes extra.
Closes #88233.
|
|
Add test cases for unstable variants
Add test cases for doc hidden variants
Move is_doc_hidden to method on TyCtxt
Add unstable variants test to reachable-patterns ui test
Rename reachable-patterns -> omitted-patterns
|
|
Closes #88233
|
|
Perform type inference in range pattern
Fix #88074
|
|
Normalize after substituting via `field.ty()`
Back in https://github.com/rust-lang/rust/issues/72476 I hadn't understood where the problem was coming from, and only worked around the issue. What happens is that calling `field.ty()` on a field of a generic struct substitutes the appropriate generics but doesn't normalize the resulting type.
As a consumer of types I'm surprised that one would substitute without normalizing, feels like a footgun, so I added a comment.
Fixes https://github.com/rust-lang/rust/issues/89393.
|
|
|
|
Add an intermediate representation to exhaustiveness checking
The exhaustiveness checking algorithm keeps deconstructing patterns into a `Constructor` and some `Fields`, but does so a bit all over the place. This PR introduces a new representation for patterns that already has that information, so we only compute it once at the start.
I find this makes code easier to follow. In particular `DeconstructedPat::specialize` is a lot simpler than what happened before, and more closely matches the description of the algorithm. I'm also hoping this could help for the project of librarifying exhaustiveness for rust_analyzer since it decouples the algorithm from `rustc_middle::Pat`.
|
|
|
|
|
|
Now `Fields` is just a `Vec` of patterns, with some extra info on the
side to reconstruct patterns when needed. This emphasizes that this
extra info is not central to the algorithm.
|
|
|
|
|
|
|