How do I interpret or otherwise evaluate Rust at runtime? - rust

I've been searching, and while this seems to be a much-wanted feature, all search results seem to be at least one year old.
What is the current state of this? Is there a good solution to evaluating arbitrary Rust code at runtime (like Haskell's hint)?
Maybe something can be done with Miri?

Miri (short for MIR Interpreter) is the de-facto interpreter of Rust code. It is what powers the compile-time function evaluation inside of rustc, the Rust compiler, but Miri is more featureful than what is currently used by compiler.
For experimentation purposes, Miri is also available in the Rust playground. It can be used to evaluate a particular run of a program, detecting if certain types of undefined behavior exist.
Miri does not provide a Rust REPL, but it may be part of creating such a tool.

Related

Is there any way to view the Debug representation of a Rust variable in the LLDB debugger?

Rust code can be debugged using LLDB. The representation of variables used by tools like CodeLLDB, though, is simply a breakdown of the in-memory contents of the variable and does not show any information from the standard Debug trait.
Is there any way using LLDB I can invoke the actual Debug representation of a variable at runtime? This often has a significant amount of useful information which is not clear from a simple memory snapshot.
The "Debug" trait in Rust looks like a pretty close equivalent to the ObjC and Swift object description methods: it provides a to-string method that prints a developer-friendly view of the object. From what I can tell this trait cooperates with the standard formatted printing machinery in Rust.
If that's right, the natural way to give access to the Rust Debug Trait in lldb would be to implement the "Object Description" part of lldb's "Rust LanguageRuntime" and call the print function under the covers. This would be accessed by the po or print-object command in lldb.
Unfortunately, Rust doesn't have a "Rust LanguageRuntime" in lldb or really much of any support currently. The only mentions of Rust in the lldb sources are a recognizer for the Rust mangling scheme and a define that says "other than mangling, pretend Rust is C++". So that isn't a viable option at present.
You could also try calling Rust's print directly in the expression evaluator, but YMMV as calling Rust code in lldb doesn't always work: as it turns out, Rust is not C++...

Why are ceilf32 and sqrtf32 unsafe?

I'm pretty new to Rust and have been working on some mathematical problems. For one of these problems I needed ceilf32 and sqrtf32. I was surprised to find that these functions are unsafe; both are fairly simple mathematical functions and my understanding is that unsafe Rust is used only as necessary to work around either the conservatism of the compiler or to allow inherently unsafe OS operations. I can't see any reason either function would run into either issue, thus I can't understand what would stop them being implemented with memory safety.
Could someone please enlighten me?
The functions you're looking at are in core::intrinsics, which are low-level compiler instructions. I don't see any official documentation on why they're marked unsafe, but my guess is that all of the compiler intrinsics were marked that way as a rule, since they're lower-level than most of Rust proper.
Regardless, for normal operation, you're looking for the inherent methods f32::ceil and f32::sqrt. These are the Rust standard library implementations that presumably[1] call the intrinsics as a course of action, and these methods are not marked unsafe.
Since they're inherent methods, you can either call them on f32 objects (my_number.sqrt()) or directly with the namespace (f32::sqrt(my_number)).
[1] In fact, a look at the source code for the current implementations indicates that both of these simply delegate to their intrinsic counterpart, wrapping it in an unsafe block to guarantee safety.

How exactly is Rust programming language implemented?

If you check languages percentage in github rust lang compiler repository it says that 97.6% of the rust lang compiler is written in rust. So how does this exactly works?. How you can create a programming language (I think this is related to a compiler, since it's whom read the code, doesn't it?) written in itself.
This is called self-hosting or bootstrapping. The basic idea goes like this:
Write an initial compiler for a small subset of Rust using your Other Programming Language of Choice. You now have compiler C0.
Using the subset of Rust you have a compiler for, rewrite the source for C0 purely in Rust. Compile that program using compiler C0 to form compiler C1.
Add features to Rust by adding code to the compiler you just wrote to properly parse and implement those features. Compile that Rust program with C1 to form compiler C2.
By repeating step (3) as many times as you’d like, you can add progressively more and more features to the Rust language, with the Rust compiler always being written in Rust itself.
There’s a famous talk called Reflections on Trusting Trust that talks about how this process works, as well as how you can use this process to do Nefarious Things.

Can Rust code compile without the standard library?

I'm currently in the progress of learning Rust. I'm mainly using The Rust Programming Language book and this nice reference which relates Rust features/syntax to C++ equivalents.
I'm having a hard time understanding where the core language stops and the standard library starts. I've encountered a lot of operators and/or traits which seems to have a special relationship with the compiler. For example, Rust has a trait (which from what I understand is like an interface) called Deref which let's a type implementing it be de-referenced using the * operator:
fn main() {
let x = 5;
let y = Box::new(x);
assert_eq!(5, x);
assert_eq!(5, *y);
}
Another example is the ? operator, which seems to depend on the Result and Option types.
Can code that uses those operators can be compiled without the standard library? And if not, what parts of the Rust language are depending on the standard library? Is it even possible to compile any Rust code without it?
The Rust standard library is in fact separated into three distinct crates:
core, which is the glue between the language and the standard library. All types, traits and functions required by the language are found in this crate. This includes operator traits (found in core::ops), the Future trait (used by async fn), and compiler intrinsics. The core crate does not have any dependencies, so you can always use it.
alloc, which contains types and traits related to or requiring dynamic memory allocation. This includes dynamically allocated types such as Box<T>, Vec<T> and String.
std, which contains the whole standard library, including things from core and alloc but also things with further requirements, such as file system access, networking, etc.
If your environment does not provide the functionality required by the std crate, you can choose to compile without it. If your environment also does not provide dynamic memory allocation, you can choose to compile without the alloc crate as well. This option is useful for targets such as embedded systems or writing operating systems, where you usually won't have all of the things that the standard library usually requires.
You can use the #![no_std] attribute in the root of your crate to tell the compiler to compile without the standard library (only core). Many libraries also usually support "no-std" compilation (e.g. base64 and futures), where functionality may be restricted but it will work when compiling without the std crate.
DISCLAIMER: This is likely not the answer you're looking for. Consider reading the other answers about no_std, if you're trying to solve a problem. I suggest you only read on, if you're interested in trivia about the inner workings of Rust.
If you really want full control over the environment you use, it is possible to use Rust without the core library using the no_core attribute.
If you decide to do so, you will run into some problems, because the compiler is integrated with some items defined in core.
This integration works by applying the #[lang = "..."] attribute to those items, making them so called "lang items".
If you use no_core, you'll have to define your own lang items for the parts of the language you'll actually use.
For more information I suggest the following blog posts, which go into more detail on the topic of lang items and no_core:
Rust Tidbits: What Is a Lang Item?
Oxidizing the technical interview
So yes, in theory it is possible to run Rust code without any sort of standard library and supplied types, but only if you then supply the required types yourself.
Also this is not stable and will likely never be stabilized and it is generally not a recommended way of using Rust.
When you're not using std, you rely on core, which is a subset of the std library which is always (?) available. This is what's called a no_std environment, which is commonly used for some types of "embedded" programming. You can find more about no_std in the Rust Embedded book, including some guidance on how to get started with no_std programming.

Is it possible to write something as complex as `print!` in a pure Rust macro?

I am starting out learning Rust macros, but the documentation is somewhat limited. Which is fine — they're an expert feature, I guess. While I can do basic code generation, implementation of traits, and so on, some of the built-in macros seem well beyond that, such as the various print macros, which examine a string literal and use that for code expansion.
I looked at the source for print! and it calls another macro called format_args. Unfortunately this doesn't seem to be built in "pure Rust" the comment just says "compiler built-in."
Is it possible to write something as complex as print! in a pure Rust macro? If so, how would it be done?
I'm actually interested in building a "compile time trie" -- basically recognizing certain fixed strings as "keywords" fixed at compile time. This would be performant (probably) but mostly I'm just interested in code generation.
format_args is implemented in the compiler itself, in the libsyntax_ext crate. The name is registered in the register_builtins function, and the code to process it has its entry point in the expand_format_args function.
Macros that do such detailed syntax processing cannot be defined using the macro_rules! construct. They can be defined with a procedural macro; however, this feature is currently unstable (can only be used with the nightly compiler and is subject to sudden and unannounced changes) and rather sparsely documented.
Rust macros cannot parse string literals, so it's not possible to create a direct Rust equivalent of format_args!.
What you could do is to use a macro to transform the function-call-like syntax into something that represents the variadic argument list in the Rust type system in some way (say, as a heterogeneous single-linked list, or a builder type). This can then be passed to a regular Rust function, along with the format string. But you will not be able to implement compile-time type checking of the format string this way.

Resources