|
| 1 | += This Year in rust-analyzer: 2021 |
| 2 | +:sectanchors: |
| 3 | +:page-layout: post |
| 4 | + |
| 5 | +[NOTE] |
| 6 | +==== |
| 7 | +In case this post picks your interest in contributing, consider checking out the https://www.youtube.com/playlist?list=PLhb66M_x9UmrqXhQuIpWC5VgTdrGxMx3y[Explaining rust-analyzer] series on youtube, check out the development docs on the https://github.com/rust-analyzer/rust-analyzer/tree/master/docs/dev[github repo] or visit our https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Frust-analyzer[Zulip Stream]. |
| 8 | +==== |
| 9 | + |
| 10 | +A lot has happened this year, so we want to take a brief look back at what we have achieved and what has yet to come. |
| 11 | + |
| 12 | +Unfortunately we did not manage to make rust-analyzer an official rust project this year, but if all goes well this should change at the start of the coming one. |
| 13 | + |
| 14 | +We started the year out by trying out a new meeting style different from our usual weekly sync meeting on https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Frust-analyzer/topic/weekly.20sync-up[Zulip]. A steering meeting repeating every 6 weeks where the working group gets together and discusses what topics and issues to focus on for the next 6 weeks. |
| 15 | + |
| 16 | +== (Proc-)Macros and Attributes |
| 17 | + |
| 18 | +Probably one of the biggest improvements that landed this year was attribute |
| 19 | +proc-macro support, landed in https://github.com/rust-analyzer/rust-analyzer/pull/9128[#9128]. Attributes are used pervasively in some Rust codebases, usually expanding to enough new items (functions, `impl` blocks etc.) to be essential in making the IDE work without significantly degrading the user experience. It took us roughly 4 months until we felt comfortable enough to enable their expansion https://github.com/rust-analyzer/rust-analyzer/pull/10366[by default], the main reason being the amount of code that had to be adapted to properly support attributed items. |
| 20 | +Unfortunately, while this feature mostly works nowadays, there is still one big problem we are facing, that of how attributes can interact with incomplete syntax. The problem is described in issue https://github.com/rust-analyzer/rust-analyzer/issues/11014[#11014] in more detail, but in short terms, attribute proc macros fail to expand when they encounter syntax errors, as is often the case when the user is typing. Of course, function-like proc macros are also affected in a similar way. We are still unsure about how to address this problem, so if you have any thoughts on the matter please comment on the linked issue. |
| 21 | + |
| 22 | +Attributes aside, a lot of improvements landed for proc-macros in general. We enabled https://github.com/rust-analyzer/rust-analyzer/pull/8032[proc-macros by default], https://github.com/rust-analyzer/rust-analyzer/pull/7412[started loading proc-macros asynchronously] and added some support for https://github.com/rust-analyzer/rust-analyzer/pull/9550[multiple proc-macro ABIs], a finicky topic. Rust's proc-macro ABI is highly unstable and evolving constantly, and whenever it changes it breaks our proc-macro server, degrading user experience. To counteract this we now try to at least support ~3 ABI versions which usually are latest stable, beta and nightly. In practice, though, we support much older versions. |
| 23 | + |
| 24 | +Finally, declarative macros also saw some love. We switched to an https://github.com/rust-analyzer/rust-analyzer/pull/7513[NFA parser] which brings us closer to how rustc handles them, added basic support for https://github.com/rust-analyzer/rust-analyzer/pull/8212[macro 2.0] and https://github.com/rust-analyzer/rust-analyzer/pull/8462[type position macros]. |
| 25 | + |
| 26 | +== Local Item Resolution |
| 27 | + |
| 28 | +Rust offers the ability to define new items inside of functions, consts and statics, making them effectively unnamable outside of these items. This is an idiom seldom used but still useful at times. Unfortunately, this is another piece of the language that is tricky to support, as an IDE wants to be lazy and only look at the big picture to understand a file's structure. Local items require us to look inside of the bodies of functions and the like unfortunately, as such doing this in an efficient but still lazy way took some work: |
| 29 | +https://github.com/rust-analyzer/rust-analyzer/pull/7336[#7336], https://github.com/rust-analyzer/rust-analyzer/pull/7359[#7359], https://github.com/rust-analyzer/rust-analyzer/pull/7366[#7366], https://github.com/rust-analyzer/rust-analyzer/pull/7375[#7375], https://github.com/rust-analyzer/rust-analyzer/pull/7426[#7426], https://github.com/rust-analyzer/rust-analyzer/pull/7431[#7431], https://github.com/rust-analyzer/rust-analyzer/pull/7466[#7466], https://github.com/rust-analyzer/rust-analyzer/pull/7480[#7480], https://github.com/rust-analyzer/rust-analyzer/pull/7481[#7481], https://github.com/rust-analyzer/rust-analyzer/pull/7482[#7482], https://github.com/rust-analyzer/rust-analyzer/pull/7485[#7485], https://github.com/rust-analyzer/rust-analyzer/pull/7518[#7518], https://github.com/rust-analyzer/rust-analyzer/pull/7525[#7525], https://github.com/rust-analyzer/rust-analyzer/pull/7541[#7541], https://github.com/rust-analyzer/rust-analyzer/pull/7544[#7544], https://github.com/rust-analyzer/rust-analyzer/pull/7554[#7554], https://github.com/rust-analyzer/rust-analyzer/pull/7555[#7555], https://github.com/rust-analyzer/rust-analyzer/pull/7557[#7557], https://github.com/rust-analyzer/rust-analyzer/pull/7559[#7559], https://github.com/rust-analyzer/rust-analyzer/pull/7561[#7561], https://github.com/rust-analyzer/rust-analyzer/pull/7568[#7568], https://github.com/rust-analyzer/rust-analyzer/pull/7575[#7575], https://github.com/rust-analyzer/rust-analyzer/pull/7627[#7627], https://github.com/rust-analyzer/rust-analyzer/pull/9244[#9244] |
| 30 | +With the final piece enabling it all landing in https://github.com/rust-analyzer/rust-analyzer/pull/7614[#7614] |
| 31 | + |
| 32 | +== Chalk integration |
| 33 | + |
| 34 | +We managed to fully switch our type representation to https://github.com/rust-lang/chalk[chalk]'s reducing the need of transforming between ours and `chalk`'s representation of types in order to run the trait solving. |
| 35 | + |
| 36 | +This work was done over a bunch of different PR's |
| 37 | +https://github.com/rust-analyzer/rust-analyzer/pull/7804[#7804], https://github.com/rust-analyzer/rust-analyzer/pull/7813[#7813], https://github.com/rust-analyzer/rust-analyzer/pull/7814[#7814], https://github.com/rust-analyzer/rust-analyzer/pull/7816[#7816], https://github.com/rust-analyzer/rust-analyzer/pull/7823[#7823], https://github.com/rust-analyzer/rust-analyzer/pull/7826[#7826], https://github.com/rust-analyzer/rust-analyzer/pull/7833[#7833], https://github.com/rust-analyzer/rust-analyzer/pull/7870[#7870], https://github.com/rust-analyzer/rust-analyzer/pull/8016[#8016], https://github.com/rust-analyzer/rust-analyzer/pull/7998[#7998], https://github.com/rust-analyzer/rust-analyzer/pull/8001[#8001], https://github.com/rust-analyzer/rust-analyzer/pull/8018[#8018], https://github.com/rust-analyzer/rust-analyzer/pull/8038[#8038], https://github.com/rust-analyzer/rust-analyzer/pull/8136[#8136], https://github.com/rust-analyzer/rust-analyzer/pull/8190[#8190], https://github.com/rust-analyzer/rust-analyzer/pull/8139[#8139], https://github.com/rust-analyzer/rust-analyzer/pull/8309[#8309], https://github.com/rust-analyzer/rust-analyzer/pull/8327[#8327], https://github.com/rust-analyzer/rust-analyzer/pull/8856[#8856], https://github.com/rust-analyzer/rust-analyzer/pull/8921[#8921], https://github.com/rust-analyzer/rust-analyzer/pull/8938[#8938], https://github.com/rust-analyzer/rust-analyzer/pull/8856[#8856] |
| 38 | +until we were finally able to fully move over in https://github.com/rust-analyzer/rust-analyzer/pull/8419[#8419] |
| 39 | + |
| 40 | +== Const Generic Params |
| 41 | + |
| 42 | +We started working on basic const generics support, tracking issue https://github.com/rust-analyzer/rust-analyzer/issues/8655[#8655]. This is one of the major pieces left for us to properly support and unfortunately also one of the more difficult ones. This problem becomes more apparent now that a lot of libraries are switching over to using const generics(a notable example being nalgebra which r-a is completely confused by). |
| 43 | + |
| 44 | +For an ideal experience we would need to be able to evaluate expressions in const generic position like rustc does, unlike rustc though, we are unable to use https://github.com/rust-lang/miri/[`miri`] for this. The reason being that we do not share the internal data structures that the compiler and miri make use of, neither do we plan to do so in the future. So we are required to build our own basic evaluator. |
| 45 | + |
| 46 | +This isn't the only problem we have though. As it currently stands, the majority of rust-analyzer's type checking codebase doesn't even know about const generics(or lifetimes), it just assumes type parameters are the only generics that exist. |
| 47 | + |
| 48 | +== Mutable Immutable Syntax Trees |
| 49 | + |
| 50 | +https://github.com/rust-analyzer/rowan[Rowan], our concrete syntax tree crate has been adjusted to allow creating mutable copies of the immutable syntax trees. For more in-depth information behind this checkout the https://github.com/rust-analyzer/rust-analyzer/issues/6857[issue]. |
| 51 | + |
| 52 | +But in short, the main thought behind this was that assists like to take existing syntax in a file, modify it slightly and paste back this modification changing only a few parts of the source. The way most assists did this before was by reconstructing the output syntax trees out of the original tree nodes with the changes inserted or left out. This is unfortunately a tedious process depending on the type of syntax node that has to be edited. These mutable immutable trees now allow us to instead mutably clone a tree, modify it in-place and paste this modified tree back as is. |
| 53 | + |
| 54 | +This does not come without its own problems of course, with the main troublemaker being that iterating while mutating, which is now possible, being an unwise idea as one can imagine(it'll usually result in a panic or incorrect tree layout). |
| 55 | + |
| 56 | +== The Code extension and server downloads |
| 57 | + |
| 58 | +The final releases of the year brought two important changes to the way the language server binary is acquired. Until now, the extension called the GitHub API to find a matching release, and downloaded the server from there. In addition, if you opted in to the nightly channel, every day the extension would search for an updated VSIX. |
| 59 | + |
| 60 | +While this suited us well for a long time, it had some downsides: |
| 61 | + |
| 62 | + - edge cases like MITM HTTPS proxies with untrusted certificates weren't working |
| 63 | + - not being able to replace running executable on Windows (in case you had two running instances) has been a major source of complaints |
| 64 | + - Code checks for extension updates automatically, but the server was downloaded on activation. Many users had an unpleasant surprise when opening a Rust project without a working Internet connection. |
| 65 | + - GitHub Actions has been increasingly unreliable lately causing the nightly builds to fail very often. This broke the extension for users running the nightlies. |
| 66 | + - the download and update code brought a lot of non-essential complexity and even exposed a Node.js bug |
| 67 | + - the required client-side dependencies increased the surface for supply chain attacks |
| 68 | + |
| 69 | +So when the Marketplace added support for platform-specific and pre-release extensions, we starting using it with https://github.com/rust-analyzer/rust-analyzer/pull/11053[#11053], https://github.com/rust-analyzer/rust-analyzer/pull/11071[#11071] and https://github.com/rust-analyzer/rust-analyzer/pull/11071[#11106]. We also https://github.com/rust-analyzer/rust-analyzer/pull/10903[replaced] the client-side unit testing framework with a bit of custom code, dropping our transitive dependencies by the dozens. |
| 70 | + |
| 71 | +Unfortunately, the update changes exposed some issues with both the Code Marketplace and Open VSX (used by open-source builds of Code). This is discussed in detail https://rust-analyzer.github.io/thisweek/2021/12/27/changelog-109.html#known-issues[here], the gist being that you might need to take manual action when installing or updating the extension. The two issues have been reported upstream, so we hope they will be fixed soon. |
| 72 | + |
| 73 | + |
| 74 | +== General IDE Experience Improvements |
| 75 | + |
| 76 | +We now support standalone rust files(https://github.com/rust-analyzer/rust-analyzer/pull/8955[#8955]), so just opening a single file should allow you to use most of rust-analyzer's functionality that is not relient on cargo. |
| 77 | + |
| 78 | +We also improved and added a bunch of smaller features, some noteworthy ones are |
| 79 | + |
| 80 | +- https://github.com/rust-analyzer/rust-analyzer/pull/7297[Flyimport Completions for Trait Associated Items] |
| 81 | +- https://github.com/rust-analyzer/rust-analyzer/pull/10458[Custom User Snippet Completions] |
| 82 | +- https://github.com/rust-analyzer/rust-analyzer/pull/7335[Region Folding] |
| 83 | +- https://github.com/rust-analyzer/rust-analyzer/pull/7799[Related Test Peeking] |
| 84 | +- https://github.com/rust-analyzer/rust-analyzer/pull/8054[Move Item Command] |
| 85 | +- https://github.com/rust-analyzer/rust-analyzer/pull/8801[Crate Graph View] |
| 86 | +- https://github.com/rust-analyzer/rust-analyzer/pull/8873[Import Granularity Guessing] |
| 87 | +- Highlight https://github.com/rust-analyzer/rust-analyzer/pull/9375[Function Exit and Yield Points] and https://github.com/rust-analyzer/rust-analyzer/pull/9396[Loop Break Points] |
| 88 | +- https://github.com/rust-analyzer/rust-analyzer/pull/8774[Respect `.cargo/config.toml`] |
| 89 | + |
| 90 | +An impressive ~37 new assists have been implemented, some by the main contributors, but most by newcomers: |
| 91 | + |
| 92 | +- https://github.com/rust-analyzer/rust-analyzer/pull/7310[Add Lifetime to Type] |
| 93 | +- https://github.com/rust-analyzer/rust-analyzer/pull/7824[Add Type Ascription] |
| 94 | +- https://github.com/rust-analyzer/pull/10362[Convert `a/mod.rs` into `a.rs`] |
| 95 | +- https://github.com/rust-analyzer/pull/9837[Convert `bool::then` to `if`] |
| 96 | +- https://github.com/rust-analyzer/rust-analyzer/pull/7741[Convert `for` Loop to `Iterator::for_each`] |
| 97 | +- https://github.com/rust-analyzer/pull/9816[Convert `if` to `bool::then`] |
| 98 | +- https://github.com/rust-analyzer/rust-analyzer/pull/8295[Convert `Into` Impl to `From` Impl] |
| 99 | +- https://github.com/rust-analyzer/rust-analyzer/pull/7956[Convert `Iterator::for_each` to `for` Loop] |
| 100 | +- https://github.com/rust-analyzer/rust-analyzer/pull/7777[Convert Between Line and Block Comments] |
| 101 | +- https://github.com/rust-analyzer/pull/10211[Convert File Module to Directory] |
| 102 | +- https://github.com/rust-analyzer/pull/10998[Convert Number Representation] |
| 103 | +- https://github.com/rust-analyzer/rust-analyzer/pull/8317[Convert Tuple Struct to Named Struct] |
| 104 | +- https://github.com/rust-analyzer/pull/9855[Destructure Pattern into Tuple Pattern] |
| 105 | +- https://github.com/rust-analyzer/rust-analyzer/pull/7130[Extract Assignment] |
| 106 | +- https://github.com/rust-analyzer/rust-analyzer/pull/7535[Extract Function] |
| 107 | +- https://github.com/rust-analyzer/pull/9939[Extract module] |
| 108 | +- https://github.com/rust-analyzer/rust-analyzer/pull/8210[Extract Type Alias] |
| 109 | +- https://github.com/rust-analyzer/rust-analyzer/pull/8037[Generate `fn is_empty`] |
| 110 | +- https://github.com/rust-analyzer/pull/10459[Generate Constant] |
| 111 | +- https://github.com/rust-analyzer/rust-analyzer/pull/7800[Generate Default Impl] |
| 112 | +- https://github.com/rust-analyzer/pull/10539[Generate Delegate Methods] |
| 113 | +- https://github.com/rust-analyzer/rust-analyzer/pull/8467[Generate Deref Impl] |
| 114 | +- https://github.com/rust-analyzer/pull/10951[Generate Documentation Templates] |
| 115 | +- https://github.com/rust-analyzer/rust-analyzer/pull/7677[Generate Enum Match 2] |
| 116 | +- https://github.com/rust-analyzer/rust-analyzer/pull/7562[Generate Enum Match] |
| 117 | +- https://github.com/rust-analyzer/rust-analyzer/pull/7617[Generate Getter and Setter] |
| 118 | +- https://github.com/rust-analyzer/pull/9804[Generate Method] |
| 119 | +- https://github.com/rust-analyzer/rust-analyzer/pull/7131[Inline Function] |
| 120 | +- https://github.com/rust-analyzer/pull/10352[Inline into Callers] |
| 121 | +- https://github.com/rust-analyzer/pull/10546[Promote Local to Const] |
| 122 | +- https://github.com/rust-analyzer/pull/10602[Qualify method call] |
| 123 | +- https://github.com/rust-analyzer/pull/10476[Replace `?` with `match`] |
| 124 | +- https://github.com/rust-analyzer/pull/10629[Replace Turbofish with Explicit Type] |
| 125 | +- https://github.com/rust-analyzer/rust-analyzer/pull/6809[Sort Impl Functions by Trait definition] |
| 126 | +- https://github.com/rust-analyzer/pull/9735[Sort Members Lexicographically] |
| 127 | +- https://github.com/rust-analyzer/rust-analyzer/pull/7289[Unmerge Use] |
| 128 | +- https://github.com/rust-analyzer/pull/10417[Unwrap `Result` Return Type] |
0 commit comments