 Thanks for being here. I realize there's another talk going on in the other room here, so thanks. My name's Emma. I am doing the Google Summer of Code project. That is this one. Alright, so a couple of words about me. I am a student at Imperial College London. I am going into my third year now. I've been programming for about 10 years now. I have a lot of different interests in all different fields of computer science like AI and computer vision. And lately I've been more and more interested in stuff like operating systems, type systems, stuff like that. I did an internship at Microsoft Research last summer doing some computer vision stuff. And I've also done some hacking on KD stuff and a bunch of other cool projects like doing a bare metal arm sending club of Mario Kart. So I want to start with a couple words about Rust because Rust is an amazing language. I think that Rust is a really great language because it sort of learns from a lot of the mistakes that other programming languages like C++ made. And it sort of tries to take the best elements of those languages. But it also gives the sort of low level access to a lot of the low level elements and the performance benefits that come from that. So to quote Bjarne Strauss-Straub, I hope I don't waggle the name. C makes it easy to shoot yourself in the foot. C++ makes it harder, but when you do it it blows your whole leg off. So in Rust you can still blow your whole leg off if that's your thing. But the compiler is there to sort of very, very politely encourage you not to. So I want to give a few examples of Rust so it's quite similar to C++ really. You probably can't see the code at the back but it hopefully looks somewhat familiar. There's all the standard imperative style, imperative language features. You have the struct, synoms, functions, methods, etc. But Rust adds a couple more interesting features. For example, lifetimes. So lifetimes, they're not really a new idea. A lifetime of variable is essentially, it starts from the moment when that variable is created and ends when the variable is destroyed. But Rust takes that idea one step further and adds some features in the compiler that help you make sure that you don't use variables that are no longer live. So for example, if you have a scoped log of a given new text, in C++ the way you do that is you acquire the log in the constructor, you drop the log in the constructor, everything's great, if the new text somehow gets destroyed while you're holding the log, you get to spend a few hours debugging. In Rust that can't happen because any reference to a value must be tagged with a lifetime and that lifetime basically allows the compiler to verify that that reference outlives, or the value that the reference points to outlives the reference itself. And these kinds of checks help you, the compiler helps you basically, it stops you from making a lot of errors that occur with dangling pointers and references in the C and C++. Rust also has traits, traits in Rust are essentially concepts in C++, if and when concepts finally make it into the language standard, essentially they give you static polymorphism without having to scroll through hundreds of lines of error messages that go forever, doesn't satisfy some requirement. Rust also has, Rust synoms are algebraic data types, if you've done Haskell or another functional program languages, algebraic data types are essentially tagged unions, so a variable of this type can only hold one of the given variants and it must hold all the data that is needed to construct that variant. And finally patterns, patterns are a cool feature that essentially lets you destructure certain types of values, so for example if you know that a function returns a tuple, you can extract the different elements of the tuple and bind them to variables, or alternatively you can have conditional bindings, so a piece of code that only executes if some pattern matches, so for example A is an optional type, it can either contain some value X or no value at all, so you can match on that pattern and say if it contains some variable called V, then do something else and there's also the match statement which is similar to this. Rust has a static and strongly typed type system, it does allow for local type inference, meaning type inference within function bodies, which saves a lot of typing in a lot of repetitive typing in a lot of places, it has the concept of owned and borrowed values, so these are essentially values on the stack and references in C++, with some additional compile time checks to make sure that these values stay alive for as long as they have to, and it does some other safety mechanisms to make sure that, for example, values that cannot be used by two threads simultaneously don't get used by two or more threads, essentially, for example, things like the mutex can be passed around between threads, but any random variable or reference cannot be passed, because all sorts of other bugs can happen with that. So, right, let's get on to what I've been working on. So, I've been working on the Rust support plugin for the past month and a half now. Initially, there was the idea to use the Rust language server, which is developed by the Rust community. It's actually being developed, but it's still quite early stages, and it's based on the language server protocol, which is developed by Microsoft for, I think originally for Visual Studio Code, but they open sourced it and made it sort of a community effort. The language server protocol is great for editors, lightweight editors, like Cake and Visual Studio Code, but in my opinion it's not really good for something like KDevelop, because it doesn't really expose enough information to build KDevelop's internal structures. When I first wrote about this in a blog post, that sparked quite a bit of discussion with the Rust community, and the things I pointed out were that in KDevelop, for example, a lot of features such as highlighting and renaming declarations are done automatically by the KDevelop platform, as long as you can build the internal structures, that is the declaration news chain. The thing is, the Rust language server doesn't really provide the information necessary to build those internal structures, so essentially, yeah, you wouldn't have to parse the language and know anything about the language, but then you would need to implement all of these different parts of KDevelop that highlight the code and give you completions and so on and so forth based on the language server protocol client. So, in the end, I decided to guest it and decided to do the language plug-in standard way. The thing is, Rust is a nightmare to parse. Now, C++ is a nightmare to parse, but Rust is pretty much just as bad. So, what I did was use the compiler's parsing library because it's a compiler, it's always going to be up to date. The thing is the compiler is written in Rust. So, what I had to do was, I wrote a library in Rust and Rust has a pretty good FFI interface to see. We basically specify that the functions are external C linkage and disable name-mangling and everything just works. X goes in API to C to allow traversing the abstract syntax tree that I get from the compiler. This is sort of similar approach to what Lips, C-Lang and C5 on ASD library do. These are also the things used for the C++ and Python plug-ins in K-Develop, respectively. Essentially, what I did was expose the CAPI, I call to it from the K-Develop source code and that basically lets me gather all the declarations and uses and do some magic and voila, syntax highlighted automatically. So, that was cool, that was quite cool, that was fun to do. Right now, I'm working on code completion and that's also quite interesting because for a lot of things in code completion, you need to know about types. As I mentioned earlier, Rust has local type inference within function bodies, so that requires type inference. The problem is in the Rust compiler that happens after the parsing stage. I think after in between the high-level to mid-level representation transform. So, it's not really feasible to use that. So, right now, amazing. It is actually quite fun. Type inference is quite a cool problem. Rust has a really cool type system that allows doing type inference. It's based on the Hindley-Miller algorithm so that is quite fun implementing. So, code completion at the moment works for local declarations so you can autocomplete a variable declared in the local scope or in the closing scope. I'm currently working on getting it to run for imported libraries. So, I've been able to successfully parse the Rust standard library and the Rust core library. These are quite huge after macro expansion so that was quite cool. And afterwards, like once this works, then basically applying the same method should work for any other library as well. And Rust's package manager, which I'll talk about in a sec as well. It basically builds everything. So, any dependent library downloads them and builds them and it exposes metadata about where they're stored. So, essentially, I can just look at the source code for those and it should work just the same as with the standard libraries and Rust. I'm also working on re-bactoring at the moment. Like I said, renaming declarations is one of the things that KDevelop provides out of the box once you have the declaration use chain. So, that's done, that works. Quick fixes are something I'd like to do and something I'm working into. So, the Rust compiler has really, really good error messages. It gives you suggestions about, for example, missing imports or different sorts of type errors that tells you, oh, did you mean this? So, I'm looking into parsing those and trying to expose them as quick fixes within KDevelop. I'm also looking into auto-generating stuff like trade implementations and pattern matches and basically anything that the ID can write for you is always nice. Debugging. Debugging should hopefully be quite straightforward. Rust uses GDB and LLDB. Both of those are already supported in KDevelop. The only thing that's needed is to integrate with Rust. To integrate that with Rust executables. And I say this because as I've been debugging KDevelop, like I said, I wrote Rust lively as well. So, any time that I've been debugging with GDB and the code crosses over into Rust code, there's no problem at all. The call stack is visible, all the variables like all the locals and stuff like that are visible. It works perfectly well. So, I'm hoping that the same should be just as easily applied in KDevelop as well. And finally, project management. So, cargo is great, as I said. It provides metadata for different dependencies like where they're located, what other things they depend on, et cetera, et cetera. And Rust projects in general have very consistent structures. So, for example, the default path for an executable like the main file of an executable is SRC main. And, respectively, for a library is source lib. It has this very consistent structure, which of course can be overwritten in cargo. But the default structure is very nice and it would allow very... It would make it easy basically to parse everything and know where things are and stuff like that. So, to recap, Rust is an amazing language. You should definitely check it out. I've been blogging about all of my work, so you should follow me on my blog if you'd like to follow my work. And the code of the Rust plugin is available online. It's in the KDE repositories. So, if you'd like to try it out, please do. It's a bit of a hassle to build at the moment, but I promise that I'll improve in the next month or so. So, yeah, all right. We have a couple of minutes for some questions. Hang on.