Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 11 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ Which tool do I want?

This project aims to catch memory safety issues at compile-time by applying Rust's proven ownership model to C++ code. It helps prevent common bugs like use-after-move, double-free, and dangling references before they reach production.

Though C++ is flexible enough to mimic Rust's idioms in many ways, implementing a borrow-checking without modifying the compiler system appears to be impossible, as analyzed in [this document](https://docs.google.com/document/d/e/2PACX-1vSt2VB1zQAJ6JDMaIA9PlmEgBxz2K5Tx6w2JqJNeYCy0gU4aoubdTxlENSKNSrQ2TXqPWcuwtXe6PlO/pub).
Though C++ is flexible enough to mimic Rust's idioms in many ways, implementing a borrow checker without modifying the compiler system appears to be impossible, as analyzed in [this document](https://docs.google.com/document/d/e/2PACX-1vSt2VB1zQAJ6JDMaIA9PlmEgBxz2K5Tx6w2JqJNeYCy0gU4aoubdTxlENSKNSrQ2TXqPWcuwtXe6PlO/pub).

We provide rusty-cpp-checker, a standalone static analyzer that enforces Rust-like ownership and borrowing rules for C++ code, bringing memory safety guarantees to existing C++ codebases without runtime overhead. rusty-cpp-checker does not bringing any new grammar into c++. Everything works through simple annoations such as adding `// @safe` enables safety checking on a function.
We provide `rusty-cpp-checker`, a standalone static analyzer that enforces Rust-like ownership and borrowing rules for C++ code without runtime overhead. `rusty-cpp-checker` does not introduce new C++ grammar. It uses comment annotations; for example, adding `// @safe` enables safety checking for a function.


### Example
Expand Down Expand Up @@ -97,7 +97,7 @@ Cannot create mutable borrow 'mut_ref': 'value' is already borrowed by 'const_re

#### Option 1: Git Submodule (Recommended)

**The recommended way to use rusty-cpp** is to use cmake to do automatic checking at build. Also consider adding rusty-cpp as a submoduel so it is easy to track updates as rusty-cpp is rapidly evolving.
**The recommended way to use rusty-cpp** is to use CMake for automatic build-time checking. Also consider adding rusty-cpp as a submodule to make updates easier to track.
See [cmake-example-project/](cmake-example-project/) for a complete working example.


Expand All @@ -111,7 +111,7 @@ curl -sSL https://raw.githubusercontent.com/shuaimu/rusty-cpp/main/install.sh |

Or clone and run locally:
```bash
git clone https://github.com/shuaimu/rusty-cpp
git clone https://github.com/shuaimu/rusty-cpp.git
cd rusty-cpp
./install.sh
```
Expand All @@ -121,15 +121,15 @@ cd rusty-cpp
#### Option 3: Manual Build

**Prerequisites** (must be installed before building):
- **Rust**: 1.70+
- **Rust**: 1.85+
- **LLVM/Clang**: 16+ (for parsing C++)
- **Z3**: 4.8+ (constraint solver)

##### macOS

```bash
brew install llvm z3
git clone https://github.com/shuaimu/rusty-cpp
git clone https://github.com/shuaimu/rusty-cpp.git
cd rusty-cpp
cargo build --release
```
Expand All @@ -138,7 +138,7 @@ cargo build --release

```bash
sudo apt-get install llvm-16-dev libclang-16-dev clang-16 libz3-dev
git clone https://github.com/shuaimu/rusty-cpp
git clone https://github.com/shuaimu/rusty-cpp.git
cd rusty-cpp
cargo build --release
```
Expand Down Expand Up @@ -166,24 +166,6 @@ rusty-cpp-checker -vv path/to/file.cpp
rusty-cpp-checker --format json path/to/file.cpp
```

#### Standalone Binary (No Environment Variables Required)

For release distributions, we provide a standalone binary that doesn't require setting environment variables:

```bash
# Build standalone release
./build_release.sh

# Install from distribution
cd dist/rusty-cpp-checker-*/
./install.sh

