What is the <- symbol in Rust?

  • A+

What is the <- operator/expression in Rust? You can find the symbol here.

I happened to be looking at a page describing expressions and operations in Rust. I do not program in Rust, so I asked a friend who is pro-Rust what this symbol is but even he doesn't know what it is.

The <- operator is not part of stable Rust. At least not yet.

There is an RFC which proposes syntax involving <- for writing new objects directly to specific places in memory, as an alternative to another RFC, which proposes in. This is a generalisation of the (currently unstable) box syntax, which lets you allocate directly to the heap, without a temporary stack allocation.

Currently, there isn't a way to do that without using unsafe code, and often you'll need to allocate on the stack first. There's a discussion of the underlying problem in this RFC which is the first of a chain of related RFCs and gives the background motivation, but the key reasons are:

  • Working with hardware which expects objects to be written to specific memory addresses. You can do this unsafely in Rust now, but it would be nicer if SDKs could provide a safe and performant API for this.
  • It is faster to write directly to a pre-allocated portion of the heap, rather than allocate new memory every time.
  • When allocating memory for a new object, it would be faster to do that directly on the heap, rather than first allocating on the stack and then cloning or moving.

In C++, there is a feature called "placement new", which accomplishes this by letting you supply a parameter to new, which is an existing pointer at which to start writing. For example:

// For comparison, a "normal new", allocating on the heap string *foo = new string("foo");  // Allocate a buffer char *buffer = new char[100]; // Allocate a new string starting at the beginning of the buffer  string *bar = new (buffer) string("bar"); 

From what I can gather, the above C++ example might look like something like this in Rust with <-:

// Memory allocated on heap (with temporary stack allocation in the process) let foo = Box::new(*b"foo");  // Or, without the stack allocation, when box syntax stabilises: let foo = box *b"foo";  // Allocate a buffer let mut buffer = box [0u8; 100]; // Allocate a new bytestring starting at the beginning of the buffer  let bar = buffer[0..3] <- b"bar"; 

I wouldn't expect this exact code to compile as-is, even if the placement feature was implemented. But notice it is not currently possible in Rust to do what the last line is trying to do: allocate b"bar" directly at the start of the buffer, without allocating on the stack first. In Rust right now, there just isn't a way to do that. Even unsafe code doesn't help you here. You'd still have to allocate on the stack first and then clone it to the buffer:

// Note that b"bar" is allocated first on the stack before being copied // into the buffer buffer[0..3].clone_from_slice(&b"bar"[0..3]); let bar = &buffer[0..3]; 

And box syntax wouldn't help here either. That would allocate new heap memory, and you'd still then have to copy the data to the buffer.

For the simpler case of avoiding temporary stack allocation when allocating new objects on the heap, the box syntax will solve that when it stabilises. Rust will need to solve the more complicated cases at some point in the future, but it it is not yet certain that <- is the syntax that will emerge.


:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: