Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Cheat Sheet: Non-Rust-Movable Types

Function parameter and return types

C++

Rust (Non-Rust-movable)

Rust (Rust-movable)

[const] T
#![allow(unused)]
fn main() {
Ctor![T]
}
#![allow(unused)]
fn main() {
T
}
T&&
#![allow(unused)]
fn main() {
RvalueReference<T>
}
#![allow(unused)]
fn main() {
&mut T
}
const T&&
#![allow(unused)]
fn main() {
ConstRvalueReference<T>
}
#![allow(unused)]
fn main() {
&T
}
T&
#![allow(unused)]
fn main() {
Pin<&mut T>
}
#![allow(unused)]
fn main() {
&mut T
}
const T&
#![allow(unused)]
fn main() {
&T
}
#![allow(unused)]
fn main() {
&T
}

Basic object creation and storage

C++

Rust (Non-Rust-movable)

Rust (Rust-movable)

auto x = T();
#![allow(unused)]
fn main() {
let x = emplace!(T::ctor_new(()));
}
#![allow(unused)]
fn main() {
let x = T::default();
}
auto x = y;
#![allow(unused)]
fn main() {
let x = emplace!(ctor::copy(&*y));
// sugar for:
let x = emplace!(
  T::ctor_new(&*y));
}
#![allow(unused)]
fn main() {
let x = y.clone();
}
auto x = std::move(y);
#![allow(unused)]
fn main() {
let x = emplace!(ctor::mov!(y));
// sugar for:
let x = emplace!(
  T::ctor_new(ctor::mov!(y)));
}
#![allow(unused)]
fn main() {
let x = y;
}
auto x = T(1, 2);
#![allow(unused)]
fn main() {
let x = emplace!(
  T::ctor_new((1, 2)));
}
#![allow(unused)]
fn main() {
let x = T::new(1, 2);
}
// Takes T or const T&
TakesTemporary(T())
#![allow(unused)]
fn main() {
// if it takes a value:
TakesTemporary(T::ctor_new(()))

// if it takes a const reference:
TakesTemporary(
  &*emplace!(T::ctor_new(())))
// (Materialization is explicit!)
}
#![allow(unused)]
fn main() {
// if it takes a value
TakesTemporary(T::default())

// if it takes a const reference:
TakesTemporary(&T::default())
}
// Takes T&&
TakesMutableTemporary(T())
#![allow(unused)]
fn main() {
TakesMutableTemporary(
  ctor::mov!(emplace!(T::ctor_new(()))))
}
#![allow(unused)]
fn main() {
TakesMutableTemporary(
  &mut T::default())
}
T Source() { return T(); }
#![allow(unused)]
fn main() {
fn Source() -> Ctor![T] {
  // copy-elided and lazy.
  // constructor won't run until
  // the returned Ctor is "emplaced".
  T::ctor_new(())
}
}
#![allow(unused)]
fn main() {
fn Source() -> T { T::default() }
}
T Source2() {
  T x = T();
  x.Mutate();
  return x;
}
#![allow(unused)]
fn main() {
fn Source2() -> Ctor![T] {
  T::ctor_new(()).ctor_then(|mut x| {
    x.as_mut().Mutate();
    Ok(())
  })
}
}
#![allow(unused)]
fn main() {
fn Source2() -> T {
  let mut x = T::default();
  x.Mutate();
  x
}
}
void Sink(T x) {
  x.Something();
}
#![allow(unused)]
fn main() {
fn Sink(x: Ctor![T]) {
  emplace!(x).Something()
}
}
#![allow(unused)]
fn main() {
fn Sink(x: T) {
  x.Something()
}
}

Compound data types

C++

Rust (Non-Rust-movable)

Rust (Rust-movable)

struct T { U field; };
#![allow(unused)]
fn main() {
#[recursively_pinned]
struct T { field: U }
}
#![allow(unused)]
fn main() {
struct T { field: U }
}
std::make_unique<T>()
#![allow(unused)]
fn main() {
Box::emplace(T::ctor_new(()))
}
#![allow(unused)]
fn main() {
Box::new(T::default())
}
T x = {.field = std::move(y)}
#![allow(unused)]
fn main() {
let x = emplace!(ctor!(
  T {field: ctor::mov!(y)}));
}
#![allow(unused)]
fn main() {
let x = T { field: y };
}

N/A: C++ doesn’t have tuple-structs.

#![allow(unused)]
fn main() {
#[recursively_pinned]
struct T2(U);
}
#![allow(unused)]
fn main() {
struct T2(U);
}

N/A: C++ doesn’t have tuple-structs.

#![allow(unused)]
fn main() {
let x = emplace!(ctor!(T2(ctor::mov!(y))));
}
#![allow(unused)]
fn main() {
let x = T2(y);
}

Object access and mutation

C++

Rust (Non-Rust-movable)

Rust (Rust-movable)

x.ConstMethod()
#![allow(unused)]
fn main() {
x.ConstMethod()
}
#![allow(unused)]
fn main() {
x.ConstMethod()
}
x.NonConstMethod()
#![allow(unused)]
fn main() {
x.as_mut().NonConstMethod()
}
#![allow(unused)]
fn main() {
x.NonConstMethod()
}
x = {};
#![allow(unused)]
fn main() {
x.as_mut().assign(T::ctor_new(()));
}
#![allow(unused)]
fn main() {
x = T::default();
}
x = y;
#![allow(unused)]
fn main() {
x.as_mut().assign(&*y);
}
#![allow(unused)]
fn main() {
x = y.clone();
}
x = std::move(y);
#![allow(unused)]
fn main() {
x.as_mut().assign(ctor::mov!(y));
}
#![allow(unused)]
fn main() {
x = y;
}
x = New();  // returns T by value
#![allow(unused)]
fn main() {
x.as_mut().assign(ctor::mov!(
  emplace!(New())));
}
#![allow(unused)]
fn main() {
x = New();
}
x.~T();
new (&x) T();
#![allow(unused)]
fn main() {
unsafe { ctor::reconstruct(x.as_mut(),
  T::ctor_new(())) };
}
#![allow(unused)]
fn main() {
x = T::default();
}
x.y = …;  // x is a struct
#![allow(unused)]
fn main() {
x.as_mut().project_pin()
  .y.assign(…);
}
#![allow(unused)]
fn main() {
x.y = …;
}