Functions
fn add(x: i32, y: i32) -> i32 {
return x +% y;
}
// No return type means the unit type ().
fn shout(msg: str) {
#println(msg);
}
// `pub` for cross-file visibility (the default is module-private).
pub fn answer() -> i32 { return 42; }
Every function body must end with return EXPR;. There is no implicit tail return at the function level (the rule is E0333). Block expressions can still be tail expressions inside a return or a let:
fn classify(n: i32) -> i32 {
return if n < 0 { -1 } else if n == 0 { 0 } else { 1 };
}
Generics use square brackets, not angle brackets (see Ownership for how arguments are passed):
fn identity[T](x: T) -> T { return x; }
fn max[T: Ord](a: T, b: T) -> T { ... }
There is no function overloading. A name has one signature, period. That is what lets a reader, or a model, resolve a call to exactly one definition.
unsafe fn
A function whose contract the compiler cannot verify is declared unsafe fn. Calling one outside an unsafe { } block is rejected (E0801), so every call site is grep-able and self-documenting.
unsafe fn as_str(borrow self) -> str { ... } // caller must uphold the invariant
let view: str = unsafe { t.as_str() };
This is the same escape hatch as an unsafe block, lifted to the signature: it marks operations whose safety rests on a caller-side invariant, such as Text::as_str or a raw FFI return.