-
Notifications
You must be signed in to change notification settings - Fork 562
Mention sharing the solver with rust-analyzer #2668
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
ShoyuVanilla
wants to merge
1
commit into
rust-lang:main
Choose a base branch
from
ShoyuVanilla:ra-solver
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,109 @@ | ||||||||||||||
| # Sharing the trait solver with rust-analyzer | ||||||||||||||
|
|
||||||||||||||
| rust-analyzer can be viewed as a compiler frontend: it performs tasks similar to the parts of rustc | ||||||||||||||
| that run before code generation, such as parsing, lexing, AST construction and lowering, HIR | ||||||||||||||
| lowering, and even limited MIR building and const evaluation. | ||||||||||||||
|
|
||||||||||||||
| However, because rust-analyzer is primarily a language server, its architecture differs in several | ||||||||||||||
| important ways from that of rustc. | ||||||||||||||
| Despite these differences, a substantial portion of its responsibilities—most notably type | ||||||||||||||
| inference and trait solving—overlap with the compiler. | ||||||||||||||
|
|
||||||||||||||
| To avoid duplication and to maintain consistency between the two implementations, rust-analyzer | ||||||||||||||
| reuses several crates from rustc, relying on shared abstractions wherever possible. | ||||||||||||||
|
|
||||||||||||||
| ## Shared Crates | ||||||||||||||
|
|
||||||||||||||
| Currently, rust-analyzer depends on several `rustc_*` crates from the compiler: | ||||||||||||||
|
|
||||||||||||||
| - `rustc_abi` | ||||||||||||||
| - `rustc_ast_ir` | ||||||||||||||
| - `rustc_index` | ||||||||||||||
| - `rustc_lexer` | ||||||||||||||
| - `rustc_next_trait_solver` | ||||||||||||||
| - `rustc_parse_format` | ||||||||||||||
| - `rustc_pattern_analysis` | ||||||||||||||
| - `rustc_type_ir` | ||||||||||||||
|
|
||||||||||||||
| Since these crates are not published on `crates.io` as part of the compiler's normal distribution | ||||||||||||||
| process, rust-analyzer maintains its own publishing pipeline. | ||||||||||||||
| It uses the [rustc-auto-publish script][rustc-auto-publish] to publish these crates to `crates.io` | ||||||||||||||
| with the prefix `ra-ap-rustc_*` | ||||||||||||||
| (for example: https://crates.io/crates/ra-ap-rustc_next_trait_solver). | ||||||||||||||
| rust-analyzer then depends on these re-published crates in its own build. | ||||||||||||||
|
|
||||||||||||||
| For trait solving specifically, the primary shared crates are `rustc_type_ir` and | ||||||||||||||
| `rustc_next_trait_solver`, which provide the core IR and solver logic used by both compiler | ||||||||||||||
| frontends. | ||||||||||||||
|
|
||||||||||||||
| ## The Abstract Layer | ||||||||||||||
|
|
||||||||||||||
| Because rust-analyzer is a language server, it must handle frequently changing source code and | ||||||||||||||
| partially invalid or incomplete source codes. | ||||||||||||||
| This requires an infrastructure quite different from rustc's, especially in the layers between | ||||||||||||||
| the source code and the HIR—for example, `Ty` and its backing interner. | ||||||||||||||
|
|
||||||||||||||
| To bridge these differences, the compiler provides `rustc_type_ir` as an abstract layer shared | ||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||
| between rustc and rust-analyzer. | ||||||||||||||
| This crate defines the fundamental interfaces used to represent types, predicates, and the context | ||||||||||||||
| required by the trait solver. | ||||||||||||||
| Both rustc and rust-analyzer implement these traits for their own concrete type representations, | ||||||||||||||
| and `rustc_next_trait_solver` is written to be generic over these abstractions. | ||||||||||||||
|
|
||||||||||||||
| In addition to these interfaces, `rustc_type_ir` also includes several non-trivial components built | ||||||||||||||
| on top of the abstraction layer—such as elaboration logic and the search graph machinery used by the | ||||||||||||||
| solver. | ||||||||||||||
|
|
||||||||||||||
| ## Design Concepts | ||||||||||||||
|
|
||||||||||||||
| `rustc_next_trait_solver` is intended to depend only on the abstract interfaces defined in | ||||||||||||||
| `rustc_type_ir`. | ||||||||||||||
| To support this, the type-system traits in `rustc_type_ir` must expose every interface the solver | ||||||||||||||
| requires—for example, [creating a new inference type variable][ir new_infer] | ||||||||||||||
| ([rustc][rustc new_infer], [rust-analyzer][r-a new_infer]) | ||||||||||||||
|
Comment on lines
+61
to
+63
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||
| For items that do not need compiler-specific representations, `rustc_type_ir` defines them directly | ||||||||||||||
| as structs or enums parameterized over these traits—for example, [`TraitRef`][ir tr]. | ||||||||||||||
|
|
||||||||||||||
| The central trait in this design is [`Interner`][ir interner], which specifies all | ||||||||||||||
| implementation-specific details for both rustc and rust-analyzer. | ||||||||||||||
| Among its essential responsibilities: | ||||||||||||||
|
|
||||||||||||||
| - it **specifies** the concrete types used by the implementation via its | ||||||||||||||
| [associated types][ir interner assocs]; these form the backbone of how each compiler frontend | ||||||||||||||
| instantiates the shared IR, | ||||||||||||||
| - it provides the context required by the solver (e.g., querying [lang items][ir require_lang_item], | ||||||||||||||
| enumerating [all blanket impls for a trait][ir for_each_blanket_impl]); | ||||||||||||||
| - and it must implement [`IrPrint`][ir irprint] for formatting and tracing. | ||||||||||||||
| In practice, these `IrPrint` impls simply route to existing formatting logic inside rustc or | ||||||||||||||
| rust-analyzer. | ||||||||||||||
|
|
||||||||||||||
| In general, we aim to support rust-analyzer just as well as rustc in these shared crates—provided | ||||||||||||||
| doing so does not substantially harm rustc's performance or maintainability. | ||||||||||||||
| (e.g., [#145377][pr 145377], [#146111][pr 146111], [#146182][pr 146182] and [#147723][pr 147723]) | ||||||||||||||
|
|
||||||||||||||
| Shared crates that require nightly-only features must guard such code behind a `nightly` feature | ||||||||||||||
| flag, since rust-analyzer is built with the stable toolchain. | ||||||||||||||
|
|
||||||||||||||
| Looking forward, we plan to uplift more shared logic into `rustc_type_ir`. | ||||||||||||||
| There are still duplicated implementations between rustc and rust-analyzer—such as `ObligationCtxt` | ||||||||||||||
| ([rustc][rustc oblctxt], [rust-analyzer][r-a oblctxt]) and type coercion logic | ||||||||||||||
| ([rustc][rustc coerce], [rust-analyzer][r-a coerce])—that we would like to unify over time. | ||||||||||||||
|
|
||||||||||||||
| [rustc-auto-publish]: https://github.com/rust-analyzer/rustc-auto-publish | ||||||||||||||
| [ir new_infer]: https://doc.rust-lang.org/1.91.1/nightly-rustc/rustc_type_ir/inherent/trait.Ty.html#tymethod.new_infer | ||||||||||||||
| [rustc new_infer]: https://github.com/rust-lang/rust/blob/63b1db05801271e400954e41b8600a3cf1482363/compiler/rustc_middle/src/ty/sty.rs#L413-L420 | ||||||||||||||
| [r-a new_infer]: https://github.com/rust-lang/rust-analyzer/blob/34f47d9298c478c12c6c4c0348771d1b05706e09/crates/hir-ty/src/next_solver/ty.rs#L59-L92 | ||||||||||||||
| [ir tr]: https://doc.rust-lang.org/1.91.1/nightly-rustc/rustc_type_ir/struct.TraitRef.html | ||||||||||||||
| [ir interner]: https://doc.rust-lang.org/1.91.1/nightly-rustc/rustc_type_ir/trait.Interner.html | ||||||||||||||
| [ir interner assocs]: https://doc.rust-lang.org/1.91.1/nightly-rustc/rustc_type_ir/trait.Interner.html#required-associated-types | ||||||||||||||
| [ir require_lang_item]: https://doc.rust-lang.org/1.91.1/nightly-rustc/rustc_type_ir/trait.Interner.html#tymethod.require_lang_item | ||||||||||||||
| [ir for_each_blanket_impl]: https://doc.rust-lang.org/1.91.1/nightly-rustc/rustc_type_ir/trait.Interner.html#tymethod.for_each_blanket_impl | ||||||||||||||
| [ir irprint]: https://doc.rust-lang.org/1.91.1/nightly-rustc/rustc_type_ir/ir_print/trait.IrPrint.html | ||||||||||||||
| [pr 145377]: https://github.com/rust-lang/rust/pull/145377 | ||||||||||||||
| [pr 146111]: https://github.com/rust-lang/rust/pull/146111 | ||||||||||||||
| [pr 146182]: https://github.com/rust-lang/rust/pull/146182 | ||||||||||||||
| [pr 147723]: https://github.com/rust-lang/rust/pull/147723 | ||||||||||||||
| [rustc oblctxt]: https://github.com/rust-lang/rust/blob/63b1db05801271e400954e41b8600a3cf1482363/compiler/rustc_trait_selection/src/traits/engine.rs#L48-L386 | ||||||||||||||
| [r-a oblctxt]: https://github.com/rust-lang/rust-analyzer/blob/34f47d9298c478c12c6c4c0348771d1b05706e09/crates/hir-ty/src/next_solver/obligation_ctxt.rs | ||||||||||||||
| [rustc coerce]: https://github.com/rust-lang/rust/blob/63b1db05801271e400954e41b8600a3cf1482363/compiler/rustc_hir_typeck/src/coercion.rs | ||||||||||||||
| [r-a coerce]: https://github.com/rust-lang/rust-analyzer/blob/34f47d9298c478c12c6c4c0348771d1b05706e09/crates/hir-ty/src/infer/coerce.rs | ||||||||||||||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think? The layer is used to abstract something, it's not abstract itself