Since the commit 50384460c68f
("Rewrite method resolution to follow rustc more closely"), the method
resolution logic has changed: rust-analyzer only looks up inherent
methods for primitive types in sysroot crates.
Unfortunately, this change broke at least one project that relies on
`rust-project.json`: Rust-for-Linux. Its auto-generated
`rust-project.json` directly embeds `core`, `alloc`, and `std` in the
`crates` list without defining `sysroot_src`. Consequently,
rust-analyzer fails to identify them as sysroot crates, breaking IDE
support for primitive methods (e.g., `0_i32.rotate_left(0)`).
However, specifying `sysroot_src` creates a new issue: it implicitly
adds `std` as a dependency to all kernel module crates, which are
actually compiled with `-Zcrate-attr=no_std`. Since rust-analyzer cannot
see compiler flags passed outside of the project definition, we need a
method to explicitly specify `#![no_std]` or, more generally,
crate-level attributes through the project configuration.
To resolve this, extend the `rust-project.json` format with a new
`crate_attrs` field. This allows users to specify crate-level attributes
such as `#![no_std]` directly into the configuration, enabling
rust-analyzer to respect them when analyzing crates.
References:
- The original Zulip discussion:
https://rust-lang.zulipchat.com/#narrow/channel/185405-t-compiler.2Frust-analyzer/topic/Primitive.20type.20inherent.20method.20lookup.20fails/with/562983853
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.
Basically, we switch to expanding cfg_attr in AST form, filter irrelevant attributes from the item tree, and move hir-def attributes (non-item-tree) to be flag-based.
The main motivation is memory usage, although this also simplifies the code, and fixes some bugs around handling of `cfg_attr`s.
It cannot be exactly the same, because we have needs rustc doesn't have (namely, accurate enumeration of all methods, not just with a specific name, for completions etc., while rustc also needs a best-effort implementation for diagnostics) but it is closer than the previous impl.
In addition we rewrite the closely related handling of operator inference and impl collection.
This in turn necessitate changing some other parts of inference in order to retain behavior. As a result, the behavior more closely matches rustc and is also more correct.
This fixes 2 type mismatches on self (1 remains) and 4 diagnostics (1 remains), plus some unknown types.
Basically, we switch to expanding cfg_attr in AST form, filter irrelevant attributes from the item tree, and move hir-def attributes (non-item-tree) to be flag-based.
The main motivation is memory usage, although this also simplifies the code, and fixes some bugs around handling of `cfg_attr`s.
It didn't do anything (behaved like `item`), as with `enforceGranularity = false` (which is the default), the style of the current file is always preferred, regardless of the setting.
We could make it fail when the setting is `preserve` and the current file's style could not be detected, but that makes little sense.
It is a bit weird that the default is `crate` but `preserve` falls back to `item`, however that was the previous behavior.
Two fixes were needed:
1. Previously, we enabled elision for the generic args of `Fn` itself, instead of for generic args of paths within it.
2. In lowering in the new solver the `Output` parameter did not have elision set correctly, I don't know why. In the old lowering it was done correctly.
Example
---
```rust
struct S { field : u32 }
fn main() {
let s = S { field : 2 };
let S { $0field } = s
}
```
**Before this PR**:
```rust
struct S { field : u32 }
fn main() {
let s = S { field : 2 };
let S { _field } = s
}
```
**After this PR**:
```rust
struct S { field : u32 }
fn main() {
let s = S { field : 2 };
let S { field: _field } = s
}
```