Improve handling of expressions in patterns
Closes#112593.
Methodcalls' dots in patterns are silently recovered as commas (e.g. `Foo("".len())` -> `Foo("", len())`) so extra diagnostics are emitted:
```rs
struct Foo(u8, String, u8);
fn bar(foo: Foo) -> bool {
match foo {
Foo(4, "yippee".yeet(), 7) => true,
_ => false
}
}
```
```
error: expected one of `)`, `,`, `...`, `..=`, `..`, or `|`, found `.`
--> main.rs:5:24
|
5 | Foo(4, "yippee".yeet(), 7) => true,
| ^
| |
| expected one of `)`, `,`, `...`, `..=`, `..`, or `|`
| help: missing `,`
error[E0531]: cannot find tuple struct or tuple variant `yeet` in this scope
--> main.rs:5:25
|
5 | Foo(4, "yippee".yeet(), 7) => true,
| ^^^^ not found in this scope
error[E0023]: this pattern has 4 fields, but the corresponding tuple struct has 3 fields
--> main.rs:5:13
|
1 | struct Foo(u8, String, u8);
| -- ------ -- tuple struct has 3 fields
...
5 | Foo(4, "yippee".yeet(), 7) => true,
| ^ ^^^^^^^^ ^^^^^^ ^ expected 3 fields, found 4
error: aborting due to 3 previous errors
```
This PR checks for patterns that ends with a dot and a lowercase ident (as structs/variants should be uppercase):
```
error: expected a pattern, found a method call
--> main.rs:5:16
|
5 | Foo(4, "yippee".yeet(), 7) => true,
| ^^^^^^^^^^^^^^^ method calls are not allowed in patterns
error: aborting due to 1 previous error
```
Also check for expressions:
```rs
fn is_idempotent(x: f32) -> bool {
match x {
x * x => true,
_ => false,
}
}
fn main() {
let mut t: [i32; 5];
let t[0] = 1;
}
```
```
error: expected a pattern, found an expression
--> main.rs:3:9
|
3 | x * x => true,
| ^^^^^ arbitrary expressions are not allowed in patterns
error: expected a pattern, found an expression
--> main.rs:10:9
|
10 | let t[0] = 1;
| ^^^^ arbitrary expressions are not allowed in patterns
```
Would be cool if the compiler could suggest adding a guard for `match`es, but I've no idea how to do it.
---
`@rustbot` label +A-diagnostics +A-parser +A-patterns +C-enhancement
Cache CI Docker images in ghcr registry
This PR changes the way `rust-lang` caches Docker images used in CI workflows. Before, the intermediate Docker layers were manually exported from `docker history` and backed up in S3. However, this approach doesn't work any more with the Docker version used by GitHub Actions since August 2023. We had to revert to disabling Docker BuildKit to make the old caching work, but this workaround will stop working eventually, after GitHub updates Docker again and the old build backend will be removed.
This PR changes the caching to use [Docker caching](https://docs.docker.com/build/cache/) instead. There are several backends for the cache, for our use-case S3 and Docker registry makes sense. This PR uses the Docker registry backend and uses the ghcr.io registry.
The caching creates a Docker image labeled `rust-ci`, which is currently stored to the `ghcr.io/rust-lang-ci` package registry. This image appears [here](https://ghcr.io/rust-lang-ci/rust-ci). The image is stored in `rust-lang-ci` and not `rust-lang`, because `try` and `auto` builds run in the context of that repository, so the used `GITHUB_TOKEN` has permissions for it (unlike for `rust-lang`).
For pull request CI runs, the provided `GITHUB_TOKEN` reduces its permissions automatically to `packages: read`, which means that we won't be able to write the Docker image. If we're not able to write, we won't have anything to read. So I disabled the caching entirely for PR runs (it makes it slightly faster to build the Docker image if we don't have to deal with exporting and using a separate build driver). Note that before this PR, we also weren't able to read or write the cache on PR runs.
Rustup part of this change is [here](https://github.com/rust-lang/rustup/pull/3648).
Related issue: https://github.com/rust-lang/infra-team/issues/81
r? `@Mark-Simulacrum`
Currently the parser will interpret any label/lifetime in certain
positions as a mistyped char literal, on the assumption that the
trailing single quote was accidentally omitted. This is reasonable for a
something like 'a (because 'a' would be valid) but not reasonable for a
something like 'abc (because 'abc' is not valid).
This commit restricts this behaviour only to labels/lifetimes that would
be valid char literals, via the new `could_be_unclosed_char_literal`
function. The commit also augments the `label-is-actually-char.rs` test
in a couple of ways:
- Adds testing of labels/lifetimes with identifiers longer than one
char, e.g. 'abc.
- Adds a new match with simpler patterns, because the
`recover_unclosed_char` call in `parse_pat_with_range_pat` was not
being exercised (in this test or any other ui tests).
Fixes#120397, an assertion failure, which was caused by this behaviour
in the parser interacting with some new stricter char literal checking
added in #120329.
Add `ErrCode`
Error codes are integers, but `String` is used everywhere to represent them. Gross!
This commit introduces `ErrCode`, an integral newtype for error codes, replacing `String`. The commit also introduces constants like `E0123` for all the used error codes.
r? `@estebank`
Error codes are integers, but `String` is used everywhere to represent
them. Gross!
This commit introduces `ErrCode`, an integral newtype for error codes,
replacing `String`. It also introduces a constant for every error code,
e.g. `E0123`, and removes the `error_code!` macro. The constants are
imported wherever used with `use rustc_errors::codes::*`.
With the old code, we have three different ways to specify an error code
at a use point:
```
error_code!(E0123) // macro call
struct_span_code_err!(dcx, span, E0123, "msg"); // bare ident arg to macro call
\#[diag(name, code = "E0123")] // string
struct Diag;
```
With the new code, they all use the `E0123` constant.
```
E0123 // constant
struct_span_code_err!(dcx, span, E0123, "msg"); // constant
\#[diag(name, code = E0123)] // constant
struct Diag;
```
The commit also changes the structure of the error code definitions:
- `rustc_error_codes` now just defines a higher-order macro listing the
used error codes and nothing else.
- Because that's now the only thing in the `rustc_error_codes` crate, I
moved it into the `lib.rs` file and removed the `error_codes.rs` file.
- `rustc_errors` uses that macro to define everything, e.g. the error
code constants and the `DIAGNOSTIC_TABLES`. This is in its new
`codes.rs` file.
This makes no sense, and has no effect. I suspect it's been confused
with a `code = "{code}"` attribute on a subdiagnostic suggestion, where
it is valid (but the "code" there is suggested source code, rather than
an error code.)
Currently the documentation of `FileExt::seek_write` on Windows
indicates that writes beyond the end of the file leave intermediate
bytes uninitialized. This commentary dates back to the original
inclusion of these functions in #35704 (wow blast from the past!). At
the time the functionality here was implemented using `WriteFile`, but
nowadays the `NtWriteFile` method is used instead. The documentation for
`NtWriteFile` explicitly states:
> If Length and ByteOffset specify a write operation past the current
> end-of-file mark, NtWriteFile automatically extends the file and updates
> the end-of-file mark; any bytes that are not explicitly written between
> such old and new end-of-file marks are defined to be zero.
This commentary has had a downstream impact in the `system-interface`
crate where it tries to handle this by explicitly writing zeros, but I
don't believe that's necessary any more. I'm sending a PR upstream here
to avoid future confusion and codify that zeros are written in the
intermediate bytes matching what Windows currently provides.
Merge into larger interval set
This reduces the work done while merging rows. In at least one case (#50450), we have thousands of union([range], [20,000 ranges]), which previously inserted each of the 20,000 ranges one by one. Now we only insert one range into the right hand set after copying the set over.
This cuts the runtime of the test case in #50450 from ~26 seconds to ~6 seconds locally, though it doesn't change the memory usage peak (~9.5GB).
llvm: change data layout bug to an error and make it trigger more
Fixes#33446.
Don't skip the inconsistent data layout check for custom LLVMs or non-built-in targets.
With #118708, all targets will have a simple test that would trigger this error if LLVM's data layouts do change - so data layouts would be corrected during the LLVM upgrade. Therefore, with builtin targets, this error won't happen with our LLVM because each target will have been confirmed to work. With non-builtin targets, this error is probably useful to have because you can change the data layout in your target and if it is wrong then that could lead to bugs.
When using a custom LLVM, the same justification makes sense for non-builtin targets as with our LLVM, the user can update their target to match their LLVM and that's probably a good thing to do. However, with a custom LLVM, the user cannot change the builtin target data layouts if they don't match - though given that the compiler's data layout is used for layout computation and a bunch of other things - you could get some bugs because of the mismatch and probably want to know about that. I'm not sure if this is something that people do and is okay, but I doubt it?
`CFG_LLVM_ROOT` was also always set during local development with `download-ci-llvm` so this bug would never trigger locally.
In #33446, two points are raised:
- In the issue itself, changing this from a `bug!` to a proper error is what is suggested, by using `isCompatibleDataLayout` from LLVM, but that function still just does the same thing that we do and check for equality, so I've avoided the additional code necessary to do that FFI call.
- `@Mark-Simulacrum` suggests a different check is necessary to maintain backwards compatibility with old LLVM versions. I don't know how often this comes up, but we can do that with some simple string manipulation + LLVM version checks as happens already for LLVM 17 just above this diff.
Remove myself from review rotation
Still willing to do reviews (and make it through my backlog), but I don't have the bandwidth to be on the rotation right now.
Improve handling of numbers in `IntoDiagnosticArg`
While working on https://github.com/rust-lang/rust/pull/120393, I realize that my fluent selectors were not working. So here is an improvement (not a fix unfortunately).
ScopeTree: remove destruction_scopes as unused
last usages removed by https://github.com/rust-lang/rust/pull/116170
Unused, but still presented in memory at `t-gmax` (in DHAT termonology)
Properly recover from trailing attr in body
When encountering an attribute in a body, we try to recover from an attribute on an expression (as opposed to a statement). We need to properly clean up when the attribute is at the end of the body where a tail expression would be.
Fix#118164, fix#118575.