Skip to content
Closed
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
19 changes: 19 additions & 0 deletions .claude/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"$schema": "https://json.schemastore.org/claude-code-settings.json",
"attribution": {
"commit": "T.E.A de Souza",
"pr": "T.E.A de Souza"
},
"hooks": {
"SessionStart": [
{
"hooks": [
{
"type": "command",
"command": "git config user.name \"T.E.A de Souza\" && git config user.email \"tea.desouza@gmail.com\""
}
]
}
]
}
}
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ on:
- automation/bors/auto
- automation/bors/try
- try-perf
pull_request:
branches:
- "**"
# pull_request trigger disabled — this fork uses decisive-ci.yml instead.
# The upstream CI matrix requires rust-lang/rust infrastructure (sccache, S3, bors)
# and will burn CI minutes or get cancelled on forks.

permissions:
contents: read
Expand Down
101 changes: 101 additions & 0 deletions .github/workflows/decisive-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
name: Decisive Trait CI

on:
push:
tags: [ 'v*' ]
pull_request:
branches: [ main ]
workflow_dispatch:

jobs:
build-and-test:
name: Build stage1 compiler & run decisive tests
runs-on: ubuntu-latest
timeout-minutes: 240

steps:
- name: Free disk space
run: |
sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc*
df -h /

- name: Checkout compiler fork
uses: actions/checkout@v4
with:
fetch-depth: 2
submodules: recursive

- name: Install build dependencies
run: |
sudo apt-get update
sudo apt-get install -y build-essential cmake ninja-build python3 curl pkg-config libssl-dev

- name: Configure compiler build
run: |
cat > bootstrap.toml << 'TOML'
change-id = 153143
profile = "compiler"

[llvm]
download-ci-llvm = false
assertions = false

[rust]
debug-logging = false
debug-assertions = false
incremental = false
lto = "off"
download-rustc = false
TOML

- name: Cache stage0 and LLVM
uses: actions/cache@v4
with:
path: |
build/cache
build/x86_64-unknown-linux-gnu/llvm
key: stage0-llvm-${{ hashFiles('src/stage0', 'src/llvm-project/llvm/CMakeLists.txt') }}
restore-keys: stage0-llvm-

- name: Build stage1 compiler and stdlib
run: python3 x.py build library --stage 1

- name: Run compiler tests (decisive trait)
run: python3 x.py test tests/ui --stage 1 --test-args "decisive"

- name: Package stage1 toolchain
run: |
STAGE1=build/x86_64-unknown-linux-gnu/stage1
DEST=rustc-decisive-x86_64-unknown-linux-gnu
mkdir -p "$DEST"
cp -a "$STAGE1/bin" "$DEST/"
cp -a "$STAGE1/lib" "$DEST/"
echo "decisive-stage1 ($(git rev-parse --short HEAD))" > "$DEST/VERSION"
tar czf "$DEST.tar.gz" "$DEST"
echo "TOOLCHAIN_ARCHIVE=$DEST.tar.gz" >> "$GITHUB_ENV"
echo "TOOLCHAIN_NAME=$DEST" >> "$GITHUB_ENV"

- name: Upload toolchain artifact
uses: actions/upload-artifact@v4
with:
name: rustc-decisive-x86_64-unknown-linux-gnu
path: ${{ env.TOOLCHAIN_ARCHIVE }}
retention-days: 90

- name: Create GitHub Release
if: startsWith(github.ref, 'refs/tags/v')
uses: softprops/action-gh-release@v2
with:
files: ${{ env.TOOLCHAIN_ARCHIVE }}
body: |
## Rust with Decisive Trait

Custom rustc build with the `Decisive` trait, enabling user-defined
short-circuiting `&&` and `||` operators.

