Add Cargo-style project discovery for Buck and Bazel Users
This feature requires the user to add a command that generates a `rust-project.json` from a set of files. Project discovery can be invoked in two ways:
1. At extension activation time, which includes the generated `rust-project.json` as part of the linkedProjects argument in `InitializeParams`.
2. Through a new command titled "rust-analyzer: Add current file to workspace", which makes use of a new, rust-analyzer-specific LSP request that adds the workspace without erasing any existing workspaces. Note that there is no mechanism to _remove_ workspaces other than "quit the rust-analyzer server".
Few notes:
- I think that the command-running functionality _could_ merit being placed into its own extension (and expose it via extension contribution points) to provide build-system idiomatic progress reporting and status handling, but I haven't (yet) made an extension that does this nor does Buck expose this sort of functionality.
- This approach would _just work_ for Bazel. I'll try and get the tool that's responsible for Buck integration open-sourced soon.
- On the testing side of things, I've used this in around my employer's Buck-powered monorepo and it's a nice experience. That being said, I can't think of an open-source repository where this can be tested in public, so you might need to trust me on this one.
I'd love to get feedback on:
- Naming of LSP extensions/new commands. I'm not too pleased with how "rust-analyzer: Add current file to workspace" is named, in that it's creating a _new_ workspace. I think that this command being added should be gated on `rust-analyzer.discoverProjectCommand` on being set, so I can add this in sequent commits.
- My Typescript. It's not particularly good.
- Suggestions on handling folders with _both_ Cargo and non-Cargo build systems and if I make activation a bit better.
(I previously tried to add this functionality entirely within rust-analyzer-the-LSP server itself, but matklad was right—an extension side approach is much, much easier.)
Rollup of 9 pull requests
Successful merges:
- #108722 (Support for Fuchsia RISC-V target)
- #108880 (Remove tests/ui/impl-trait/in-trait/new-lowering-strategy in favor of using revisions on existing tests)
- #108909 (Fix object safety checks for new RPITITs)
- #108915 (Remove some direct calls to local_def_id_to_hir_id on diagnostics)
- #108923 (Make fns from other crates with RPITIT work for -Zlower-impl-trait-in-trait-to-assoc-ty)
- #109101 (Fall back to old metadata computation when type references errors)
- #109105 (Don't ICE for late-bound consts across `AnonConstBoundary`)
- #109110 (Don't codegen impossible to satisfy impls)
- #109116 (Emit diagnostic when calling methods on the unit type in method chains)
Failed merges:
r? `@ghost`
`@rustbot` modify labels: rollup
Emit diagnostic when calling methods on the unit type in method chains
Fixes#104204.
What this PR does: If a method is not found somewhere in a call chain, we check if we called earlier a method with signature `(&mut T, ...) -> ()`. If this is the case then we emit a diagnostic message.
For example given input:
```
vec![1, 2, 3].into_iter().collect::<Vec<i32>>().sort_by_key(|i| i).sort();
```
the current output is:
```
error[E0599]: no method named `sort` found for unit type `()` in the current scope
--> hello.rs:3:72
|
3 | vec![1, 2, 3].into_iter().collect::<Vec<i32>>().sort_by_key(|i| i).sort();
| ^^^^ method not found in `()`
```
after this PR it will be:
```
error[E0599]: no method named `sort` found for unit type `()` in the current scope
--> ./hello.rs:3:72
|
3 | vec![1, 2, 3].into_iter().collect::<Vec<i32>>().sort_by_key(|i| i).sort();
| ^^^^ method not found in `()`
|
note: method `sort_by_key` modifies its receiver in-place, it is not meant to be used in method chains.
--> ./hello.rs:3:53
|
3 | vec![1, 2, 3].into_iter().collect::<Vec<i32>>().sort_by_key(|i| i).sort();
| ^^^^^^^^^^^ this call modifies its receiver in-place
```
Fall back to old metadata computation when type references errors
Projection is a bit too aggressive normalizing `<dyn Trait<[type error]> as Pointee>::Metadata` to `[type error]`, rather than to `DynMetadata<..>`. Side-step that by just falling back to the old structural metadata computation.
Fixes#109078
Make fns from other crates with RPITIT work for -Zlower-impl-trait-in-trait-to-assoc-ty
Only the last two commits are meaningful.
r? `@compiler-errors`
Remove some direct calls to local_def_id_to_hir_id on diagnostics
Was playing with `tests/ui/impl-trait/in-trait/default-body-with-rpit.rs` and was able to remove some ICEs. Still getting ...
```
error[E0277]: `impl Future<Output = Foo::{opaque#0}>` is not a future
--> tests/ui/impl-trait/in-trait/default-body-with-rpit.rs:10:28
|
10 | async fn baz(&self) -> impl Debug {
| ^^^^^^^^^^ `impl Future<Output = Foo::{opaque#0}>` is not a future
|
= help: the trait `Future` is not implemented for `impl Future<Output = Foo::{opaque#0}>`
= note: impl Future<Output = Foo::{opaque#0}> must be a future or must implement `IntoFuture` to be awaited
note: required by a bound in `Foo::{opaque#1}`
--> tests/ui/impl-trait/in-trait/default-body-with-rpit.rs:10:28
|
10 | async fn baz(&self) -> impl Debug {
| ^^^^^^^^^^ required by this bound in `Foo::{opaque#1}`
error[E0277]: the size for values of type `impl Future<Output = Foo::{opaque#0}>` cannot be known at compilation time
--> tests/ui/impl-trait/in-trait/default-body-with-rpit.rs:10:28
|
10 | async fn baz(&self) -> impl Debug {
| ^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `impl Future<Output = Foo::{opaque#0}>`
note: required by a bound in `Foo::{opaque#1}`
--> tests/ui/impl-trait/in-trait/default-body-with-rpit.rs:10:28
|
10 | async fn baz(&self) -> impl Debug {
| ^^^^^^^^^^ required by this bound in `Foo::{opaque#1}`
error: internal compiler error: compiler/rustc_hir_typeck/src/closure.rs:724:18: async fn generator return type not an inference variable: Foo::{opaque#1}<'_>
--> tests/ui/impl-trait/in-trait/default-body-with-rpit.rs:10:39
|
10 | async fn baz(&self) -> impl Debug {
| _______________________________________^
11 | | ""
12 | | }
| |_____^
```
But I guess this is a little bit of progress anyway.
This one goes on top of #108700 and #108945
r? `@compiler-errors`
Remove tests/ui/impl-trait/in-trait/new-lowering-strategy in favor of using revisions on existing tests
r? `@compiler-errors`
This one again sits on top of existing approved PRs and it still needs to add revisions to tests in `tests/ui/impl-trait/in-trait` as it only does so for async in traits.
Support for Fuchsia RISC-V target
Fuchsia is in the process of implementing the RISC-V support. This change implements the minimal Rust compiler support. The support for building runtime libraries will be implemented in follow up changes once Fuchsia SDK has the RISC-V support.
If no method is found when checking method call, we check if we called a method with signature (&mut T, ...) -> (). If this is the case then we emit a diagnostic message
Properly allow macro expanded `format_args` invocations to uses captures
Originally, this was kinda half-allowed. There were some primitive checks in place that looked at the span to see whether the input was likely a literal. These "source literal" checks are needed because the spans created during `format_args` parsing only make sense when it is indeed a literal that was written in the source code directly.
This is orthogonal to the restriction that the first argument must be a "direct literal", not being exanpanded from macros. This restriction was imposed by [RFC 2795] on the basis of being too confusing. But this was only concerned with the argument of the invocation being a literal, not whether it was a source literal (maybe in spirit it meant it being a source literal, this is not clear to me).
Since the original check only really cared about source literals (which is good enough to deny the `format_args!(concat!())` example), macros expanding to `format_args` invocations were able to use implicit captures if they spanned the string in a way that lead back to a source string.
The "source literal" checks were not strict enough and caused ICEs in certain cases (see #106191). So I tightened it up in #106195 to really only work if it's a direct source literal.
This caused the `indoc` crate to break. `indoc` transformed the source literal by removing whitespace, which made it not a "source literal" anymore (which is required to fix the ICE). But since `indoc` spanned the literal in ways that made the old check think that it's a literal, it was able to use implicit captures (which is useful and nice for the users of `indoc`).
This commit properly seperates the previously introduced concepts of "source literal" and "direct literal" and therefore allows `indoc` invocations, which don't create "source literals" to use implicit captures again.
Fixes#106191
[RFC 2795]: https://rust-lang.github.io/rfcs/2795-format-args-implicit-identifiers.html#macro-hygiene
Sometimes, we want to create subspans and point at code in the literal
if possible. But this doesn't always make sense, sometimes the literal
may come from macro expanded code and isn't actually there in the
source. Then, we can't really make these suggestions.
This now makes sure that the literal is actually there as we see it so
that we will not run into ICEs on weird literal transformations.
Originally, this was kinda half-allowed. There were some primitive
checks in place that looked at the span to see whether the input was
likely a literal. These "source literal" checks are needed because the
spans created during `format_args` parsing only make sense when it is
indeed a literal that was written in the source code directly.
This is orthogonal to the restriction that the first argument must be a
"direct literal", not being exanpanded from macros. This restriction was
imposed by [RFC 2795] on the basis of being too confusing. But this was
only concerned with the argument of the invocation being a literal, not
whether it was a source literal (maybe in spirit it meant it being a
source literal, this is not clear to me).
Since the original check only really cared about source literals (which
is good enough to deny the `format_args!(concat!())` example), macros
expanding to `format_args` invocations were able to use implicit
captures if they spanned the string in a way that lead back to a source
string.
The "source literal" checks were not strict enough and caused ICEs in
certain cases (see # 106191 (the space is intended to avoid spammy
backreferences)). So I tightened it up in # 106195 to really only work
if it's a direct source literal.
This caused the `indoc` crate to break. `indoc` transformed the source
literal by removing whitespace, which made it not a "source literal"
anymore (which is required to fix the ICE). But since `indoc` spanned
the literal in ways that made the old check think that it's a literal,
it was able to use implicit captures (which is useful and nice for the
users of `indoc`).
This commit properly seperates the previously introduced concepts of
"source literal" and "direct literal" and therefore allows `indoc`
invocations, which don't create "source literals" to use implicit
captures again.
[RFC 2795]: https://rust-lang.github.io/rfcs/2795-format-args-implicit-identifiers.html#macro-hygiene
Remove `identity_future` indirection
This was previously needed because the indirection used to hide some unexplained lifetime errors, which it turned out were related to the `min_choice` algorithm.
Removing the indirection also solves a couple of cycle errors, large moves and makes async blocks support the `#[track_caller]`annotation.
Fixes https://github.com/rust-lang/rust/issues/104826.
internal: add `as_slice` to `hir::Type`
~`remove_slice`~ `as_slice` is same as `remove_ref` but for slices.
Though there is `as_array` which I believe was named such because it also gets the length of the array, maybe. I am still shaky on the names feel free to suggest corrections.
feat: add `is_float` & `is_char` to `hir::Type`
Some useful functions we didn't have on `Type` (were present on `BuiltinType`).
Also, I am considering exposing `TyKind` with `get_kind`, let me know if that's a better idea than implementing these API extensions incrementally.
Add path of workspace root folders to status output
Hi folks! Just a quick addition to the status output. There are some colleagues of mine who use a mix of Buck and Cargo. A person spent a bit of time this past week trying to figure out there the `rust-project.json` was coming from and pointed out that `rust-analyzer: Status` could be a good place to put this information. rust-analyzer doesn't seem to record the full path of the `Cargo.toml` or the `rust-project.json`, just the root directory. While not perfect, this should be enough for people to unblock themselves on. Here's an example of `rust-analyzer: Status` on the rust-analyzer repo:
```
Workspaces:
Loaded 192 packages across 1 workspace.
Workspace roots: [AbsPath("/Users/dbarsky/Developer/rust-analyzer")]
Analysis:
57mb of files
0b of index symbols (0)
2514 trees, 128 preserved
29535 trees, 128 preserved (Macros)
0b in total
File info:
Crate: rust_analyzer(CrateId(131))
Dependencies: proc_macro=CrateId(5), core=CrateId(2), alloc=CrateId(0), std=CrateId(7), test=CrateId(9), always_assert=CrateId(12), anyhow=CrateId(13), cfg=CrateId(25), crossbeam_channel=CrateId(35), dissimilar=CrateId(41), expect_test=CrateId(46), flycheck=CrateId(50), hir=CrateId(56), hir_def=CrateId(57), hir_ty=CrateId(59), ide=CrateId(63), ide_db=CrateId(66), ide_ssr=CrateId(68), itertools=CrateId(73), jod_thread=CrateId(75), lsp_server=CrateId(83), lsp_types=CrateId(85), mbe=CrateId(87), num_cpus=CrateId(96), oorandom=CrateId(99), parking_lot=CrateId(102), proc_macro_api=CrateId(110), proc_macro_srv=CrateId(111), profile=CrateId(118), project_model=CrateId(119), rayon=CrateId(125), rustc_hash=CrateId(136), scip=CrateId(141), serde=CrateId(145), serde_json=CrateId(147), sourcegen=CrateId(153), stdx=CrateId(155), syntax=CrateId(158), test_utils=CrateId(159), threadpool=CrateId(165), toolchain=CrateId(170), tracing=CrateId(171), tracing_log=CrateId(174), tracing_subscriber=CrateId(175), tracing_tree=CrateId(176), tt=CrateId(177), vfs=CrateId(188), vfs_notify=CrateId(189), xflags=CrateId(192), xshell=CrateId(194)
```