 Hello? Perfect, okay, so audio works now. So, at the end, you get a 13. So, this is cool, const valiant works. Well, this is actually called const folding, but the difference is smooth. So, now we get to more complex stuff. Imagine you have a function, it has local variables, and it has some loops and stuff. So, how do you const fold that? Like, turn that into a tree and start collapsing it. Like, this is not really possible. This is code that you walk down from the top to the bottom and you execute each instruction after each other, like you would do at runtime. But this is not possible if you try to combine things. Like, you cannot combine a Y divides equals two, because what are you combining there? There's no two values to combine to something else. So, we were trying to look at something new, where we could do local variables, which are not possible in constants right now, where we can do mutation and where we can do loops. These are the things that we want to be able to do. Like, right now, you cannot do them at compile time. You just can do them at runtime, but even if there's an error in this program, you won't detect it at compile time. It'll panic at runtime. So, the REST compiler developers decided to do it right. They created a mirror, which is a structure that allows you to do the sequential constant evaluation instead of the folding. And then, somebody wrote something called miri, which is the mirror interpreter. Which allows you to evaluate mirror code. And if the mirror code contains solely constants, well, then you can just evaluate it to the end and look at the end result and then store the end result. And when you started doing it, they were looking at like integers and adding them and similar things like that. But at some point, they kind of got crazy and then we got pointers and pointer arithmetic and calling C functions and calling syscalls. And yeah, right now, we're not quite at reading files yet, but we can do print line and reading from sdn. So, if you just pipe your file into the sdn, you can read files. That's a little bit much for const evaluation, but, well, we will try to get there. So, last year, I added miri to RESTC as an experiment where we were running the old const evaluator next to the new one and comparing them. So, just to make sure, like, we're not introducing any weird stuff that we don't wanna have. Because right now, we just wanna get the new miri so we can get new features in the future, but we don't wanna break anybody's code. So, that was running, well, in December. It was a big pull request at RESTFest, which had like 1,600 commits. It has 7K lines of code added to the REST compiler, which is a lot. But you have to remember, this is something that's essentially a virtual machine running your REST code at compile time and producing a value that you can then compile down into your final binary. The next step was, well, removing the old const evaluator, which touched another 6,000 lines of code, but it didn't add anything new. Instead, it removed all the old crap that we had in there in the old compiler. And, well, now it's gone. The pull request isn't merged yet, but it's running right now. The REST compiler developers are merging it at the moment. It's basically already approved, just checking every single crate on crates.io whether we don't break it with the new compiler, because, well, we don't want to break anybody's code. So, let's go back to the bottom. What is MIR? MIR is called the Medium Intermediate Representation. What's that? Well, it's basically an assembler, an assembler language. But it's very close to how REST builds your code. So, you have types. You don't have any registers. You have local variables. And it's already used for a lot of things. Like, borrow checking is done completely on the MIR. So, that's where we're getting nonlinear lifetimes in the future from, from MIR and borrow checking on the MIR. Also, in the future, we might be able to do guaranteed optimizations like tail call optimization and so on on the MIR. Like, everything that's REST required will be done on the MIR. So, MIR looks a little bit like that. It's like a big text blob that you can't really read. It's essentially, if you read all the small steps in there, it looks like REST code, but there's go-to's in there. Like, a lot of go-to's. And you don't want to read code with go-to's. So, instead, you can convert it into a graphical representation. So, this is exactly the same code. This and this is the same thing. The only difference is all the local variables declared on top are turned into virtual stack. And all the blocks in there with go-to's are turned into a graph with arrows between them. So, you can actually read your code. And this is actually a tool that you can use to step through your constant code to check, like, what it's doing. What is the virtual memory of MIR doing? Well, what's going on? And, yeah. So, MIR is a MIR interpreter. So, you can execute all the code. It has no undefined behavior. You can do pointer arithmetics. You can do whatever you want. And if you try to do undefined behavior, compiler will simply tell you, well, you try to do undefined behavior here. Please don't do that. So, it will give you an error message that, like, it looks like a rust compiler error message. It just tells you, at this line of code, you're doing undefined behavior. Stop and try again. And this works for a lot of things. Like, please try to break MIR. It's really hard. Like, there's a few things that we know about. Like, you can actually mutate non-mutable variables. But that's basically by the definition. A mutable variable is just a lint telling you, you are allowed to mutate it, but whether, like, the background memory is mutable, that's completely allowed to modify it, actually. There's no, nothing restricting you from modifying immutable variable, yeah. So, I already told you, MIR, the tool, it can do a lot of stuff, like read from a command line or do some syscalls, some easier ones. But, well, we don't want all of that in compiler. So, what we're doing right now is we're separating MIRi, the tool, and MIRi, the const evaluator. And the const evaluator does everything you expect from a const evaluator. It computes your pluses, your multiplications, it calls functions and so on. But it doesn't do print line. It doesn't do syscalls because syscalls during const evaluation, that's just weird. But we might do it in the future, but we'll need RFCs for that because we don't just randomly want to enable random features that maybe are bad. So, but what you can do instead with MIRi, the tool is, well, you have a test suite and you're kind of getting undefined behavior somewhere, you don't know where. So, you just run Kygo MIRi instead of Kygo test, and it'll run all your tests with MIRi through the const evaluator. So, if you do any undefined behavior, it'll just stop and tell you, this test at this line of code is doing undefined behavior. And to top off on that, it'll print a stack trace. Like if you're inside libstd in the vector function, push inside something whatever deep, it'll tell you a stack trace down to where you're doing undefined behavior. It's not like GDB, which crashes at some point when you're at an actual error, it stops you right when you're doing undefined behavior, like right before it. And then you can even look at the memory and say, okay, well, how does it look? Well, where am I right now? And then you can find out how your code is doing undefined behavior. So, this is the tool. Side effects of using all of this and const evaluation is, you can start doing heap allocation in constants. Well, you can't, we disabled it, but we will be able to do that in the future. So, you can do strings, you can do certain decoding of JSON files at compile time, convert that into a structure, store that structure in static memory, and then you have your configuration already parsed, already checked for errors, everything at compile time in memory. You can just say, okay, well, what's the setting and you get the setting. You don't need to check anything. You don't need to even have the file present. And you have like a big configuration file, like in JSON or XML, these might take megabytes or something, convert them down to binaries, down to kilobytes or even less. So, you save all the computation time at compile time, you save all the memory and you even get error checking at compile time. So, yeah, these are side effects. There's still some things that we need to do in the future. For example, there's some very complex things when people start using associated types and associated constants. Like, technically these things are all right, but Miri will just say, sorry, this is too complex for me. The old console values had the same thing, so we're not losing any features here. But the thing is with Miri, we can actually start doing these things. Like, we can think about how are we gonna do this? We have a structured way to approach this. For example, think about you have an array and the length of the array depends on a trade implementation for this array that you don't know the length of. So, you need to look at the trade implementation, but to get at the trade implementation, you need to have to type for which you need the length, for which you need the trade implementation. Yeah, you're gonna end in a cycle. So, but maybe that value you need for the length is completely independent of the length that you need, so there's no cycle. It's just an information attached to the array in general. And to do these things, that's called partial evaluation because you don't know everything, but you know enough to compute the value. And this is the big thing that we're gonna be working on this year, but it's gonna take time. And yeah. One other big thing that we're working on allowing, for example, GDB to run a Rust code with Miri on actual physical memory. So, instead of trying to actually execute real code, you're gonna run the things on your actual memory, but with the Miri debugger checking the code for things like undefined behavior and so on in your debugger. So, you can run GDB and you execute a small command, it got compiled, it'll get run by Miri and it'll tell you some results that you usually could not get because this kind of complex evaluation just isn't possible in GDB. Also, one feature that we wanna have, if you compile your code and you have a constant evaluation error, well, compiler could stop at that point and offer your debugging window telling you exactly what went wrong. Like, you usually get a stack trace that tells you, okay, it went wrong here and there and there and there, but you don't know any values, you don't know how the memory looks, maybe you did some weird pointers things in your constants, you don't know exactly what's going on. So, the next step is to allow you to call your compiler and then just stop when something goes wrong and inspect what exactly is going on. So, these are the things that we are working on, but what's even better for you is you can help too and you can write RFCs because we have a lot of features that are basically just error, needs RFC, format some texts about what kind of RFC we need. This is literally just a check. If something is not allowed, report this error and below is the code that would execute if it were allowed. So, the code is there. Like, we just need RFCs, you need to write a text and that explains how this affects other things, but you need to write it from a user perspective. You don't need to care about the implementation. The implementation is there. You just need to write how you wanted this feature to work and we can just turn it on. So, yeah, please do that. We need RFCs and we don't have enough people annoying the other REST compiler developers to actually enable the features. If the feature is required by enough people, we're probably gonna get it pretty quickly. Yeah, one other thing you can do, you can go to the REST compiler and look through the documentation and think this function doesn't do anything weird. It doesn't do anything that depends on runtime values, no randomization and so on. It could be a constant function. This function could be evaluated at compile time. So, all you need to do is open and pull requests to the REST compiler, writing const in front of DFN and you're already helping us because you found a function that we could make const. There's a pull request, you're talking with the REST compiler developers about it and we're gonna turn it into a constant and then it works. It's now a constant function. These things are really easy to do but somebody needs to do them and we are already trying to do hard things. So, it would be really cool if you guys would help us there and yeah, make the REST compiler even more awesome than it already is. Thanks. So, does anybody have any questions? Yes. Okay, the question is if we can automate the process from finding functions that could be constant and making these suggestions automatic? We probably can. I have no idea why I've never thought about that. I'm developing Clippy like every few weeks. Yeah, that's a really good question. We should totally do that. It won't work for everything. It's really hard to detect if something is const-valuable. If it were easy, we'd just do it automatic and you wouldn't need to annotate anything but they're just basically the halting problem. Like, sometimes to check whether a function is const-valuable, you probably need infinite computation time to figure it out so that might not quite work out. But for the easy things, we can definitely do that. Yes. Changing functions to const, changing declaration wouldn't break the API? The question is whether adding const to a const-fan, to a function, so making it a const-fan would be a breaking change. No, it will never be a breaking change to move from fn to const-fan. That's impossible to be breaking change by itself. What would be a breaking change is going the other way from const-fan to fn. This means you need to think about whether this function would ever in the future of rust do something that could be not constant. For example, access random number generators or do something other like actually the current time or so on. If it would ever do that in the future, then you cannot turn it from fn to const-fan right now. This is something that wouldn't be automatically checkable because it's just semantics of the function. Okay, I am prepared for this question because Pascal already asked me this question. So sufficiently advanced incremental compilation is indistinguishable from a REPL. So the REST compiler dev, they're doing incremental compilation things. We might have heard about those. This is to speed up compilation. So instead of having to recompile for adding a small variable or anything, the compiler just recompiles the parts that you changed. If you get this incremental compilation good enough, at some point, you won't care if there's no REPL because you'll just be weak. The REPL will be just a wrapper around the rust compiler that just adds new stuff to a file and then reruns the rust compiler and the const evaluation memorizes with incremental compilation the values from the previous compilation. So this will be a bash script with like three lines. Yes? The question is since immutability is the default for locals and so on, would it be better if rust started in you to make everything default const-fan and then have a flag for making it not const-fan? I personally would think that would be the correct solution. We had an RFC about that where there was a big discussion about it and at some point we just realized, well, switching around would be a breaking change. It's questionable, like you can't really test it. Like with immutability and immutability, it's easy. Just look at big code bases and look how it's done there. But with const-fan, the problem is there's not much previous experience about that. We have other languages that do best effort const-evaluation where, for example, in Lisp, where you just throw random statements in there and they're gonna get evaluated if they are evaluable. And here we try to do it upfront by deciding whether it's const-evaluable or not. It's a really hard decision and it would probably be better to do the other way around but that might just lead to people randomly throwing not const on it. So right now we're just opting for the lint option that tells you when to make it const-fan and then you're done with it.