Fe for Rust Developers
Fe draws heavy inspiration from Rust. This guide highlights what’s familiar and what’s different for Rust developers.
Familiar Concepts
Section titled “Familiar Concepts”Structs
Section titled “Structs”Fe structs work like Rust structs:
struct Point { x: u256, y: u256,}
let p = Point { x: 10, y: 20 }let x = p.xImpl Blocks
Section titled “Impl Blocks”Methods are defined in impl blocks:
struct Counter { value: u256,}
impl Counter { fn new() -> Self { Counter { value: 0 } }
fn increment(mut self) { self.value += 1 }
fn get(self) -> u256 { self.value }}Traits
Section titled “Traits”Traits define shared behavior:
trait Hashable { fn hash(self) -> u256}
impl Hashable for Point { fn hash(self) -> u256 { self.x ^ self.y }}Generics
Section titled “Generics”Type parameters work similarly:
fn identity<T>(value: own T) -> T { value}
struct Wrapper<T> { value: T,}
impl<T> Wrapper<T> { fn get(own self) -> T { self.value }}Trait Bounds
Section titled “Trait Bounds”Constrain generics with trait bounds:
fn process<T: Hashable>(item: T) -> u256 { item.hash()}
fn complex<T: Hashable + Printable>(item: T) { // T must implement both traits}Enums and Pattern Matching
Section titled “Enums and Pattern Matching”Enums with match expressions:
enum Status { Pending, Active, Completed { result: u256 },}
fn handle(status: Status) -> u256 { match status { Status::Pending => 0, Status::Active => 1, Status::Completed { result } => result, }}Option Type
Section titled “Option Type”Optional values use Option<T>:
let maybe: Option<u256> = Option::Some(42)
match maybe { Option::Some(v) => v, Option::None => 0,}Expression-Based
Section titled “Expression-Based”Most constructs are expressions:
let value: u256 = if condition { 10 } else { 20 }
let result = match status { Status::Active => true, _ => false,}Type Inference
Section titled “Type Inference”Types are inferred where possible:
let x = true // Type inferred as boollet y: u8 = 42 // Explicit annotationMutability
Section titled “Mutability”Variables are immutable by default:
let x: u256 = 10 // Immutablelet mut y: u256 = 10 // Mutabley = 20 // OKKey Differences
Section titled “Key Differences”Simplified Ownership Model
Section titled “Simplified Ownership Model”Fe has ownership concepts similar to Rust (own, ref, mut) but with key differences:
- Default is view mode (no keyword): the function can read the value but not move or modify it. Unlike Rust, view-mode parameters can be used multiple times without explicit borrowing:
fn process(data: MyStruct) { // View mode: read-only access, no ownership transfer}
let a = MyStruct { x: 1 }process(data: a)process(data: a) // Fine: view mode doesn't consume the valueowntransfers ownership (like Rust’s move): the caller cannot use the value after passing itrefcreates a read-only reference that can be stored in struct fields (like Rust’s&T)mutcreates a mutable handle (like Rust’s&mut T)
Fe also has a borrow checker that prevents simultaneous ref and mut access to the same data.
No Lifetimes
Section titled “No Lifetimes”Fe does not require lifetime annotations. References are scoped but the compiler manages lifetimes implicitly.
See Ownership & Mutability for details on own, ref, and mut.
Iterators
Section titled “Iterators”Currently, Fe has basic loop constructs but not yet the full iterator pattern:
// Rust: items.iter().map(|x| x + 1).collect()// Fe: Currently uses manual while loopslet mut i: u256 = 0while i < len { // process items[i] i = i + 1}No Closures
Section titled “No Closures”Fe doesn’t support closures:
// Rust: let add = |a, b| a + b;// Fe: Use named functionsfn add(a: u256, b: u256) -> u256 { a + b}Modules and Ingots
Section titled “Modules and Ingots”Fe has modules, but uses different terminology:
| Rust | Fe |
Modules and Ingots
Section titled “Modules and Ingots”Fe has modules, but uses different terminology:
| Rust | Fe |
|---|---|
| Crate | Ingot |
| Module | Module |
// In fe.toml[dependencies]my_lib = { path = "../my_lib" }Fe organizes code into ingots (packages) containing modules, similar to Rust’s crate/module system.
EVM-Specific Features
Section titled “EVM-Specific Features”Contract Declarations
Section titled “Contract Declarations”Fe has first-class contract support:
contract Token { store: TokenStorage
init(supply: u256) uses (mut store) { }
recv TokenMsg { }}Message Types
Section titled “Message Types”External interfaces are defined separately:
use std::abi::sol
msg TokenMsg { #[selector = sol("transfer(address,uint256)")] Transfer { to: Address, amount: u256 } -> bool,}Storage Maps
Section titled “Storage Maps”Persistent key-value storage:
struct Storage { balances: StorageMap<Address, u256>,}Events
Section titled “Events”Blockchain events for logging:
#[event]struct Transfer { #[indexed] from: Address, #[indexed] to: Address, value: u256,}Effect System
Section titled “Effect System”Explicit capability tracking:
fn transfer(from: Address, to: Address, amount: u256) uses (store: mut TokenStore, log: mut Log){ // Function declares what it accesses}Syntax Comparison
Section titled “Syntax Comparison”| Concept | Rust | Fe |
|---|---|---|
| Function | fn foo() {} | fn foo() {} |
| Struct | struct Foo {} | struct Foo {} |
| Impl | impl Foo {} | impl Foo {} |
| Trait | trait Bar {} | trait Bar {} |
| Generics | fn foo<T>() | fn foo<T>() |
| Bounds | T: Trait | T: Trait |
| Match | match x {} | match x {} |
| If | if x {} | if x {} |
| Loop | loop {} | loop {} |
| For | for x in iter {} | for x in iter {} |
| Let | let x = 1; | let x = 1 |
| Mut | let mut x = 1; | let mut x = 1 |
| Return | return x | return x |
| Self | self | self |
| Self type | Self | Self |
What You’ll Miss from Rust
Section titled “What You’ll Miss from Rust”| Feature | Status in Fe |
|---|---|
| Ownership/Borrowing | Not applicable (effects instead) |
| Lifetimes | Not needed |
| Closures | Not available |
| Iterators | Planned (trait-based) |
async/await | Not applicable |
| Macros | Not available |
What’s New in Fe
Section titled “What’s New in Fe”| Feature | Description |
|---|---|
contract | Smart contract declarations |
msg | Message type definitions |
recv | Message handlers |
init | Contract constructors |
uses | Effect declarations |
with | Effect binding |
#[selector] | ABI selector attributes |
#[indexed] | Event indexing |
Map<K, V> | Storage mappings |