Rename `overlapping_patterns` lint
As discussed in https://github.com/rust-lang/rust/issues/65477. I also tweaked a few things along the way.
r? `@varkor`
`@rustbot` modify labels: +A-exhaustiveness-checking
Reserve necessary space for params in generics_of
Always reserve space for the exact number of generic parameters we need in generics_of. As far as I can see, the default is 0/4 elements based on has_self, and the vector grows on after that.
Acknowledge that `[CONST; N]` is stable
When `const_in_array_repeat_expressions` (RFC 2203) got unstably implemented as part of https://github.com/rust-lang/rust/pull/61749, accidentally, the special case of repeating a *constant* got stabilized immediately. That is why the following code works on stable:
```rust
const EMPTY: Vec<i32> = Vec::new();
pub const fn bar() -> [Vec<i32>; 2] {
[EMPTY; 2]
}
fn main() {
let x = bar();
}
```
In contrast, if we had written `[expr; 2]` for some expression that is not *literally* a constant but could be evaluated at compile-time (e.g. `(EMPTY,).0`), this would have failed.
We could take back this stabilization as it was clearly accidental. However, I propose we instead just officially accept this and stabilize a small subset of RFC 2203, while leaving the more complex case of general expressions that could be evaluated at compile-time unstable. Making that case work well is pretty much blocked on inline `const` expressions (to avoid relying too much on [implicit promotion](https://github.com/rust-lang/const-eval/blob/master/promotion.md)), so it could take a bit until it comes to full fruition. `[CONST; N]` is an uncontroversial subset of this feature that has no semantic ambiguities, does not rely on promotion, and basically provides the full expressive power of RFC 2203 but without the convenience (people have to define constants to repeat them, possibly using associated consts if generics are involved).
Well, I said "no semantic ambiguities", that is only almost true... the one point I am not sure about is `[CONST; 0]`. There are two possible behaviors here: either this is equivalent to `let x = CONST; [x; 0]`, or it is a NOP (if we argue that the constant is never actually instantiated). The difference between the two is that if `CONST` has a destructor, it should run in the former case (but currently doesn't, due to https://github.com/rust-lang/rust/issues/74836); but should not run if it is considered a NOP. For regular `[x; 0]` there seems to be consensus on running drop (there isn't really an alternative); any opinions for the `CONST` special case? Should this instantiate the const only to immediately run its destructors? That seems somewhat silly to me. After all, the `let`-expansion does *not* work in general, for `N > 1`.
Cc `@rust-lang/lang` `@rust-lang/wg-const-eval`
Cc https://github.com/rust-lang/rust/issues/49147
Ran the tidy check
Following the diagnostic guide better
Diagnostic generation is now relegated to its own function in the diagnostics module.
Added tests
Fixed the ui test
Fix pretty printing an AST representing `&(mut ident)`
The PR fixes a misguiding help diagnostic in the parser that I reported in #80186. I discovered that the parsers recovery and reporting logic was correct but the pretty printer produced wrong code for the example. (Details in https://github.com/rust-lang/rust/issues/80186#issuecomment-748498676)
Example:
```rust
#![allow(unused_variables)]
fn main() {
let mut &x = &0;
}
```
The AST fragment
`PatKind::Ref(PatKind::Ident(BindingMode::ByValue(Mutability::Mut), ..), Mutability::Not)`
was printed to be `&mut ident`. But this wouldn't round trip through parsing again, because then it would be:
`PatKind::Ref(PatKind::Ident(BindingMode::ByValue(Mutability::Not), ..), Mutability::Mut)`
Now the pretty-printer prints `&(mut ident)`. Reparsing that code results in the AST fragment
`PatKind::Ref(PatKind::Paren(PatKind::Ident(BindingMode::ByValue(Mutability::Mut), ..)), Mutability::Not)`
which I think should behave like the original pattern.
Old diagnostic:
```
error: `mut` must be attached to each individual binding
--> src/main.rs:3:9
|
3 | let mut &x = &0;
| ^^^^^^ help: add `mut` to each binding: `&mut x`
|
= note: `mut` may be followed by `variable` and `variable @ pattern`
```
New diagnostic:
```
error: `mut` must be attached to each individual binding
--> src/main.rs:3:9
|
3 | let mut &x = &0;
| ^^^^^^ help: add `mut` to each binding: `&(mut x)`
|
= note: `mut` may be followed by `variable` and `variable @ pattern`
```
Fixes#80186
Minor cleanups in LateResolver
- Avoid calculating hash twice
- Avoid creating a closure in every iteration of a loop
- Reserve space for path in advance
- Some readability changes
Handle desugaring in impl trait bound suggestion
Fixes#79843.
When an associated type of a generic function parameter needs extra bounds, the diagnostics may suggest replacing an `impl Trait` with a named type parameter so that it can be referenced in the where clause. On stable and nightly, the suggestion can be malformed, for instance transforming:
```rust
async fn run(_: &(), foo: impl Foo) -> std::io::Result<()>
```
Into:
```rust
async fn run(_: &, F: Foo(), foo: F) -> std::io::Result<()> where <F as Foo>::Bar: Send
^^^^^^^^ ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^
```
Where we want something like:
```rust
async fn run<F: Foo>(_: &(), foo: F) -> std::io::Result<()> where <F as Foo>::Bar: Send
^^^^^^^^ ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^
```
The problem is that the elided lifetime of `&()` is added as a generic parameter when desugaring the async fn; the suggestion code sees this as an existing generic parameter and tries to use its span as an anchor to inject `F` into the parameter list. There doesn't seem to be an entirely principled way to check which generic parameters in the HIR were explicitly named in the source, so this commit changes the heuristics when generating the suggestion to only consider type parameters whose spans are contained within the span of the `Generics` when determining how to insert an additional type parameter into the declaration. (And to be safe it also excludes parameters whose spans are marked as originating from desugaring, although that doesn't seem to handle this elided lifetime.)
Edit rustc_middle docs
Re-word doc comment for rustc_middle::hir::place::Projection.
Also adds:
- Missing end stop punctuation, and
- Documentation links to `rustc_middle::mir::Place`.
When normalizing a projection which results in a cycle, we would
cache the result of `project_type` without the nested obligations
(because they're not needed for inference). This would result in
the nested obligations only being handled once in fulfill, which
would avoid the cycle error.
Fixes#79714, a regresion from #79305 caused by the removal of
`get_paranoid_cache_value_obligation`.
Turn quadratic time on number of impl blocks into linear time
Previously, if you had a lot of inherent impl blocks on a type like:
```Rust
struct Foo;
impl Foo { fn foo_1() {} }
// ...
impl Foo { fn foo_100_000() {} }
```
The compiler would be very slow at processing it, because
an internal algorithm would run in O(n^2), where n is the number
of impl blocks. Now, we add a new algorithm that allocates but
is faster asymptotically.
Comparing rustc nightly with a local build of rustc as of this PR (results in seconds):
| N | real time before | real time after |
| - | - | - |
| 4_000 | 0.57 | 0.46 |
| 8_000 | 1.31 | 0.84 |
| 16_000 | 3.56 | 1.69 |
| 32_000 | 10.60 | 3.73 |
I've tuned up the numbers to make the effect larger than the startup noise of rustc, but the asymptotic difference should hold for smaller n as well.
Note: current state of the PR omits error messages if there are other errors present already. For now, I'm mainly interested in a perf run to study whether this issue is present at all. Please queue one for this PR. Thanks!
Re-word doc comment for rustc_middle::hir::place::Projection.
Also adds:
- Missing end stop punctuation, and
- Documentation links to `rustc_middle::mir::Place`.
`PatKind::Ref(PatKind::Ident(BindingMode::ByValue(Mutability::Mut), ..), ..)`
is an AST representing `&(mut ident)`. It was errorneously printed as
`&mut ident` which reparsed into a syntactically different AST.
This affected help diagnostics in the parser.
Make BoundRegion have a kind of BoungRegionKind
Split from #76814
Also includes making `replace_escaping_bound_vars` only return `T`
Going to r? `@lcnr`
Feel free to reassign
or_patterns: implement :pat edition-specific behavior
cc #54883 `@joshtriplett`
This PR implements the edition-specific behavior of `:pat` wrt or-patterns, as determined by the crater runs and T-lang consensus in https://github.com/rust-lang/rust/issues/54883#issuecomment-745509090.
I believe this can unblock stabilization of or_patterns.
r? `@petrochenkov`
const_evaluatable_checked: fix occurs check
fixes#79615
this is kind of a hack because we use `TypeRelation` for both the `Generalizer` and the `ConstInferUnifier` but i am not sure if there is a useful way to disentangle this without unnecessarily duplicating some code.
The error in the added test is kind of unavoidable until we erase the unused substs of `ConstKind::Unevaluated`. We talked a bit about this in the cg lazy norm meeting (https://rust-lang.zulipchat.com/#narrow/stream/260443-project-const-generics/topic/lazy_normalization_consts)
Improve and fix diagnostics of exhaustiveness checking
Primarily, this fixes https://github.com/rust-lang/rust/issues/56379. This also fixes incorrect interactions between or-patterns and slice patterns that I discovered while working on #56379. Those two examples show the incorrect diagnostics:
```rust
match &[][..] {
[true] => {}
[true // detected as unreachable but that's not true
| false, ..] => {}
_ => {}
}
match (true, None) {
(true, Some(_)) => {}
(false, Some(true)) => {}
(true | false, None | Some(true // should be detected as unreachable
| false)) => {}
}
```
I did not measure any perf impact. However, I suspect that [`616ba9f`](616ba9f9f7) should have a negative impact on large or-patterns. I'll see what the perf run says; I have optimization ideas up my sleeve if needed.
EDIT: I initially had a noticeable perf impact that I thought unavoidable. I then proceeded to avoid it x)
r? `@varkor`
`@rustbot` label +A-exhaustiveness-checking
Stabilize or_insert_with_key
Stabilizes the `or_insert_with_key` feature from https://github.com/rust-lang/rust/issues/71024. This allows inserting key-derived values when a `HashMap`/`BTreeMap` entry is vacant.
The difference between this and `.or_insert_with(|| ... )` is that this provides a reference to the key to the closure after it is moved with `.entry(key_being_moved)`, avoiding the need to copy or clone the key.
passes: prohibit invalid attrs on generic params
Fixes#78957.
This PR modifies the `check_attr` pass so that attribute placement on generic parameters is checked for validity.
r? `@lcnr`
Register nodes that we've reused from the previous session explicitly
with `OnDiskCache`. Previously, we relied on this happening as a side
effect of accessing the nodes in the `PreviousDepGraph`. For the sake of
performance and avoiding unintended side effects, register explictily.
This is elegant but a bit of a perf gamble. That said, or-patterns
rarely have many branches and it's easy to optimize or revert if we ever
need to. In the meantime simpler code is worth it.
Stop using intermediate macros in definition of symbols
Currently, the rustc_macros::symbols macro generates two
`macro_rules!` macros as its output. These two macros are
used in rustc_span/src/symbol.rs.
This means that each Symbol that we define is represented
in the AST of rustc_symbols twice: once in the definition
of the `define_symbols!` macro (similarly for the
`keywords! macro), and once in the rustc_span::symbols
definition.
That would be OK if there were only a handful of symbols,
but currently we define over 1100 symbols. The definition
of the `define_symbols!` macro contains the expanded definition
of each symbol, so that's a lot of AST storage wasted on a
macro that is used exactly once.
This commit removes the `define_symbols` macro, and simply
allows the proc macro to directly generate the
`rustc_symbols::symbol::sym` module.
The benefit is mainly in reducing memory wasted during
compilation of rustc itself. It should also reduce memory used
by Rust Analyzer.
This commit also reduces the size of the AST for symbol
definitions, by moving two `#[allow(...)]` attributes from
the symbol constants to the `sym` module. This eliminates 2200+
attribute nodes.
This commit also eliminates the need for the `digits_array`
constant. There's no need to store an array of Symbol values
for digits. We can simply define a constant of the base value,
and add to that base value.
I left the `sym::integer` function in rustc_span/src/symbol.rs
instead of moving it into rustc_macros/src/symbols.rs for two
reasons. First, because it's human-written code; it doesn't need
to be generated by the proc-macro. Second, because I didn't want
the `#[allow(...)]` attributes that I moved to the `sym` module
scope to apply to this function. The `sym` module re-exports the
`integer` function from its parent module.
Rollup of 5 pull requests
Successful merges:
- #78164 (Prefer regions with an `external_name` in `approx_universal_upper_bound`)
- #80003 (Fix overflow when converting ZST Vec to VecDeque)
- #80023 (Enhance error message when misspelled label to value in break expression)
- #80046 (Add more documentation to `Diagnostic` and `DiagnosticBuilder`)
- #80109 (Remove redundant and unreliable coverage test results)
Failed merges:
r? `@ghost`
`@rustbot` modify labels: rollup
Prefer regions with an `external_name` in `approx_universal_upper_bound`
Fixes#75785
When displaying a MIR borrowcheck error, we may need to find an upper
bound for a region, which gives us a region to point to in the error
message. However, a region might outlive multiple distinct universal
regions, in which case the only upper bound is 'static
To try to display a meaningful error message, we compute an
'approximate' upper bound by picking one of the universal regions.
Currently, we pick the region with the lowest index - however, this
caused us to produce a suboptimal error message in issue #75785
This PR `approx_universal_upper_bound` to prefer regions with an
`external_name`. This causes us to prefer regions from function
arguments/upvars, which seems to lead to a nicer error message in some
cases.
Currently, the rustc_macros::symbols macro generates two
`macro_rules!` macros as its output. These two macros are
used in rustc_span/src/symbol.rs.
This means that each Symbol that we define is represented
in the AST of rustc_symbols twice: once in the definition
of the `define_symbols!` macro (similarly for the
`keywords! macro), and once in the rustc_span::symbols
definition.
That would be OK if there were only a handful of symbols,
but currently we define over 1100 symbols. The definition
of the `define_symbols!` macro contains the expanded definition
of each symbol, so that's a lot of AST storage wasted on a
macro that is used exactly once.
This commit removes the `define_symbols` macro, and simply
allows the proc macro to directly generate the
`rustc_symbols::symbol::sym` module.
The benefit is mainly in reducing memory wasted during
compilation of rustc itself. It should also reduce memory used
by Rust Analyzer.
This commit also reduces the size of the AST for symbol
definitions, by moving two `#[allow(...)]` attributes from
the symbol constants to the `sym` module. This eliminates 2200+
attribute nodes.
This commit also eliminates the need for the `digits_array`
constant. There's no need to store an array of Symbol values
for digits. We can simply define a constant of the base value,
and add to that base value.
Fixes#75785
When displaying a MIR borrowcheck error, we may need to find an upper
bound for a region, which gives us a region to point to in the error
message. However, a region might outlive multiple distinct universal
regions, in which case the only upper bound is 'static
To try to display a meaningful error message, we compute an
'approximate' upper bound by picking one of the universal regions.
Currently, we pick the region with the lowest index - however, this
caused us to produce a suboptimal error message in issue #75785
This PR `approx_universal_upper_bound` to prefer regions with an
`external_name`. This causes us to prefer regions from function
arguments/upvars, which seems to lead to a nicer error message in some
cases.
Move binder for dyn to each list item
This essentially changes `ty::Binder<&'tcx List<ExistentialTraitRef>>` to `&'tcx List<ty::Binder<ExistentialTraitRef>>`.
This is a first step in moving the `dyn Trait` representation closer to Chalk, which we've talked about in `@rust-lang/wg-traits.`
r? `@nikomatsakis`
Always run intrinsics lowering pass
Move intrinsics lowering pass from the optimization phase (where it
would not run if -Zmir-opt-level=0), to the drop lowering phase where it
runs unconditionally.
The implementation of those intrinsics in code generation and
interpreter is unnecessary. Remove it.
Fixed conflict with drop elaboration and coverage
See
https://github.com/rust-lang/rust/issues/80045#issuecomment-745733339
Coverage statements are moved to the beginning of the BCB. This does
also affect what's counted before a panic, changing some results, but I
think these results may even be preferred? In any case, there are no
guarantees about what's counted when a panic occurs (by design).
r? `@tmandry`
FYI `@wesleywiser` `@ecstatic-morse`
Fix issue #78496
EarlyOtherwiseBranch finds MIR structures like:
```
bb0: {
...
_2 = discriminant(X)
...
switchInt(_2) -> [1_isize: bb1, otherwise: bb3]
}
bb1: {
...
_3 = discriminant(Y)
...
switchInt(_3) -> [1_isize: bb2, otherwise: bb3]
}
bb2: {...}
bb3: {...}
```
And transforms them into something like:
```
bb0: {
...
_2 = discriminant(X)
_3 = discriminant(Y)
_4 = Eq(_2, _3)
switchInt(_4) -> [true: bb4, otherwise: bb3]
}
bb2: {...} // unchanged
bb3: {...} // unchanged
bb4: {
switchInt(_2) -> [1_isize: bb2, otherwise: bb3]
}
```
But that is not always a safe thing to do -- sometimes the early `otherwise` branch is necessary so the later block could assume the value of `discriminant(X)`.
I am not totally sure what's the best way to detect that, but fixing #78496 should be easy -- we just check if `X` is a sub-expression of `Y`. A more precise test might be to check if `Y` contains a `Downcast(1)` of `X`, but I think this might be good enough.
Fix#78496
Allow `since="TBD"` for rustc_deprecated
Closes#78381.
This PR only affects `#[rustc_deprecated]`, not `#[deprecated]`, so there is no effect on any stable language feature.
Likewise this PR only implements `since="TBD"`, it does not actually tag any library functions with it, so there is no effect on any stable API.
Overview of changes:
* `rustc_middle/stability.rs`:
* change `deprecation_in_effect` function to return `false` when `since="TBD"`
* tidy up the compiler output when a deprecated item has `since="TBD"`
* `rustc_passes/stability.rs`:
* allow `since="TBD"` to pass the sanity check for stable_version < deprecated_version
* refactor the "invalid stability version" and "invalid deprecation version" error into separate errors
* rustdoc: make `since="TBD"` message on a deprecated item's page match the command-line deprecation output
* tests:
* test rustdoc output
* test that the `deprecated_in_future` lint fires when `since="TBD"`
* test the new "invalid deprecation version" error message
Implement if-let match guards
Implements rust-lang/rfcs#2294 (tracking issue: #51114).
I probably should do a few more things before this can be merged:
- [x] Add tests (added basic tests, more advanced tests could be done in the future?)
- [x] Add lint for exhaustive if-let guard (comparable to normal if-let statements)
- [x] Fix clippy
However since this is a nightly feature maybe it's fine to land this and do those steps in follow-up PRs.
Thanks a lot `@matthewjasper` ❤️ for helping me with lowering to MIR! Would you be interested in reviewing this?
r? `@ghost` for now
Take into account negative impls in "trait item not found" suggestions
This removes the suggestion to implement a trait for a type when that type already has a negative implementation for the trait, and replaces it with a note to point out that the trait is explicitely unimplemented, as suggested by `@scottmcm.`
Helps with #79683.
r? `@scottmcm` do you want to review this?
llvm-dwp concatenates `DW_AT_comp_dir` with `DW_AT_GNU_dwo_name` (only
when `DW_AT_comp_dir` exists), which can result in it failing to find
the DWARF object files.
In earlier testing, `DW_AT_comp_dir` wasn't present in the final
object and the current directory was the output directory.
When running tests through compiletest, the working directory of the
compilation is different from output directory and that resulted in
`DW_AT_comp_dir` being in the object file (and set to the current
working directory, rather than the output directory), and
`DW_AT_GNU_dwo_name` being set to the full path (rather than just
the filename), so llvm-dwp was failing.
This commit changes the compilation directory provided to LLVM to match
the output directory, where DWARF objects are output; and ensures that
only the filename is used for `DW_AT_GNU_dwo_name`.
Signed-off-by: David Wood <david@davidtw.co>
This commit adds a Split DWARF compare mode to compiletest so that
debuginfo tests are also tested using Split DWARF in split mode (and
manually in single mode).
Signed-off-by: David Wood <david@davidtw.co>
This commit makes minor changes to the cranelift backend so that it can
build given changes in cg_ssa for Split DWARF.
Signed-off-by: David Wood <david@davidtw.co>
This commit implements Split DWARF support, wiring up the flag (added in
earlier commits) to the modified FFI wrapper (also from earlier
commits).
Signed-off-by: David Wood <david@davidtw.co>
This commit removes the `TargetMachineFactory` struct and adds a
`TargetMachineFactoryFn` type alias which is used everywhere that the
previous, long type was used.
Signed-off-by: David Wood <david@davidtw.co>
This commit changes some comments to documentation comments so that
they can be read on the generated rustdoc.
Signed-off-by: David Wood <david@davidtw.co>
This commit modifies the FFI bindings to LLVM required for Split DWARF
support in rustc. In particular:
- `addPassesToEmitFile`'s wrapper, `LLVMRustWriteOutputFile` now takes
a `DwoPath` `const char*`. When disabled, `nullptr` should be provided
which will preserve existing behaviour. When enabled, the path to the
`.dwo` file should be provided.
- `createCompileUnit`'s wrapper, `LLVMRustDIBuilderCreateCompileUnit`
now has two additional arguments, for the `DWOId` and to enable
`SplitDebugInlining`. `DWOId` should always be zero.
- `createTargetMachine`'s wrapper, `LLVMRustCreateTargetMachine` has an
additional argument which should be provided the path to the `.dwo`
when enabled.
Signed-off-by: David Wood <david@davidtw.co>
See
https://github.com/rust-lang/rust/issues/80045#issuecomment-745733339
Coverage statements are moved to the beginning of the BCB. This does
also affect what's counted before a panic, changing some results, but I
think these results may even be preferred? In any case, there are no
guarantees about what's counted when a panic occurs (by design).
make MIR graphviz generation use gsgdt
gsgdt [https://crates.io/crates/gsgdt] is a crate which provides an
interface for stringly typed graphs. It also provides generation of
graphviz dot format from said graph.
This is the first in a series of PRs on moving graphviz code out of rustc into normal crates and then implementating graph diffing on top of these crates.
r? `@oli-obk`
[rustdoc] Switch to Symbol for item.name
This decreases the size of `Item` from 680 to 616 bytes. It also does a
lot less work since it no longer has to copy as much.
Helps with #79103.
r? `@GuillaumeGomez`
Fixes reported bugs in Rust Coverage
Fixes: #79569Fixes: #79566Fixes: #79565
For the first issue (#79569), I got hit a `debug_assert!()` before
encountering the reported error message (because I have `debug = true`
enabled in my config.toml).
The assertion showed me that some `SwitchInt`s can have more than one
target pointing to the same `BasicBlock`.
I had thought that was invalid, but since it seems to be possible, I'm
allowing this now.
I added a new test for this.
----
In the last two cases above, both tests (intentionally) fail to compile,
but the `InstrumentCoverage` pass is invoked anyway.
The MIR starts with an `Unreachable` `BasicBlock`, which I hadn't
encountered before. (I had assumed the `InstrumentCoverage` pass
would only be invoked with MIRs from successful compilations.)
I don't have test infrastructure set up to test coverage on files that
fail to compile, so I didn't add a new test.
r? `@tmandry`
FYI: `@wesleywiser`
consider assignments of union field of ManuallyDrop type safe
Assigning to `Copy` union fields is safe because that assignment will never drop anything. However, with https://github.com/rust-lang/rust/pull/77547, unions may also have `ManuallyDrop` fields, and their assignments are currently still unsafe. That seems unnecessary though, as assigning `ManuallyDrop` does not drop anything either, and is thus safe even for union fields.
I assume this will at least require FCP.
[mir-opt] Allow debuginfo to be generated for a constant or a Place
Prior to this commit, debuginfo was always generated by mapping a name
to a Place. This has the side-effect that `SimplifyLocals` cannot remove
locals that are only used for debuginfo because their other uses have
been const-propagated.
To allow these locals to be removed, we now allow debuginfo to point to
a constant value. The `ConstProp` pass detects when debuginfo points to
a local with a known constant value and replaces it with the value. This
allows the later `SimplifyLocals` pass to remove the local.
Move intrinsics lowering pass from the optimization phase (where it
would not run if -Zmir-opt-level=0), to the drop lowering phase where it
runs unconditionally.
The implementation of those intrinsics in code generation and
interpreter is unnecessary. Remove it.
Adds checks for:
* `no_core` attribute
* explicitly-enabled `legacy` symbol mangling
* mir_opt_level > 1 (which enables inlining)
I removed code from the `Inline` MIR pass that forcibly disabled
inlining if `-Zinstrument-coverage` was set. The default `mir_opt_level`
does not enable inlining anyway. But if the level is explicitly set and
is greater than 1, I issue a warning.
The new warnings show up in tests, which is much better for diagnosing
potential option conflicts in these cases.
Improve error handling in `symbols` proc-macro
This improves how the `symbols` proc-macro handles errors.
If it finds an error in its input, the macro does not panic.
Instead, it still produces an output token stream. That token
stream will contain `compile_error!(...)` macro invocations.
This will still cause compilation to fail (which is what we want),
but it will prevent meaningless errors caused by the output not
containing symbols that the macro normally generates.
This solves a small (but annoying) problem. When you're editing
rustc_span/src/symbol.rs, and you get something wrong (dup
symbol name, misordered symbol), you want to get only the errors
that are relevant, not a burst of errors that are irrelevant.
This change also uses the correct Span when reporting errors,
so you get errors that point to the correct place in
rustc_span/src/symbol.rs where something is wrong.
This also adds several unit tests which test the `symbols` proc-macro.
This commit also makes it easy to run the `symbols` proc-macro
as an ordinary Cargo test. Just run `cargo test`. This makes it
easier to do development on the macro itself, such as running it
under a debugger.
This commit also uses the `Punctuated` type in `syn` for parsing
comma-separated lists, rather than doing it manually.
The output of the macro is not changed at all by this commit,
so rustc should be completely unchanged. This just improves
quality of life during development.
Properly capture trailing 'unglued' token
If we try to capture the `Vec<u8>` in `Option<Vec<u8>>`, we'll
need to capture a `>` token which was 'unglued' from a `>>` token.
The processing of unglueing a token for parsing purposes bypasses the
usual capturing infrastructure, so we currently lose the trailing `>`.
As a result, we fall back to the reparsed `TokenStream`, causing us to
lose spans.
This commit makes token capturing keep track of a trailing 'unglued'
token. Note that we don't need to care about unglueing except at the end
of the captured tokens - if we capture both the first and second unglued
tokens, then we'll end up capturing the full 'glued' token, which
already works correctly.
Recover on `const impl<> X for Y`
`@leonardo-m` mentioned that `const impl Foo for Bar` could be recovered from in #79287.
I'm not sure about the error strings as they are, I think it should probably be something like the error that `expected_one_of_not_found` makes + the suggestion to flip the keywords, but I'm not sure how exactly to do that. Also, I decided not to try to handle `const unsafe impl` or `unsafe const impl` cause I figured that `unsafe impl const` would be pretty rare anyway (if it's even valid?), and it wouldn't be worth making the code more messy.
Resolve enum field visibility correctly
Fixes#79593. 🎉
Previously, this code treated enum fields' visibility as if they were
struct fields. However, that's not correct because the visibility of a
struct field with `ast::VisibilityKind::Inherited` is private to the
module it's defined in, whereas the visibility of an *enum* field with
`ast::VisibilityKind::Inherited` is the visibility of the enum it
belongs to.
Remove an unused dependency that made `rustdoc` crash
Whilst struggling with https://github.com/rust-lang/rust/issues/79980 I discovered that this dependency was unused, and that made rustdoc crash. This PR removes it.
fix more clippy::complexity findings
fix clippy::unnecessary_filter_map
use if let Some(x) = .. instead of ...map(|x|) to conditionally run fns that return () (clippy::option_map_unit_fn)
fix clippy::{needless_bool, manual_unwrap_or}
don't clone types that are copy (clippy::clone_on_copy)
don't convert types into identical types with .into() (clippy::useless_conversion)
use strip_prefix over slicing (clippy::manual_strip)
r? ``@Dylan-DPC``
This improves how the `symbols` proc-macro handles errors.
If it finds an error in its input, the macro does not panic.
Instead, it still produces an output token stream. That token
stream will contain `compile_error!(...)` macro invocations.
This will still cause compilation to fail (which is what we want),
but it will prevent meaningless errors caused by the output not
containing symbols that the macro normally generates.
This solves a small (but annoying) problem. When you're editing
rustc_span/src/symbol.rs, and you get something wrong (dup
symbol name, misordered symbol), you want to get only the errors
that are relevant, not a burst of errors that are irrelevant.
This change also uses the correct Span when reporting errors,
so you get errors that point to the correct place in
rustc_span/src/symbol.rs where something is wrong.
This also adds several unit tests which test the `symbols` proc-macro.
This commit also makes it easy to run the `symbols` proc-macro
as an ordinary Cargo test. Just run `cargo test`. This makes it
easier to do development on the macro itself, such as running it
under a debugger.
This commit also uses the `Punctuated` type in `syn` for parsing
comma-separated lists, rather than doing it manually.
The output of the macro is not changed at all by this commit,
so rustc should be completely unchanged. This just improves
quality of life during development.
Previously, this code treated enum fields' visibility as if they were
struct fields. However, that's not correct because the visibility of a
struct field with `ast::VisibilityKind::Inherited` is private to the
module it's defined in, whereas the visibility of an *enum* field with
`ast::VisibilityKind::Inherited` is the visibility of the enum it
belongs to.
If we try to capture the `Vec<u8>` in `Option<Vec<u8>>`, we'll
need to capture a `>` token which was 'unglued' from a `>>` token.
The processing of unglueing a token for parsing purposes bypasses the
usual capturing infrastructure, so we currently lose the trailing `>`.
As a result, we fall back to the reparsed `TokenStream`, causing us to
lose spans.
This commit makes token capturing keep track of a trailing 'unglued'
token. Note that we don't need to care about unglueing except at the end
of the captured tokens - if we capture both the first and second unglued
tokens, then we'll end up capturing the full 'glued' token, which
already works correctly.
Create `rustc_type_ir`
Decided to start small 😄
This PR creates a `rustc_type_ir` crate as part of the WG-Traits plan to create a shared type library.
~~There already exists a `rustc_ty` crate, so I named the new crate `rustc_ty_library`. However I think it would make sense to rename the current `rustc_ty` to something else (e.g. `rustc_ty_passes`) to free the name for this new crate.~~
r? `@jackh726`
Fixes: #79569Fixes: #79566Fixes: #79565
For the first issue (#79569), I got hit a `debug_assert!()` before
encountering the reported error message (because I have `debug = true`
enabled in my config.toml).
The assertion showed me that some `SwitchInt`s can have more than one
target pointing to the same `BasicBlock`.
I had thought that was invalid, but since it seems to be possible, I'm
allowing this now.
I added a new test for this.
----
In the last two cases above, both tests (intentionally) fail to compile,
but the `InstrumentCoverage` pass is invoked anyway.
The MIR starts with an `Unreachable` `BasicBlock`, which I hadn't
encountered before. (I had assumed the `InstrumentCoverage` pass
would only be invoked with MIRs from successful compilations.)
I don't have test infrastructure set up to test coverage on files that
fail to compile, so I didn't add a new test.
Capture precise paths in THIR and MIR
This PR allows THIR and MIR to use the result of the new capture analysis to actually capture precise paths
To achieve we:
- Writeback min capture results to TypeckResults
- Move handling upvars to PlaceBuilder in mir_build
- Lower precise paths in THIR build by reading min_captures
- Search for ancestors in min_capture when trying to build a MIR place which starts off of an upvar
Closes: https://github.com/rust-lang/project-rfc-2229/issues/10
Partly implements: rust-lang/project-rfc-2229#18
Work that remains (not in this PR):
- [ ] [Known bugs when feature gate is enabled](https://github.com/rust-lang/project-rfc-2229/projects/1?card_filter_query=label%3Abug)
- [ ] Use min_capure_map for
- [ ] Liveness analysis
- [ ] rustc_mir/interpret/validity.rs
- [ ] regionck
- [ ] rust-lang/project-rfc-2229#8
- [ ] remove closure_captures and upvar_capture_map
r? `@ghost`
CTFE: tweak abort-on-uninhabited message
Having an "aborted execution:" makes it more consistent with the `Abort` terminator saying "the program aborted execution". Right now, at least one of the two errors will look weird in Miri.
r? `@oli-obk`
Use `def_path_hash_to_def_id` when re-using a `RawDefId`
Fixes#79890
Previously, we just copied a `RawDefId` from the 'old' map to the 'new'
map. However, the `RawDefId` for a given `DefPathHash` may be different
in the current compilation session. Using `def_path_hash_to_def_id`
ensures that the `RawDefId` we use is valid in the current session.
Use Symbol for inline asm register class names
This takes care of one "FIXME":
// FIXME: use direct symbol comparison for register class names
Instead of using string literals, this uses Symbol for register
class names.
This is part of work I am doing to improve how Symbol interning works.
Clarify the 'default is only allowed on...' error
Code like
impl Foo {
default fn foo() {}
}
will trigger the error
error: `default` is only allowed on items in `impl` definitions
--> src/lib.rs:5:5
|
5 | default fn foo() {}
| -------^^^^^^^^^
| |
| `default` because of this
but that's very confusing! I *did* put it on an item in an impl!
So this commit changes the message to
error: `default` is only allowed on items in trait impls
--> src/lib.rs:5:5
|
5 | default fn foo() {}
| -------^^^^^^^^^
| |
| `default` because of this
Dogfood `str_split_once()`
Part of https://github.com/rust-lang/rust/issues/74773.
Beyond increased clarity, this fixes some instances of a common confusion with how `splitn(2)` behaves: the first element will always be `Some()`, regardless of the delimiter, and even if the value is empty.
Given this code:
```rust
fn main() {
let val = "...";
let mut iter = val.splitn(2, '=');
println!("Input: {:?}, first: {:?}, second: {:?}", val, iter.next(), iter.next());
}
```
We get:
```
Input: "no_delimiter", first: Some("no_delimiter"), second: None
Input: "k=v", first: Some("k"), second: Some("v")
Input: "=", first: Some(""), second: Some("")
```
Using `str_split_once()` makes more clear what happens when the delimiter is not found.
This takes care of one "FIXME":
// FIXME: use direct symbol comparison for register class names
Instead of using string literals, this uses Symbol for register
class names.
Fixes#79890
Previously, we just copied a `RawDefId` from the 'old' map to the 'new'
map. However, the `RawDefId` for a given `DefPathHash` may be different
in the current compilation session. Using `def_path_hash_to_def_id`
ensures that the `RawDefId` we use is valid in the current session.
rustc_codegen_ssa: use bitcasts instead of type punning for scalar transmutes.
This specifically helps with `f32` <-> `u32` (`from_bits`, `to_bits`) in Rust-GPU (`rustc_codegen_spirv`), where (AFAIK) we don't yet have enough infrastructure to turn type punning memory accesses into SSA bitcasts.
(There may be more instances, but the one I've seen myself is `f32::signum` from `num-traits` inspecting e.g. the sign bit)
Sadly I've had to make an exception for `transmute`s between pointers and non-pointers, as LLVM disallows using `bitcast` for them.
r? `@nagisa` cc `@khyperia`
Constier maybe uninit
I was playing around trying to make `[T; N]::zip()` in #79451 be `const fn`. One of the things I bumped into was `MaybeUninit::assume_init`. Is there any reason for the intrinsic `assert_inhabited<T>()` and therefore `MaybeUninit::assume_init` not being `const`?
---
I have as best as I could tried to follow the instruction in [library/core/src/intrinsics.rs](https://github.com/rust-lang/rust/blob/master/library/core/src/intrinsics.rs#L11). I have no idea what I am doing but it seems to compile after some slight changes after the copy paste. Is this anywhere near how this should be done?
Also any ideas for name of the feature gate? I guess `const_maybe_assume_init` is quite misleading since I have added some more methods. Should I add test? If so what should be tested?
- Closures now use closure_min_captures to figure out captured paths
- Build upvar_mutbls using closure_min_captures
- Change logic in limit_capture_mutability to differentiate b/w
capturing parent's local variable or capturing a variable that is
captured by the parent (in case of nested closure) using PlaceBase.
Co-authored-by: Roxane Fruytier <roxane.fruytier@hotmail.com>
- Use closure_min_capture maps to capture precise paths
- PlaceBuilder now searches for ancestors in min_capture list
- Add API to `Ty` to allow access to the n-th element in a
tuple in O(1) time.
Co-authored-by: Roxane Fruytier <roxane.fruytier@hotmail.com>
Rollup of 12 pull requests
Successful merges:
- #79732 (minor stylistic clippy cleanups)
- #79750 (Fix trimming of lint docs)
- #79777 (Remove `first_merge` from liveness debug logs)
- #79795 (Privatize some of libcore unicode_internals)
- #79803 (Update xsv to prevent random CI failures)
- #79810 (Account for gaps in def path table during decoding)
- #79818 (Fixes to Rust coverage)
- #79824 (Strip prefix instead of replacing it with empty string)
- #79826 (Simplify visit_{foreign,trait}_item)
- #79844 (Move RWUTable to a separate module)
- #79861 (Update LLVM submodule)
- #79862 (Remove tab-lock and replace it with ctrl+up/down arrows to switch between search result tabs)
Failed merges:
r? `@ghost`
`@rustbot` modify labels: rollup
Simplify visit_{foreign,trait}_item
Using an `if` seems like a better semantic fit and saves a few lines.
Noticed while looking at https://github.com/rust-lang/rust/pull/79752, but that's already merged.
r? `@lcnr,` cc `@cjgillot`
`@rustbot` modify labels +C-cleanup +T-compiler
Strip prefix instead of replacing it with empty string
r? `@lcnr,` since you reviewed my other PR in the area.
`@rustbot` modify labels +C-cleanup +T-compiler