# Or use directly
./rusty-cpp-checker-standalone file.cpp
```

See [RELEASE.md](RELEASE.md) for details on building and distributing standalone binaries.

#### Environment Setup (macOS)

No environment variables required! Both Z3 and LLVM are auto-detected via pkg-config at build time.
Expand Down Expand Up @@ -544,7 +526,7 @@ rusty-cpp-transpiler input.rs -o output.cppm -m my_module
rusty-cpp-transpiler --crate path/to/Cargo.toml --output-dir cpp_out

# Generate a CMakeLists.txt for the emitted modules from Cargo.toml
rusty-cpp-transpiler --crate path/to/Cargo.toml --cmake path/to/Cargo.toml
rusty-cpp-transpiler --cmake path/to/Cargo.toml

# Crates using macros: expand first (requires cargo-expand)
rusty-cpp-transpiler --crate path/to/Cargo.toml --expand
Expand Down Expand Up @@ -574,7 +556,7 @@ bash tests/transpile_tests/run_parity_matrix.sh --crate semver

## 3. Rust as an Embedded DSL in C++

For codebases that can't (or shouldn't) move whole crates at once, the transpiler supports **inline Rust blocks inside `.cpp` files**. You write a function in Rust where it lives today; the tool generates and maintains the equivalent C++ right below it. Normal builds compile the generated C++ (`RUSTYCPP_RUST=0`) — consumers of your project never need a Rust toolchain.
For codebases that can't (or shouldn't) move whole crates at once, the transpiler supports **inline Rust blocks inside C++ source and header files**. You write supported Rust items where they live today; the tool generates and maintains the equivalent C++ below them. Normal builds compile the generated C++ (`RUSTYCPP_RUST=0`) — consumers of your project never need a Rust toolchain.

```cpp
#if RUSTYCPP_RUST
Expand All @@ -596,7 +578,7 @@ rusty-cpp-transpiler inline-rust --check --files src/*.cpp
rusty-cpp-transpiler inline-rust --rewrite --files src/*.cpp
```

The generator is deterministic, touches only the `GEN` regions, and records a `rust_sha256` of the Rust payload so CI can reject stale fallbacks. V1 deliberately accepts a conservative Rust subset (free functions, structs with named fields, inherent impls, `Option`/`Result`/`Vec`/`String`, standard control flow) and keeps each block local to its translation unit — no cross-TU declaration magic. See §12 of [docs/rusty-cpp-transpiler.md](docs/rusty-cpp-transpiler.md) for the normative grammar and subset.
The generator is deterministic, touches only the `GEN` regions, and records a `rust_sha256` of the Rust payload so CI can reject stale fallbacks. The supported subset includes free functions, structs with named fields, inherent impls, traits and trait implementations, `Option`/`Result`/`Vec`/`String`, and standard control flow. Inline blocks do not automatically surface declarations across translation units. See §12 of [docs/rusty-cpp-transpiler.md](docs/rusty-cpp-transpiler.md) for the marker format.

---

Expand Down Expand Up @@ -649,7 +631,6 @@ Include the headers:
#include <rusty/box.hpp>
#include <rusty/refcell.hpp>
#include <rusty/vec.hpp>
#include <rusty/hashmap.hpp>
```

These types are designed to work seamlessly with the borrow checker and enforce Rust's safety guarantees at runtime. They are also the runtime the transpiler (§2) emits code against — hand-written `rusty::` C++ and transpiled Rust share one type system, so the two styles mix freely in a codebase.
Expand Down Expand Up @@ -846,7 +827,7 @@ if (result.is_ok()) {

---

## Tips in writing rusty c++
## Tips for Writing Rusty C++
Writing C++ that is easier to debug by adopting principles from Rust.

### Being Explicit
Expand Down
6 changes: 3 additions & 3 deletions cmake-example-project/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ ctest -R cpp_rust_member_interop --output-on-failure

Notes:

- The test wiring is enabled by default with `ENABLE_CPP_RUST_MEMBER_INTEROP_TEST=ON`.
- The test wiring is enabled by default with `ENABLE_CPP_RUST_MEMBER_INTEROP_TEST=ON` when `bash` is available.
- Rust source transpilation is configured in CMake via `RustyCppTranspiler.cmake` (`cpp_rust_member_interop_transpile` target).
- The script probes for C++20 modules support using a local module import and skips if unavailable.
- The script prefers `clang++` (precompiled module flow) and falls back to `g++ -fmodules-ts`.
Expand All @@ -83,8 +83,8 @@ cmake --build . --target inline_rust_example_rewrite

Notes:

- `inline_rust_example_check` validates marker structure and `rust_sha256`.
- `inline_rust_example_rewrite` rewrites only `RUSTYCPP:GEN` regions.
- When `tools/rustycpp-inline` is available, `inline_rust_example_check` validates marker structure and `rust_sha256`.
- When `tools/rustycpp-inline` is available, `inline_rust_example_rewrite` rewrites only `RUSTYCPP:GEN` regions.
- The `.cpp` example demonstrates TU-local placement; no automatic cross-TU declaration surfacing is performed in v1.

## CMakeLists.txt Integration
Expand Down
3 changes: 2 additions & 1 deletion cmake-example-project/src/inline_header_example.hpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
#pragma once

// Inline Rust DSL example in a header-like file.
// V1 rule: this is safe for shared APIs because other translation units can include it.
// This fixture is included by one translation unit; shared APIs still need an
// ordinary C++ declaration/definition strategy to avoid duplicate definitions.
// In inline mode, includes are author-managed.
// This example demonstrates:
// - a free function (`greet`)
Expand Down
2 changes: 1 addition & 1 deletion cmake/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,7 @@ endif()

## Further Documentation

- [Submodule Integration Guide](../docs/SUBMODULE_INTEGRATION.md) - Detailed submodule setup
- [Submodule Integration Guide](../docs/submodule_integration.md) - Detailed submodule setup
- [Main Project README](../README.md) - Project overview and features
- [Examples](../examples/) - Sample projects using both integration methods

Expand Down
2 changes: 1 addition & 1 deletion docs/RUST_COMPARISON.md
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,6 @@ No Pin support. Self-referential structs are not specially handled.

## Related Documentation

- [RAII_TRACKING.md](RAII_TRACKING.md) - RAII tracking implementation details
- [raii_tracking.md](raii_tracking.md) - RAII tracking implementation details
- [../CLAUDE.md](../CLAUDE.md) - Full project documentation
- [annotation_reference.md](annotation_reference.md) - Safety annotation syntax
4 changes: 2 additions & 2 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,13 @@ Complete implementation summaries for major features:
- Workarounds for missing features
- Implementation priorities

- **[RAII_TRACKING.md](RAII_TRACKING.md)** - RAII tracking implementation
- **[raii_tracking.md](raii_tracking.md)** - RAII tracking implementation
- Container/iterator lifetime tracking
- Member lifetime tracking
- Lambda escape analysis
- new/delete tracking

- **[PARTIAL_MOVES_PLAN.md](PARTIAL_MOVES_PLAN.md)** - Partial moves improvement plan
- **[partial_borrows.md](partial_borrows.md)** - Partial moves and borrows
- Current status (basic support implemented)
- Nested field tracking plan
- Partial borrow tracking plan
Expand Down
42 changes: 22 additions & 20 deletions docs/rusty-cpp-book.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ A Rust-style borrow checker for C++ code.
- [Part IX: Future Roadmap](#part-ix-future-roadmap)
- [30. Planned Features](#30-planned-features)
- [31. FAQ & Troubleshooting](#31-faq--troubleshooting)
- [32. Macro Hygiene & the Cross-Crate Manifest](#32-macro-hygiene--the-cross-crate-manifest)

---

Expand Down Expand Up @@ -132,7 +133,7 @@ RustyCpp differs by using Rust's proven ownership model rather than heuristics,
### Installation & Build Requirements

**Prerequisites:**
- Rust 1.70+ (for building the checker)
- Rust 1.85+ (for building the checker)
- LLVM/Clang 16+ (for LibClang)
- Z3 Solver (for constraint solving)

Expand Down Expand Up @@ -180,13 +181,13 @@ void bad_example() {

```bash
# Basic usage
./rusty-cpp-checker example.cpp
./target/release/rusty-cpp-checker example.cpp

# With include paths
./rusty-cpp-checker example.cpp -I include -I /usr/local/include
./target/release/rusty-cpp-checker example.cpp -I include -I /usr/local/include

# With compile_commands.json
./rusty-cpp-checker example.cpp --compile-commands build/compile_commands.json
./target/release/rusty-cpp-checker example.cpp --compile-commands build/compile_commands.json
```

### Understanding Output
Expand Down Expand Up @@ -1723,13 +1724,11 @@ add_custom_target(borrow_check
COMMENT "Running RustyCpp borrow checker"
)

# Or integrate with compile_commands.json
add_custom_target(borrow_check_all
COMMAND ${RUSTY_CPP_CHECKER}
--compile-commands ${CMAKE_BINARY_DIR}/compile_commands.json
${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp
COMMENT "Running RustyCpp on all sources"
)
# The checker accepts one translation unit per invocation. For target-wide
# checking, use the repository's CMake helper:
include(path/to/rusty-cpp/cmake/RustyCppSubmodule.cmake)
enable_borrow_checking()
add_borrow_check_target(your_target)
```

### Makefile Integration
Expand All @@ -1739,7 +1738,9 @@ RUSTY_CPP_CHECKER := rusty-cpp-checker
INCLUDE_DIRS := -I include -I third_party/include

borrow_check: $(SOURCES)
$(RUSTY_CPP_CHECKER) $(SOURCES) $(INCLUDE_DIRS)
@for source in $(SOURCES); do \
$(RUSTY_CPP_CHECKER) $$source $(INCLUDE_DIRS) || exit $$?; \
done

.PHONY: borrow_check
```
Expand All @@ -1753,7 +1754,7 @@ RustyCpp can read compiler flags from `compile_commands.json`:
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ..

# Run checker with compile commands
./rusty-cpp-checker src/main.cpp --compile-commands build/compile_commands.json
./target/release/rusty-cpp-checker src/main.cpp --compile-commands build/compile_commands.json
```

---
Expand All @@ -1763,7 +1764,7 @@ cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ..
### CLI Flags

```bash
./rusty-cpp-checker file.cpp -I include -I /usr/local/include
./target/release/rusty-cpp-checker file.cpp -I include -I /usr/local/include
```

### Environment Variables
Expand All @@ -1772,7 +1773,7 @@ cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ..
export CPLUS_INCLUDE_PATH=/project/include:/third_party/include
export CPATH=/usr/include

./rusty-cpp-checker file.cpp
./target/release/rusty-cpp-checker file.cpp
```

### Auto-Detection
Expand Down Expand Up @@ -2167,7 +2168,7 @@ void safe_wrapper() {

### Current Status: Implemented

RustyCpp provides **compile-time thread safety** via Rust-like `Send` and `Sync` traits, enforced through C++20 concepts.
RustyCpp provides compile-time `Send` and `Sync` constraints for supported types, enforced through C++20 concepts. It does not analyze arbitrary C++ thread code for data races.

### Send Trait: Transfer Across Threads

Expand Down Expand Up @@ -2684,10 +2685,10 @@ The [Safe C++ Proposal](https://safecpp.org/draft.html) is a comprehensive langu
| **Borrow types** | `T^` (mutable), `const T^` (shared) | Standard C++ references |
| **Relocation** | `rel` keyword | `std::move` + analysis |
| **Sum types** | `choice` + `match` | Library types + callbacks |
| **Thread safety** | `send`/`sync` traits | Not implemented |
| **Thread safety** | `send`/`sync` traits | `Send`/`Sync` constraints for supported types |
| **Lifetime params** | First-class syntax | Comment annotations |
| **Runtime checks** | Panic on bounds, etc. | Pure static analysis |
| **Compiler support** | Requires compiler changes | Works with any C++20 compiler |
| **Compiler support** | Requires compiler changes | Works with the repository's supported C++23 toolchain |
| **Adoption** | Rewrite with new syntax | Gradual annotation |

### Philosophical Differences
Expand Down Expand Up @@ -2824,7 +2825,8 @@ A: Make sure third-party headers are detected as external. Check:

A: Pass specific files to the checker:
```bash
./rusty-cpp-checker src/safe_module.cpp src/core.cpp
./target/release/rusty-cpp-checker src/safe_module.cpp
./target/release/rusty-cpp-checker src/core.cpp
```

### Q: Can I use this with existing codebases?
Expand Down Expand Up @@ -2965,7 +2967,7 @@ Rust-like cross-crate resolution without brittle number-matching.
---

*Document version: 1.7*
*Last updated: June 2026*
*Last updated: August 2026*
*Section 32 (macro hygiene & cross-crate manifest) added June 2026*
*Reorganized: Raw pointer discussion moved to dedicated Section 24 in Part VIII*
*Early examples now use references instead of pointers to match Rust's safe-by-default model*
2 changes: 1 addition & 1 deletion tests/transpile_tests/arrayvec/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ arrayvec

[![License: Apache](https://img.shields.io/badge/License-Apache%202.0-red.svg)](LICENSE-APACHE)
OR
[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE-MIT)

A vector with fixed capacity.

Expand Down