It sees them as regular impls; the details are abstracted. It's beautiful for the IDE layer, and less beautiful for `hir`, so this is a big change.
Some small differences still exist:
- We show builtin derives impl (to the IDE layer) as if they have had no generic parameters. It is possible to show the parameters, but that means also having to handle fake impls in `TypeParam` etc., and the benefit is questionable.
- Getting the fn *def* type of a method of a builtin derive impl is not supported, as there is no real `FunctionId`, therefore no `CallableDefId`. The trait method is returned instead. Note: getting the fn *ptr* type of the method is supported well.
- Builtin derive impls and their methods do not fully support `HasSource`, because, well, they have no source (at least, not in the form of `ast::Impl` and `ast::Fn`). To support them, we use the derive's `TextRange` where possible, and the trait method's source when not.
It's important to note that the def map still records the `MacroCallId`. I have doubts over this, as this means it's very easy to create the queries we don't want to create, but it does make things more convenient. In particular, a nicety of this setup is that even "Expand macro recursively" works (it creates the macro input/output query, but given that they will only be created when the user invokes the command, that does not seem to be a problem).
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
In the inferred type hints, expand the line too long. add config to disable it.
Example
---
```json
{"rust-analyzer.inlayHints.typeHints.hideInferredTypes": true}
```
```rust
use std::collections::HashMap;
fn foo(iter: Vec<Result<HashMap<String, String>, std::io::Error>>) {
let output = iter.into_iter().collect::<Result<Vec<_>, _>>().unwrap();
}
```
**Before this PR**
```rust
let output: Vec<HashMap<String, String>> = iter.into_iter().collect::<Result<Vec<_ = HashMap<String, String>>, _ = Error>>().unwrap();
```
**After this PR**
```rust
let output: Vec<HashMap<String, String>> = iter.into_iter().collect::<Result<Vec<_>, _>>().unwrap();
```
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.
Lang items rarely change, so putting a query for each doesn't give us anything. On the other hand, putting them behind only one query not only saves memory, it also has a giant benefit: we can store the struct with all lang items in the interner, making access to them very cheap. That basically means that anything in the hot path can avoid a *very common* query, and exchange it for a simple field access.
Previously we didn't set the enclosing position on definitions, so
SCIP consumers didn't know the position of the entire definition that
provides the symbol.
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.
I don't do it by default, for three reasons: (1) it's more expensive, (2) I actually quite like seeing the derives, and they may expand to no impl/more than one impl, (3) if #19130 will ever be merged this will become even more useful.
Even a config might be too much, but it was fun and easy to code so I did that.
By letting the solver take control of them (reveal them when needed and define them when needed), by providing them in the `TypingMode` plus few helpers.