fix ICE when {{root}} appears in import suggestions
Fixesrust-lang/rust#150103
When wrong nested imports like `use A::{::Fish}` were used, the internal {{root}} would appear in diagnostic suggestions, causing an ICE in `join_path_idents` which asserted that **{{root}} should only appear at the start of a path**.
r? ``@matthiaskrgr``
Replace Rvalue::NullaryOp by a variant in mir::Operand.
Based on https://github.com/rust-lang/rust/pull/148151
This PR fully removes the MIR `Rvalue::NullaryOp`. After rust-lang/rust#148151, it was only useful for runtime checks like `ub_checks`, `contract_checks` and `overflow_checks`.
These are "runtime" checks, boolean constants that may only be `true` in codegen. It depends on a rustc flag passed to codegen, so we need to represent those flags cross-crate.
This PR replaces those runtime checks by special variants in MIR `ConstValue`. This allows code that expects constants to manipulate those as such, even if we may not always be able to evaluate them to actual scalars.
Better closure requirement propagation.
Fixesrust-lang/rust#148289Fixesrust-lang/rust#104477
Should unblock rust-lang/rust#148187
When propagating closure requirements we:
- no longer try to find a post dominiting region for the list of non-local lower bounds of `longer_fr`.
- we filter the list of `longer_fr-: shorter_fr+` to only these constraints between external regions which are required regardless. If no such constraint exists, we fall back to propagating all of them.
See the [FCP](https://github.com/rust-lang/rust/pull/148329#issuecomment-3581019253) for more information.
r? `@lcnr`
Perf regression fix
The only thing changed from the previous PR is that I removed `output_is_inhabited` from hot path, and hide it behind condition, so now it will compute it less frequent
follow up on https://github.com/rust-lang/rust/pull/149664
Prefer remapping the relative `library/` and `compiler/` directories
This is done to avoid leaking the relative paths to the standard library after the overall of filenames in rust-lang/rust#149709.
Noted that the paths were already leaking before, but to a lesser extent since most (but not all) the paths embedded in the distributed `rlib` were absolute.
In general Cargo compiles workspace members with relative paths, so it's better anyway to remap the relative path.
In addition to our tests I have manually confirmed that it also works as expected for the printed diagnostics paths.
cf. https://rust-lang.zulipchat.com/#narrow/channel/131828-t-compiler/topic/remapping.20of.20the.20standard.20library/near/564093571
Make closure capturing have consistent and correct behaviour around patterns
Reference PR:
- https://github.com/rust-lang/reference/pull/1837
This PR has two goals:
- firstly, it fixesrust-lang/rust#137467. In order to do so, it needs to introduce a small breaking change surrounding the interaction of closure captures with matching against enums with uninhabited variants. Yes – to fix an ICE!
- this also fixesrust-lang/rust#138973, a slightly different case with the same root cause.
- likewise, fixesrust-lang/rust#140011.
- secondly, it fixesrust-lang/rust#137553, making the closure capturing rules consistent between `let` patterns and `match` patterns. This is new insta-stable behavior.
## Background
This change concerns how precise closure captures interact with patterns. As a little known feature, patterns that require inspecting only part of a value will only cause that part of the value to get captured:
```rust
fn main() {
let mut a = (21, 37);
// only captures a.0, writing to a.1 does not invalidate the closure
let mut f = || {
let (ref mut x, _) = a;
*x = 42;
};
a.1 = 69;
f();
}
```
I was not able to find any discussion of this behavior being introduced, or discussion of its edge-cases, but it is [documented in the Rust reference](https://doc.rust-lang.org/reference/types/closure.html#r-type.closure.capture.precision.wildcard).
The currently stable behavior is as follows:
- if any pattern contains a binding, the place it binds gets captured (implemented in current `walk_pat`)
- patterns in refutable positions (`match`, `if let`, `let ... else`, but not destructuring `let` or destructuring function parameters) get processed as follows (`maybe_read_scrutinee`):
- if matching against the pattern will at any point require inspecting a discriminant, or it includes a variable binding not followed by an ``@`-pattern,` capture *the entire scrutinee* by reference
You will note that this behavior is quite weird and it's hard to imagine a sensible rationale for at least some of its aspects. It has the following issues:
- firstly, it assumes that matching against an irrefutable pattern cannot possibly require inspecting any discriminants. With or-patterns, this isn't true, and it is the cause of the rust-lang/rust#137467 ICE.
- secondly, the presence of an ``@`-pattern` doesn't really have any semantics by itself. This is the weird behavior tracked as rust-lang/rust#137553.
- thirdly, the behavior is different between pattern-matching done through `let` and pattern-matching done through `match` – which is a superficial syntactic difference
This PR aims to address all of the above issues. The new behavior is as follows:
- like before, if a pattern contains a binding, the place it binds gets captured as required by the binding mode
- if matching against the pattern requires inspecting a disciminant, the place whose discriminant needs to be inspected gets captured by reference
"requires inspecting a discriminant" is also used here to mean "compare something with a constant" and other such decisions. For types other than ADTs, the details are not interesting and aren't changing.
## The breaking change
During closure capture analysis, matching an `enum` against a constructor is considered to require inspecting a discriminant if the `enum` has more than one variant. Notably, this is the case even if all the other variants happen to be uninhabited. This is motivated by implementation difficulties involved in querying whether types are inhabited before we're done with type inference – without moving mountains to make it happen, you hit this assert: 43f0014ef0/compiler/rustc_middle/src/ty/inhabitedness/mod.rs (L121)
Now, because the previous implementation did not concern itself with capturing the discriminants for irrefutable patterns at all, this is a breaking change – the following example, adapted from the testsuite, compiles on current stable, but will not compile with this PR:
```rust
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
enum Void {}
pub fn main() {
let mut r = Result::<Void, (u32, u32)>::Err((0, 0));
let mut f = || {
let Err((ref mut a, _)) = r;
*a = 1;
};
let mut g = || {
//~^ ERROR: cannot borrow `r` as mutable more than once at a time
let Err((_, ref mut b)) = r;
*b = 2;
};
f();
g();
assert_eq!(r, Err((1, 2)));
}
```
## Is the breaking change necessary?
One other option would be to double down, and introduce a set of syntactic rules for determining whether a sub-pattern is in an irrefutable position, instead of querying the types and checking how many variants there are.
**This would not eliminate the breaking change,** but it would limit it to more contrived examples, such as
```rust
let ((true, Err((ref mut a, _, _))) | (false, Err((_, ref mut a, _)))) = x;
```
In this example, the `Err`s would not be considered in an irrefutable position, because they are part of an or-pattern. However, current stable would treat this just like a tuple `(bool, (T, U, _))`.
While introducing such a distinction would limit the impact, I would say that the added complexity would not be commensurate with the benefit it introduces.
## The new insta-stable behavior
If a pattern in a `match` expression or similar has parts it will never read, this part will not be captured anymore:
```rust
fn main() {
let mut a = (21, 37);
// now only captures a.0, instead of the whole a
let mut f = || {
match a {
(ref mut x, _) => *x = 42,
}
};
a.1 = 69;
f();
}
```
Note that this behavior was pretty much already present, but only accessible with this One Weird Trick™:
```rust
fn main() {
let mut a = (21, 37);
// both stable and this PR only capture a.0, because of the no-op `@-pattern`
let mut f = || {
match a {
(ref mut x @ _, _) => *x = 42,
}
};
a.1 = 69;
f();
}
```
## The second, more practically-relevant breaking change
After running crater, we have discovered that the aforementioned insta-stable behavior, where sometimes closures will now capture less, can also manifest as a breaking change. This is because it is possible that previously a closure would capture an entire struct by-move, and now it'll start capturing only part of it – some by move, and some by reference. This then causes the closure to have a more restrictive lifetime than it did previously.
See:
- https://github.com/rust-lang/rust/pull/138961#issuecomment-2761888557
- https://github.com/EC-labs/cec-assignment/pull/1
- https://github.com/tryandromeda/andromeda/pull/43
## Implementation notes
The PR has two main commits:
- "ExprUseVisitor: properly report discriminant reads" makes `walk_pat` perform all necessary capturing. This is the part that fixesrust-lang/rust#137467.
- "ExprUseVisitor: remove maybe_read_scrutinee" removes the unnecessary "capture the entire scrutinee" behavior, fixing rust-lang/rust#137553.
The new logic stops making the distinction between one particular example that used to work, and another ICE, tracked as rust-lang/rust#119786. As this requires an unstable feature, I am leaving this as future work.
Fix span note for question mark expression
Fixesrust-lang/rust#144304
Seems it's better to fix the note instead of modifying the span to cover the whole expression.
r? `@estebank`
std: small `sys` refactor
Part of rust-lang/rust#117276
The large number of files changed just results from the need to update a lot of imports. Actually this PR only:
* combines the two definitions of `RawOsError` in `sys::pal` into one in `sys::io`
* moves `FULL_BACKTRACE_DEFAULT` from `sys::pal` to `sys::backtrace`
* moves the `FromInner`/`IntoInner`/... traits into `sys` (in preparation for removing `sys_common` entirely)
Don't leak sysroot crates through dependencies
Previously if a dependency of the current crate depended on a sysroot crate, then `extern crate` would in the current crate would pick the first loaded version of said sysroot crate even in case of an ambiguity. This is surprising and brittle. For `-Ldependency=` we already blocked this since rust-lang/rust#110229, but the fix didn't account for sysroot crates.
Should fix https://github.com/rust-lang/rust/issues/147966
Reverse the order of returned lint attributes for a `SyntaxNode` to
match rustc's behavior.
When multiple lint attributes are present, rustc overrides earlier ones
with the last defined attribute. The previous iteration order was
incorrect, causing earlier attributes to override the later ones.
Externally implementable items
Supersedes https://github.com/rust-lang/rust/pull/140010
Tracking issue: https://github.com/rust-lang/rust/issues/125418
Getting started:
```rust
#![feature(eii)]
#[eii(eii1)]
pub fn decl1(x: u64)
// body optional (it's the default)
{
println!("default {x}");
}
// in another crate, maybe
#[eii1]
pub fn decl2(x: u64) {
println!("explicit {x}");
}
fn main() {
decl1(4);
}
```
- tiny perf regression, underlying issue makes multiple things in the compiler slow, not just EII, planning to solve those separately.
- No codegen_gcc support, they don't have bindings for weak symbols yet but could
- No windows support yet for weak definitions
This PR merges the implementation of EII for just llvm + not windows, doesn't yet contain like a new panic handler implementation or alloc handler. With this implementation, it would support implementing the panic handler in terms of EII already since it requires no default implementation so no weak symbols
The PR has been open in various forms for about a year now, but I feel that having some implementation merged to build upon
Overhaul filename handling for cross-compiler consistency
This PR overhauls the way we handle filenames in the compiler and `rmeta` in order to achieve achieve cross-compiler consistency (ie. having the same path no matter if the filename was created in the current compiler session or is coming from `rmeta`).
This is required as some parts of the compiler rely on consistent paths for the soundness of generated code (see rust-lang/rust#148328).
In order to achieved consistency multiple steps are being taken by this PR:
- by making `RealFileName` immutable
- by only having `SourceMap::to_real_filename` create `RealFileName`
- currently `RealFileName` can be created from any `Path` and are remapped afterwards, which creates consistency issue
- by also making `RealFileName` holds it's working directory, embeddable name and the remapped scopes
- this removes the need for a `Session`, to know the current(!) scopes and cwd, which is invalid as they may not be equal to the scopes used when creating the filename
In order for `SourceMap::to_real_filename` to know which scopes to apply `FilePathMapping` now takes the current remapping scopes to apply, which makes `FileNameDisplayPreference` and company useless and are removed.
This PR is split-up in multiple commits (unfortunately not atomic), but should help review the changes.
Unblocks https://github.com/rust-lang/rust/pull/147611
Fixes https://github.com/rust-lang/rust/issues/148328
Run main rust-analyzer tests in rust-lang/rust CI
Part of rust-lang/rust#147370.
MCP: https://github.com/rust-lang/compiler-team/issues/923
This PR prepares `rust-analyzer` crates with `in-rust-tree` cargo featues where needed, and and updates bootstrap to run the main `rust-analyzer` tests in rust-lang/rust CI, not just the `proc-macro-srv` crate tests.
This supersedes the earlier attempt at https://github.com/rust-lang/rust/pull/136779. I was honestly expecting more failures in this PR, but looking back at the previous attempt, that makes sense because we no longer run `i686-mingw` (32-bit windows-gnu) which had a _bunch_ of these failures. In the earlier attempt I also disabled the `i686-mingw`-related failures for `i686-msvc` since I didn't feel like digging into 32-bit msvc at the time. Try results from this PR shows that it's most likely limited to 32-bit windows-gnu specifically.
### `rust-analyzer` test remarks
- I actually had to _remove_ the `CARGO_WORKSPACE_DIR` `expect-test`-hack in order for `expect-test` to be able to find the test expectation HTML files (for `syntax_highlighting` tests in `ide`). When I added the hack, ironically, it made `expect-test` unable to find the expectation files. I think this was because previously the path was of the `proc-macro-srv` crate specifically, now we point to the root r-a workspace?
- The `cfg`-related differences on `aarch64-apple-darwin` might've been fixed? I can't tell, but we don't seem to be observing the differences now.
- I'm not sure why `config::{generate_config_documentation, generate_package_json_config}` no longer fails. Perhaps they were fixed to no longer try to write to source directory?
### Review remarks
- Commit 1 updates r-a crates that are involved in tests needing artifacts from `rustc_private` compiler crates to use the `in-rust-tree` cargo feature. I briefly tried to use a plain `--cfg=in_rust_tree`, but quickly realized it was very hacky, and needed invasive bootstrap changes. The cargo feature approach seems most "natural"/well-supported to both bootstrap and cargo.
- Commit 2 updates bootstrap to not only run the `proc-macro-srv` tests, but the whole r-a tests.
- Commit 3 restricts r-a main tests to non-32-bit targets we test in CI, since (1) r-a repo does not run tests against 32-bit platforms, and (2) there are some target pointer width sensitive hash differences causing tests to fail. Notably, this means that we also no longer run r-a `proc-macro-srv` tests against 32-bit targets, but we don't expect that crate to be have target pointer width differences. Discussed this in [#t-compiler/rust-analyzer > 32-bit tests?](https://rust-lang.zulipchat.com/#narrow/channel/185405-t-compiler.2Frust-analyzer/topic/32-bit.20tests.3F/with/563145736).
---
// try-job: aarch64-gnu
// try-job: aarch64-apple
// try-job: x86_64-mingw-1
// try-job: i686-msvc-1
// try-job: x86_64-msvc-1
// try-job: aarch64-msvc-1
This assist is often before inline and is very inconvenient
Usually, incomplete expression statements are written at the tail of the block, but they are not the return value of the block
```rust
fn foo() {
Some(2).$0and(optb)
}
```
```text
1. Add this function's return type
2. Inline `and`
3. Qualify `and` method call
4. Replace and with and_then
```
Update server capabilities to set `save` to `None` when the client supports
dynamic registration for `didSaveTextDocument`. This prevents redundant
static registration and aligns with LSP specification.