---
title: Send and Sync
url: https://doc.liz6.com/en/rust/06-concurrency-and-asynchrony/01-Send-Sync
locale: en
area: rust
tags:
- rust
- concurrency-and-asynchrony
date: 2026-06-30
modified: 2026-07-16
description: 'Send and Sync are the cornerstones of Rust concurrency safety—Send allows transferring ownership of a type across threads, while Sync allows sharing references to a type across threads. They are auto traits (inferred by the compiler): if all fields of a type are Send, the type is automatically Send. PhantomData is used to manually suppress or restore this inference—crucial in unsafe code and FFI.'
---

# Send and Sync

> Send and Sync are the cornerstones of Rust concurrency safety—Send allows transferring ownership of a type across threads, while Sync allows sharing references to a type across threads. They are auto traits (inferred by the compiler): if all fields of a type are Send, the type is automatically Send. PhantomData is used to manually suppress or restore this inference—crucial in unsafe code and FFI.

## What are Send and Sync?

`Send` and `Sync` are the core of Rust's concurrency safety—they are compile-time marker traits that indicate whether a type can be used across threads.

**`Send`**: Ownership of this type can be transferred between threads. If all fields of a type are `Send`, it is `Send`—the compiler infers this automatically. `Rc<T>` is not `Send`—its reference counting operations are not atomic, and moving it into another thread could lead to incorrect counts.

**`Sync`**: This type can be accessed between threads via **shared references** (`&T`). Formally: `T: Sync` if and only if `&T: Send`. `RefCell<T>` is not `Sync`—its runtime borrow checking does not guarantee thread safety. `Mutex<T>` is `Sync` (when `T: Send`)—Mutex protects its interior with locks, allowing safe access via `&Mutex<T>` from multiple threads.

## How the Compiler Infers Them

The compiler checks each field of a type: if all fields are `Send`, the type is automatically `Send`. If all fields are `Sync`, the type is automatically `Sync`. A type loses these properties only when it introduces **raw pointers** (`*const T`, `*mut T`) or **non-thread-safe primitives** (`Rc`, `RefCell`, `Cell`, `UnsafeCell`).

```rust
fn assert_send<T: Send>() {}
assert_send::<i32>();                // OK
assert_send::<Arc<String>>();        // OK (Arc synchronizes via atomic operations)
// assert_send::<Rc<String>>();      // COMPILE ERROR
// assert_send::<*const i32>();      // COMPILE ERROR — raw pointers lack ownership semantics

fn assert_sync<T: Sync>() {}
assert_sync::<Mutex<i32>>();         // OK (Mutex ensures internal synchronization)
// assert_sync::<RefCell<i32>>();    // COMPILE ERROR
```

## Controlling Inference Manually with PhantomData

When implementing custom containers using raw pointers, raw pointers do not carry Send/Sync semantics—but your container might logically guarantee them:

```rust
use std::marker::PhantomData;
use std::rc::Rc;

struct MyNonSend {
    data: i32,
    _not_send: PhantomData<Rc<()>>,  // Marks: this type is not Send (inherits Rc's property)
}
// Although MyNonSend only contains i32 internally (which is Send), PhantomData<Rc<()>> makes it !Send
```

PhantomData occupies no memory (it is a ZST) and serves only as a type-level marker. Authors of unsafe code use PhantomData to communicate to the compiler "this type should/should not be Send/Sync"—and the compiler then performs correctness checks for callers.

## Why Not "All Types Are Send by Default"

The standard library's types are carefully designed: `Rc<T>` is inherently not Send, and `Mutex<T>` is inherently Sync. Any third-party library introducing interior mutability must carefully consider the propagation of Send/Sync. If a type accidentally becomes Send when it is not actually thread-safe, it would create a backdoor for data races. This design of "automatic inference + human intervention" allows Rust to balance performance (zero overhead) and safety (compile-time guarantees).

## References

- **Rustonomicon**: Send and Sync
- **Rust Reference**: auto traits

*Keywords: Send, Sync, auto trait, PhantomData, thread safety, marker type, Rc, RefCell*
