Open BenjaminBrienen opened 11 months ago
Hello,
I haven't personally used Rust but it would be a neat language to fully support given its popularity. The highlighting depends on what VSCode offers for any given language so when adding support for a language I generally start with checking out the most popular or advanced LSP extension that developers would have installed for it.
For rust that seems to be the semantic highlighting of Rust Analyzer. This is in fact one of the more comprehensive semantic highlighters I've come across, and I'm already seeing both new tokens (such as struct, trait, lifetime) and modifiers (such as consuming, callable, reference) that are not yet part of the Semantic Rainbow Specification.
The main part is just figuring out how to situate those tokens within the theme's design philosophy and that's where, having no rust experience, I'd be grateful for help.
Helpful things to know would be:
...And so on.
Hi.
I recently started using your theme and I like its approach of maximal use of semantic information. Here are some specific observations about Rust and how some of its concepts can fit into this theme's design philosophy. This is probably not a complete list and I could be missing things.
struct
s are Rust's way of storing state. There are no classes in Rust, so a simple alias would suffice.trait
s are essentially interfaces. They are a group of functions and methods that can be implemented by another type and then the trait can be used generically.let
bindings, function parameters, etc.) are immutable by default and must be declared as mut
to be mutated. Mutable items get a mutable
modifier. This inverts the readonly distinction that the theme uses.pub(crate)
(usable only in the current crate, Rust's version of a package, basically) or pub
. This inverts the theme's privacy distinction, as well as adding a second level.const
variables are read-only and calculated at compile-time. There are also const
functions and methods, which can be used to initialize const
variables and have restrictions on what they can do so they can be run at compile-time. It would be nice to highlight these differently from other functions and methods.static
variables are non-constant variables with specifically 'static
lifetime. They are valid for the entire lifetime of the running program. They can technically be modified (you can have mut static
) but this requires the use of unsafe
and is also not thread-safe and is practically never done. So static
variables are almost always read-only.derive
token that is used for the derive
attribute, which allows automatic implementation of some traits. Maybe these should be highlighted like traits?selfKeyword
token that should get the "self parameter" highlighting.Methods have a three-way (technically four-way) distinction in how they access self
that should be highlighted.
consuming
: Method takes self
by value and moves it out of the calling function. The value cannot be used after that point. This also includes methods which take mut self
.reference
: Method takes self by reference &self
. Self cannot be mutated and is not consumed.mutable.reference
: Method takes self by mutable reference &mut self
. The value that this method is called with must be mutable with let mut
or another form of mutable binding.The value - reference - mutable reference distinction also applies to parameters.
Lifetime parameters should be highlighted differently from type parameters. To give a quick explanation, if you want to store a reference to borrowed data, that reference must be marked with a lifetime.
struct Example<'a> {
p: &'a i32
}
struct Example
holds a reference to an i32
. The lifetime 'a
means that an instance of Example
can not live longer than the lifetime 'a
of the owner of the i32
, otherwise the reference would become invalid. So something like this is illegal:
fn bad() -> &i32 {
let x = 0;
&x // x is dropped at the end of the function; this reference is invalid
}
They are essentially a generic type parameter that controls where and how object may be used in the flow of the program. A borrower can never outlive the owner of its data and lifetimes are what enforces this.
One final thing that I'm not sure about is how the theme can highlight scopes. Rust has an unsafe
feature that enables you to do things like access raw pointers or do FFI with C which could potentially cause memory errors that the compiler cannot prevent. Use of unsafe
can be a bit of a contentious issue and lots of crates advertise their performance with no use of unsafe. I think it would be a good idea and in the spirit of the theme to highlight these blocks somehow, even if it's just the unsafe keyword. Highlighting the entire block with a separate background may not be possible.
Thanks for the input, I can definitely work with that, although some of the stuff sure seems challenging. Scope highlighting is not something that semantic tokens are good at because well, it's really about individual tokens. But perhaps the Textmate grammar recognizes unsafe scopes that would also make them styleable.
I guess I'll see when I check out some more Rust code.
Couldn't find a better place to add a feature request or gauge interest...
I know the readme suggests adding support for more language-specific features. I'm simply here to ask whether rust is of particular interest to this project, be it implemented by the current maintainer or a new maintainer such as myself. If supporting Rust is something that you are particularly interested in, then I'm interested in having a discussion about which language features should be considered for semantic coloring, the feasibility of each, and related topics.