9

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.

Peter Hall
  • 53,120
  • 14
  • 139
  • 204
FredMan
  • 861
  • 7
  • 19
  • Looks like placement_new was scrapped... so right now it does nothing? – Keozon Apr 10 '18 at 21:21
  • Using this gives this error: `error[E0658]: placement-in expression syntax is experimental and subject to change. (see issue #27779)`. Looks like it is going to be used like this if approved: `let v = Vec::new(); // The old syntax in v.back() { 10 }; // The new syntax. v.back() <- 10; // This clearly looks better to me.` – AbhiNickz Apr 11 '18 at 06:29
  • @turbulencetoo please be careful of where you link. That's a fork of the official RFCs repo, **not the official one itself**. [The official RFC repo](https://github.com/rust-lang/rfcs/blob/master/text/1228-placement-left-arrow.md) contains updates, such as the fact that this RFC has been unaccepted. – Shepmaster Apr 12 '18 at 23:46

1 Answers1

13

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.

Peter Hall
  • 53,120
  • 14
  • 139
  • 204
  • 3
    It's worth noting that those RFCs were originally accepted (hence why they were semi-implemented on nightly), [but as of a week ago have been 'unaccepted'](https://github.com/rust-lang/rust/pull/48333) due to various soundness issues. It's likely that an entirely new RFC will have to be submitted for this to make a return. `box` syntax is still around though, as the compiler itself makes pretty heavy use of it. – Joe Clay Apr 11 '18 at 11:02