IMPORTANT: To view this page as Markdown, append `.md` to the URL (e.g. /docs/manual/basics.md). For the complete Mojo documentation index, see llms.txt.
Skip to main content
Version: Nightly
For the complete Mojo documentation index, see llms.txt. Markdown versions of all pages are available by appending .md to any URL (e.g. /docs/manual/basics.md).

Mojo traits cheat sheet

What each standard library trait does, when you need it, and where it bites.
v1.2.0.dev

Conforming​

Conformance syntaxdeclare, condition, or opt out of a trait

struct Meters(Comparable, Writable): ...
# unconditional conformance
struct Box[T: AnyType](Hashable where conforms_to(T, Hashable)): ...
# only when T does, usually a field or fields
struct Handle(not Movable): ...
# opt out: pinned in place
struct Lease(not Deinitable else "call 'release()'"): ...
# opt out, with a reason: linear type

A conditional conformance exists when the compiler can prove a condition: Box[Int] is Hashable, and a Box of a non-hashable type isn't.

A not Deinitable message appears in the error when a value reaches the end of scope without calling its deinitializer.

Diagnostics​

Messages after elsewhat to write when a condition or opt-out fails

def chunk[w: Int]() where w.is_power_of_two()
else "'w' must be a power of two": pass

struct Lease(
not Deinitable else "call 'release()' to return the lease"
): pass
Best practices

A compilation error says what went wrong; your else message says what to do next. The compiler appends your message, so write it as a continuation: lowercase, with no final period.

Writing else messages
After else, state what's required: 'count' must be positive.
After not Deinitable, state the method that ends the value: call 'release()'.
Put identifiers in single quotes, not backticks.
Don't restate the failure. The compiler already says what went wrong.
Use a string literal. A computed message doesn't compile.

Using this chart​

How to read this chartall the traits in one place

Trait declaration information
FeatureDescription
sourcePath to the stdlib file that defines the trait (top right)
implicitAutomatically applied by default if the type supports it (top left)
markerTrait that marks a type without requirements (top left)
refinesAn ordered list of traits that this trait builds on (after header)
< is a refinement dependency
Multiple names form trait compositions
Trait requirements

The methods or declarations required by the trait.

FeatureDescription
providedA default implementation is available
associated typeThe type declared as a comptime member
compile-time flagThe flag declared as a comptime member
no remarkThe type must implement it

Notes follow where applicable.

Lifecycle​

AnyType(implicit, marker) the root; every type conformstraits/anytype.mojo

No requirements (marker).

Deinitable(implicit) has a destructor, called at last usetraits/deinitable.mojo

SignatureRemark
__deinit__(deinit self, /)provided
comptime __del__is_trivial: Boolcompile-time flag

Automatically added to every eligible type (all fields are also Deinitable). When the type is trivial, Mojo skips the destructor. Opt out with not Deinitable to make a linear type.

Movable(implicit) relocate a value to new storagetraits/movable.mojo

SignatureRemark
__init__(out self, *, deinit move: Self)provided
comptime __move_ctor_is_trivial: Boolcompile-time flag

Every type is Movable unless it opts out. not Movable pins a value in place: it can't go to a new binding (var b = a^), out of a function (return local^), or into a container (append()). A ^ transfer that consumes the value where it is, into a var argument or a deinit method, still works.

Copyableexplicit copytraits/copyable.mojo

Refines: Movable

SignatureRemark
__init__(out self, *, copy: Self)provided
copy(self) -> Selfprovided
comptime __copy_ctor_is_trivial: Boolcompile-time flag

The copy constructor is synthesized if all fields are Copyable. Call it with .copy().

ImplicitlyCopyable(marker) lets copies be inserted implicitlytraits/copyable.mojo

Refines: Copyable < Movable

No additional requirements.

Use thoughtfully, not to save time typing .copy(). Prefer Movable or Copyable when you don't need implicit copies for function arguments, constructors, or similar contexts.

Defaultablecreate with no argumentsbuiltin/value.mojo

SignatureRemark
__init__(out self)

Reach for this when you need parameterized default-construction (TypeName()) without arguments.

RegisterPassable(marker) stored in registersbuiltin/value.mojo

Stored in registers, not memory; no stable address or identity

Refines: Movable

No requirements (marker).

No stable address: you can't take the address of self in imm-convention methods. Identifiable is meaningless for these types.

Moved trivially; all fields must also conform.

TrivialRegisterPassable(marker) copyable by moving bitsbuiltin/value.mojo

Register-passable, copyable by moving bits, no side effects.

Refines: ImplicitlyCopyable < Copyable < Movable, Deinitable, RegisterPassable

No requirements (marker).

A type whose values are treated as basic bit patterns. No constructors or destructors needed. All fields must also conform.

Format​

Writableformat itself as textformat/__init__.mojo

format itself as text; works with print(), String(), format strings
SignatureRemark
write_to(self, mut writer: Some[Writer])provided
write_repr_to(self, mut writer: Some[Writer])provided

If all fields conform, you inherit both methods through reflection.

Writercustom output targetformat/__init__.mojo

SignatureRemark
write_string(mut self, string: StringSpan)
write[*Ts: Writable](mut self, *args: *Ts)provided

Use for loggers, network streams, string builders, etc. String, FileHandle, FileDescriptor conform to Writer.

Testing​

Strategyrandom inputstesting/prop/strategy/__init__.mojo

random inputs for property-based tests

Refines: Deinitable, Movable

SignatureRemark
Value: Copyable & Deinitableassociated type
value(mut self, mut rng: Rng) raises -> Self.Value

Allows strategies to carry and advance state between draws. value() draws one sample from the random number generator.

Compare & hash​

Equatableequality; enables == and !=builtin/comparable.mojo

SignatureRemark
__eq__(self, other: Self, /) -> Boolprovided
__ne__(self, other: Self, /) -> Boolprovided

Don't use with floating-point values (use isclose()).

NaN != NaN. (See: std.utils.numerics.nan)

Mojo provides a fieldwise default. Override for caches, internal metadata, and custom behavior.

Comparableordered comparison; < > ≤ ≥, and sort()builtin/comparable.mojo

Refines: Equatable

SignatureRemark
__lt__(self, rhs: Self) -> Bool
__gt__(self, rhs: Self) -> Boolprovided
__le__(self, rhs: Self) -> Boolprovided
__ge__(self, rhs: Self) -> Boolprovided

Implement __lt__() unless it's expensive. If so, override all four.

Hashablea type that can be hashedhashlib/hash.mojo

KeyElement = Hashable + Equatable + Movable

SignatureRemark
__hash__(self, mut hasher: Some[Hasher])provided

Needed for Dict keys and Set elements.

Hasherimplements a hash algorithmhashlib/hasher.mojo

SignatureRemark
__init__(out self)
_update_with_simd(mut self, value: SIMD[_,_])
update(mut self, value: ImmSpan[Byte, _])
finish(var self) -> UInt64

Every method is required. update() takes bytes; a Hashable type feeds itself to a hasher through its own __hash__().

Identifiableidentity; same-object test, enables is / is notbuiltin/identifiable.mojo

SignatureRemark
__is__(self, rhs: Self) -> Bool
__isnot__(self, rhs: Self) -> Boolprovided

Identity is meaningless for register-passable types, which have no stable address.

Convert​

Boolable, Intable, Floatableconvert with Bool(), Int(), Float64()builtin/bool.mojo · builtin/int.mojo · builtin/floatable.mojo

Logical ("truthy") and numeric conversions
SignatureRemark
__bool__(self) -> BoolBoolable
__int__(self) -> IntIntable
__int__(self) raises -> IntIntableRaising
__float__(self) -> Float64Floatable
__float__(self) raises -> Float64FloatableRaising

Boolable unlocks use with if / while / and / or like if my_boolable_object: do_something().

Intable converts to any integer type; Floatable only to Float64. If the method can fail (Int("two")), use the Raising variant.

Math​

Absable, Powable, Roundableunary math operatorsmath/math.mojo

SignatureRemark
__abs__(self) -> SelfAbsable · abs()
__pow__(self, exp: Self) -> SelfPowable · pow(), **
__round__(self) -> SelfRoundable · round()
__round__(self, ndigits: Int) -> SelfRoundable · round(), precision

Ceilable, Floorable, Truncableround toward a boundmath/math.mojo

SignatureRemark
__ceil__(self) -> SelfCeilable · ceil()
__floor__(self) -> SelfFloorable · floor()
__trunc__(self) -> SelfTruncable · trunc()

CeilDivable, CeilDivableRaisingceiling divisionmath/math.mojo

SignatureRemark
__ceildiv__(self, denominator: Self) -> SelfCeilDivable
__ceildiv__(self, denominator: Self) raises -> SelfCeilDivableRaising

Rounds up instead of down.

DivModablecombined division and modulo; enables divmod()math/math.mojo

Refines: ImplicitlyCopyable < Copyable < Movable

SignatureRemark
__divmod__(self, denominator: Self) -> Tuple[Self, Self]DivModable

Math outlier. The tuple is (quotient, remainder).

Count and iterate​

Sized, SizedRaisinghas a length; enables len()builtin/len.mojo

SignatureRemark
__len__(self) -> IntSized
__len__(self) raises -> IntSizedRaising

Don't use with String. String lengths depend on character encoding. Ask for byte_length(), count_codepoints(), or count_graphemes() and skip Sized.

Iterableiterate by borrowingiter/__init__.mojo

SignatureRemark
IteratorType[iterable_mut: Bool, //, iterable_origin: Origin[mut=iterable_mut]]: Iteratorassociated type
__iter__(ref self) -> Self.IteratorType[origin_of(self)]

The iterator yields references tied to the source lifetime. The origin is tracked.

IterableOwnediterate by consuming and owningiter/__init__.mojo

SignatureRemark
IteratorOwnedType: Iteratorassociated type
__iter__(var self) -> Self.IteratorOwnedType

No origin tracking.

Iteratorproduces elements one at a time; the for-loop workhorseiter/__init__.mojo

Refines: Deinitable, Movable

SignatureRemark
Element: Movableassociated type
__next__(mut self) raises StopIteration -> Self.Element
bounds(self) -> Tuple[Int, Optional[Int]]provided
nth(var self, n: Int) -> Optional[Self.Element]provided

Requires an Iterable on the collection, and Iterator on the iterator. Don't rely on bounds() for safety checks; it's a hint.

Typed raise: StopIteration.

Interop​

PathLiketreat as a conforming pathos/pathlike.mojo

Represents itself as a file system path.

SignatureRemark
__fspath__(self) -> String

ConvertibleToPythoncan be sent to Pythonpython/conversions.mojo

Refines: Deinitable

SignatureRemark
to_python_object(var self) raises -> PythonObject

ConvertibleFromPythoncan be created from a Python objectpython/conversions.mojo

Refines: Copyable < Movable, Deinitable

SignatureRemark
__init__(out self, *, py: PythonObject) raises