The prelude’s traits connect generic algorithms and language syntax. Dispatch
is static: generic uses are monomorphized for concrete types, and there is no
current dyn Trait or vtable surface.
| Trait | Contract |
|---|---|
Equatable |
Equality through equals |
Hashable |
Hash consistent with equality |
Comparable[T] |
Total ordering through compare_to |
Display, Debug |
Human and developer text |
Numeric |
Arithmetic and numeric conversion |
Neg, Not, BitNot |
Unary operators |
BitAnd, BitOr, BitXor, Shl, Shr |
Bitwise operators |
Index[K, V], IndexMut[K, V] |
Indexed read and write |
Default, Clone |
Construction and copying |
From[T], Into[T] |
Conversion |
Iterator[T], Iterable[T] |
One-shot and repeatable iteration |
Bytes, Buffer |
Byte views and builders |
Drop |
User cleanup before storage release |
Selectable[T] |
Value that can participate in select |
Operator resolution uses direct primitive operations first and trait dispatch for user-defined operands.
struct Money { cents: int }
impl Equatable for Money {
fn equals(self, other: Money): bool {
return self.cents == other.cents
}
}
impl Display for Money {
fn to_string(self): string {
return "${self.cents} cents"
}
}Collection bounds are meaningful: map keys and set members require Hashable;
sorting requires Comparable; numeric aggregation requires Numeric.
Implement the narrowest contracts a type actually satisfies.
Drop.drop runs as part of compiler-managed cleanup, including cancellation
paths. It is for releasing external resources, not for manually balancing the
compiler’s reference counts.
Contract laws
The type checker verifies signatures, not semantic laws. Implementations must preserve the laws expected by algorithms:
Equatableshould be reflexive, symmetric, and transitive;- equal
Hashablevalues must return the same hash code; Comparableshould agree with equality whencompare_toreturns zero;Cloneshould produce an independently usable value;Displayshould remain suitable for users, whileDebugcan expose structure.
Violating equality and hashing laws can make map entries and set members unreachable even though the program still type-checks.
Operators
For non-primitive operands, syntax routes through trait methods:
| Syntax | Trait method |
|---|---|
left == right |
Equatable.equals |
left < right |
Comparable.compare_to |
-value |
Neg.neg |
!value |
Not.not |
left & right |
BitAnd.bit_and |
left << amount |
Shl.shl |
value[key] |
Index.get |
value[key] = item |
IndexMut.set |
Primitive numeric operations continue through direct compiler lowering. Implementing a trait does not replace those primitive paths.
Conversion
From[T] constructs the implementing type from T; Into[T] converts a
receiver to T. Atoll does not apply arbitrary user conversions silently.
Call conversion methods explicitly at API boundaries so allocation, failure,
and precision changes remain visible.
Default.default() supplies a canonical zero or empty value. It does not imply
that every instance can be reset safely by overwriting it with a default.
Iteration
Iterator[T] defines mutable next(): Option[T]; Iterable[T] creates an
associated iterator. Default iterator methods implement traversal and lazy
map/filter/take/skip adapters.
Byte protocols
Bytes exposes a pointer and length for read-only binary values. Buffer
adds mutation and formatted appends. These traits let strings, lists, slices,
and host APIs share binary operations without a separate nominal byte-buffer
class.
Bytes is implemented by owned and borrowed byte sequences. Buffer is the
growable super-surface implemented only by owned []byte.
Selection
Selectable[T] is structural:
trait Selectable[T] {
fn raw_handle(self): usize
fn await(self): T
}Task[T] and Stream[T] satisfy it. Application implementations must also
honor scheduler handle, readiness, and consumption invariants, so this is
primarily a runtime extension point.
await() on a stream consumes its next item according to stream readiness;
await() on a task waits for completion. select uses raw_handle() to
register readiness with the scheduler before evaluating the winning arm.
Cleanup
Drop.drop cannot suspend. Standard resource wrappers therefore make close
synchronous even when their ordinary I/O methods can suspend. A custom Drop
implementation must be safe to run during early return and error propagation.
See Traits for declarations, bounds, and associated types, and Implementations for coherence and method resolution.