Skip to content

Add null safety #32

@synapticvoid

Description

@synapticvoid

Design

T? is a built-in first-class optional type — same relationship as E!T to Result[E, T]. It is not sugar over a generic Option[T].

fn find(id: Int) User?
    
let user: User? = find(42)
let name = user orelse "unknown"

Unwrapping

  • orelse — provide a default: x orelse fallback
  • when — pattern match: when x { value(v) => ..., null => ... }

Rules

  • null literal is only valid where a T? type is expected — no untyped null
  • T widens to T? automatically (non-null is always a valid optional)
  • Assigning T? where T is expected is a type error — must unwrap explicitly

Implementation notes

Mirrors the E!T system:

  • PipeTypeAnnotation: add optional: *PipeTypeAnnotation
  • PipeType: add optional: *PipeType
  • Parser: postfix ? on type annotations; orelse infix expression
  • Type checker: enforce null only in optional positions; track unwrap
  • Interpreter: Value.null already exists, just needs type gating

Timing

Add after generics are settled — T? being built-in avoids the T? vs Option[T] design knot entirely, same as E!T vs Result[E, T]. Safe to defer as long as no null literal is exposed in the syntax before this lands.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions