Skip to content
La3 Docs
Browse docs

Interfaces and Generics

How La3 describes reusable APIs, explicit conformance, and type parameters.

Interfaces

An interface is a contract of method shapes, not an implicit guess based on method names.

The declaration is deliberately familiar to readers coming from TypeScript, but satisfaction is nominal rather than structural. A type conforms when there is an explicit impl block for it, which keeps the contract visible to the reader and the compiler at the same time.

  • The interface names the operations a type must provide.
  • The impl block states the promise explicitly.
  • Generics can constrain a parameter with T: Interface.
  • Multiple interfaces can be combined into a larger contract.

Impl blocks

Implementation lives near the type shape, but remains separate from the data declaration.

impl exists so the layout and the behaviour do not blur together. That matters a lot once a type has more than one constructor or several method groups that readers need to scan independently.

  • Constructors are ordinary associated functions.
  • Methods with self consume the receiver.
  • &self and &mut self borrow the receiver.
  • mut self lets a method transform its owned value before returning it.

Generics

Type parameters keep APIs reusable without hiding what concrete types still matter.

  • Type parameters are inferred when the call site makes them obvious.
  • Bounds limit what methods and operators the body can use.
  • The docs should make it clear when a generic is a readability win and when a concrete type would be better.
fn max<T: Ord>(a: T, b: T) -> T {
    if a >= b { a } else { b }
}

Bounds and borrowing

The compiler combines interface bounds with ownership checks, so the API surface needs to say both things.

  • Bounds are a type-system promise.
  • Borrowing is a lifetime and aliasing promise.
  • The docs should separate the two because they solve different reader questions.