### Install
```bash
tar xzf ${{ env.TOOLCHAIN_NAME }}.tar.gz
rustup toolchain link decisive ./${{ env.TOOLCHAIN_NAME }}
cargo +decisive build
```
150 changes: 98 additions & 52 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,79 +1,125 @@
> Fork of [rust-lang/rust](https://github.com/rust-lang/rust). See the [original README](https://github.com/rust-lang/rust/blob/master/README.md).

<div align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/rust-lang/www.rust-lang.org/master/static/images/rust-social-wide-dark.svg">
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/rust-lang/www.rust-lang.org/master/static/images/rust-social-wide-light.svg">
<img alt="The Rust Programming Language: A language empowering everyone to build reliable and efficient software"
src="https://raw.githubusercontent.com/rust-lang/www.rust-lang.org/master/static/images/rust-social-wide-light.svg"
width="50%">
</picture>

[Website][Rust] | [Getting started] | [Learn] | [Documentation] | [Contributing]
<img alt="Rust - Shorted" src="RUST-SHORTED.png" width="50%">
</div>

This is the main source code repository for [Rust]. It contains the compiler,
standard library, and documentation.
# Overloadable Short-Circuiting Operators for Rust

This public fork `rust-lang/rust` adds a `Decisive` trait to `core::ops`, enabling user-defined types to participate in short-circuiting `&&` and `||` expressions. The mechanism is general-purpose (three-valued logic, fuzzy logic, option types, etc.).

The key change is at [7a510a6](https://github.com/eelstork/rust/commit/7a510a641535e0c1c5acc7dfef41e04b4df9ada5)

## Community discussions

Making `&&` and `||` overloadable has been discussed several times within the Rust ecosystem:

- **[rust-lang/libs-team #144](https://github.com/rust-lang/libs-team/issues/144)** — *Traits for short-circuiting `||` and `&&`*, proposing `And` and `Or` traits using `ControlFlow` for the short-circuit decision. Originally suggested by @scottmcm on Zulip.
- **[rust-lang/rfcs #2722](https://github.com/rust-lang/rfcs/pull/2722)** — @Nokel81's RFC proposing `LogicalOr` and `LogicalAnd` traits with a `ShortCircuit` enum.
- **[Rust Internals: Pre-RFC (2019)](https://internals.rust-lang.org/t/pre-rfc-overload-short-curcuits/10460)** — Early discussion exploring `BoolOr`/`BoolAnd` trait shapes and whether "truthiness" should be a separate trait.
- **[Rust Internals: A different way to override `||` and `&&` (2021)](https://internals.rust-lang.org/t/a-different-way-to-override-and/14627)** — Follow-up reacting to RFC 2722's design.

Rust's own `std::ops` documentation [acknowledges the gap](https://doc.rust-lang.org/std/ops/index.html): `&&` and `||` are not currently overloadable because their short-circuiting semantics don't fit the standard trait-as-function-call model.

This fork takes a simpler approach than those proposals — a single `Decisive` trait with `is_true()` / `is_false()` methods, combined with existing `BitAnd` / `BitOr` — closer to how C# solves the same problem via `operator true`, `operator false`, `operator &`, and `operator |`.

## Re: Classic Behavior Trees and Correctness

The design implemented here enables stateless behavior trees via Active Logic, convergent with Colledanchise and Ögren in [*Behavior Trees in Robotics and AI: An Introduction*](https://arxiv.org/abs/1709.00084) (CRC Press, 2018). The central argument is that BTs derive their formal properties — reactivity, modularity, and analyzability for safety and liveness — from re-evaluating the tree from the root at every tick. Nodes that cache a "running" status and expect to be resumed introduce stale state, which undermines exactly the reactive guarantees that motivated adopting BTs over finite state machines.

Many popular BT implementations (Unreal's BT system, BehaviorTree.CPP, Unity Behavior) lean on persistent running state and blackboards. These are practical choices for specific domains, but they trade away the formal properties that Colledanchise and Ögren analyze. This fork targets the stateless end of the spectrum.

## What Changed

[Rust]: https://www.rust-lang.org/
[Getting Started]: https://www.rust-lang.org/learn/get-started
[Learn]: https://www.rust-lang.org/learn
[Documentation]: https://www.rust-lang.org/learn#learn-use
[Contributing]: CONTRIBUTING.md
The `Decisive` trait is gated behind `#![feature(decisive_trait)]`. The change touches 18 files:

## Why Rust?
**Library:**

- **Performance:** Fast and memory-efficient, suitable for critical services, embedded devices, and easily integrated with other languages.
- `library/core/src/ops/decisive.rs` — The `Decisive` trait with `is_true()` and `is_false()` methods, plus `impl Decisive for bool`.

- **Reliability:** Our rich type system and ownership model ensure memory and thread safety, reducing bugs at compile-time.
**Compiler:**

- **Productivity:** Comprehensive documentation, a compiler committed to providing great diagnostics, and advanced tooling including package manager and build tool ([Cargo]), auto-formatter ([rustfmt]), linter ([Clippy]) and editor support ([rust-analyzer]).
- `rustc_hir_typeck/src/op.rs` — When `&&`/`||` operands aren't `bool`, the type checker now accepts types implementing `Decisive + BitAnd` / `Decisive + BitOr`.
- `rustc_middle/src/thir.rs` — New `OverloadedLogicalOp` variant in the THIR.
- `rustc_mir_build/src/builder/expr/into.rs` — MIR lowering desugars to: evaluate LHS → call `is_false` / `is_true` → branch → short-circuit (return LHS) or continue (`BitAnd::bitand` / `BitOr::bitor`).

[Cargo]: https://github.com/rust-lang/cargo
[rustfmt]: https://github.com/rust-lang/rustfmt
[Clippy]: https://github.com/rust-lang/rust-clippy
[rust-analyzer]: https://github.com/rust-lang/rust-analyzer
**Tests:**

## Quick Start
- New `decisive-trait.rs` test passes — verifies short-circuiting, chaining, and `bool` backward compatibility.
- All 56 existing `binop/` tests pass.
- All 44 existing `overloaded/` tests pass.

Read ["Installation"] from [The Book].
## Desugaring

["Installation"]: https://doc.rust-lang.org/book/ch01-01-installation.html
[The Book]: https://doc.rust-lang.org/book/index.html
```rust
// a && b desugars to:
{
let lhs = a;
if Decisive::is_false(&lhs) { lhs } else { BitAnd::bitand(lhs, b) }
}

## Installing from Source
// a || b desugars to:
{
let lhs = a;
if Decisive::is_true(&lhs) { lhs } else { BitOr::bitor(lhs, b) }
}
```

If you really want to install from source (though this is not recommended), see
[INSTALL.md](INSTALL.md).
For `bool`, this is a no-op — `Decisive` for `bool` is trivially `is_true = *self`, `is_false = !*self`, and `bool` already implements `BitAnd` and `BitOr`.

## Getting Help
## Usage

See https://www.rust-lang.org/community for a list of chat platforms and forums.
```rust
#![feature(decisive_trait)]
use std::ops::{BitAnd, BitOr, Decisive};

## Contributing
#[derive(Clone, Copy, PartialEq)]
struct Status(i8);

See [CONTRIBUTING.md](CONTRIBUTING.md).
const DONE: Status = Status(1);
const CONT: Status = Status(0);
const FAIL: Status = Status(-1);

For a detailed explanation of the compiler's architecture and how to begin contributing, see the [rustc-dev-guide](https://rustc-dev-guide.rust-lang.org/).
impl Decisive for Status {
fn is_true(&self) -> bool { self.0 != -1 } // not failing → short-circuits ||
fn is_false(&self) -> bool { self.0 != 1 } // not complete → short-circuits &&
}

## License
impl BitAnd for Status {
type Output = Status;
fn bitand(self, rhs: Status) -> Status { rhs }
}

Rust is primarily distributed under the terms of both the MIT license and the
Apache License (Version 2.0), with portions covered by various BSD-like
licenses.
impl BitOr for Status {
type Output = Status;
fn bitor(self, rhs: Status) -> Status { rhs }
}

See [LICENSE-APACHE](LICENSE-APACHE), [LICENSE-MIT](LICENSE-MIT), and
[COPYRIGHT](COPYRIGHT) for details.
// Sequence — short-circuits on first non-complete:
fn brew_coffee(&mut self) -> Status {
self.pour_water()
&& self.heat_kettle()
&& self.pour_grounds()
&& self.wait_for_boil()
&& self.pour_hot_water()
}

## Trademark
// Selector — short-circuits on first non-failing:
fn find_drink(&mut self) -> Status {
self.try_coffee() || self.try_tea() || self.try_water()
}
```

[The Rust Foundation][rust-foundation] owns and protects the Rust and Cargo
trademarks and logos (the "Rust Trademarks").
## Why Not Alternatives

If you want to use these names or brands, please read the
[Rust language trademark policy][trademark-policy].
| Approach | Problem |
|---|---|
| `&` / `\|` operators | No short-circuiting — both sides always evaluate |
| Macros `seq!(a, b, c)` | Not native syntax, poor composability |
| Method chaining `.and_then()` | Verbose, requires closures |
| `?` operator via custom `Try` | Early-return semantics, not expression-level short-circuiting |

Third-party logos may be subject to third-party copyrights and trademarks. See
[Licenses][policies-licenses] for details.
## References

[rust-foundation]: https://rustfoundation.org/
[trademark-policy]: https://rustfoundation.org/policy/rust-trademark-policy/
[policies-licenses]: https://www.rust-lang.org/policies/licenses
- Colledanchise, M. and Ögren, P. (2018). *Behavior Trees in Robotics and AI: An Introduction*. CRC Press. [arXiv:1709.00084](https://arxiv.org/abs/1709.00084)
- de Souza, T. (2020). *Implementing Behavior Trees using Three-Valued Logic*. [arXiv:2011.03835](https://arxiv.org/abs/2011.03835)
Binary file added RUST-SHORTED.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions compiler/rustc_hir/src/lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ language_item_table! {
BitXor, sym::bitxor, bitxor_trait, Target::Trait, GenericRequirement::Exact(1);
BitAnd, sym::bitand, bitand_trait, Target::Trait, GenericRequirement::Exact(1);
BitOr, sym::bitor, bitor_trait, Target::Trait, GenericRequirement::Exact(1);
Decisive, sym::decisive, decisive_trait, Target::Trait, GenericRequirement::Exact(0);
Shl, sym::shl, shl_trait, Target::Trait, GenericRequirement::Exact(1);
Shr, sym::shr, shr_trait, Target::Trait, GenericRequirement::Exact(1);
AddAssign, sym::add_assign, add_assign_trait, Target::Trait, GenericRequirement::Exact(1);
Expand Down
Loading
Loading