Edge Cases
This appendix documents edge cases and their expected formatting.
Empty Constructs
// Empty collections - no inner space
let empty_list = []
let empty_map = {}
let empty_tuple = ()
let empty_struct = Empty {}
// Empty function body
@noop () -> void = ()
// Empty trait
trait Marker {}
// Empty impl
impl Point: Marker {}
Single-Element Collections
// Single-element list
let single = [42]
let single_str = ["hello"]
// Single-entry map
let single_map = {"key": "value"}
// Single-element tuple (note: this is just parenthesized expression)
let not_tuple = (42)
// Single-field struct
type Wrapper = { value: int }
let w = Wrapper { value: 42 }
Very Long Single Items
// Long string - never break inside, break the binding if needed
let message =
"This is a very long string that exceeds 100 characters but we never break inside string literals"
// Long template string
let template =
`Dear {user.name}, your order #{order.id} has been shipped to {order.address}.`
// Long identifier (rare but possible)
let very_long_variable_name_that_somehow_exists_in_the_codebase = compute()
Deeply Nested Structures
// Each level breaks independently
let config = Config {
database: DatabaseConfig {
connection: ConnectionConfig {
host: "production-db.example.com",
port: 5432,
pool: PoolConfig {
min_size: 5,
max_size: 20,
timeout: 30s,
},
},
credentials: Credentials { username: user, password: pass },
},
cache: CacheConfig { host: "localhost", port: 6379 },
}
// Deeply nested calls
let result = process(
data: transform(
input: validate(
data: parse(
text: fetch(url: endpoint)?,
)?,
)?,
options: TransformOptions {
mode: Mode.Strict,
fallback: None,
},
),
)
Chains with Mixed Call Lengths
// All break once any breaks
let result = items
.a()
.b()
.very_long_method_name_that_takes_many_arguments(
first: value1,
second: value2,
third: value3,
)
.c()
.d()
Binary Expressions with Mixed Precedence
// Parentheses preserved, breaks before operators
let result = (first_value + second_value)
* (third_value - fourth_value)
/ (fifth_value + sixth_value)
// Complex boolean
let valid = (is_admin || has_permission(user, resource))
&& is_authenticated(user)
&& !is_expired(token)
Parentheses Preservation
Parentheses are required in certain positions to maintain correct parsing. See ParenthesesRule for details.
// Method receiver - parens required for complex expressions
(for x in items yield x).fold(0, acc, x -> acc + x)
(items.filter(x -> x > 0)).count()
// Call target - parens required for lambdas
(x -> x * 2)(5)
((a, b) -> a + b)(1, 2)
// Iterator source - parens required for nested for/if/lambda
for x in (for y in outer yield transform(y)) yield process(x)
for item in (if has_data then items else []) yield item
// Continue with value - parens may be needed for complex expressions
for x in items yield
if skip_condition then continue (x * 2)
else x
Function Signatures at Boundary
// Just under 100 - stays inline
@process (input: int, config: Config) -> Result<Output, Error> = do_it()
// Just over 100 - breaks
@process (
input: int,
config: Config,
) -> Result<Output, ProcessingError> = do_work()
Where Clause Combinations
// Single short constraint - inline
@sort<T> (items: [T]) -> [T] where T: Comparable = do_sort()
// Single long constraint - breaks
@process<T> (items: [T]) -> [T]
where T: Clone + Debug + Default + Printable = do_it()
// Multiple constraints
@transform<T, U, V> (a: T, b: U) -> V
where T: Clone + Into<V>,
U: Debug + Default,
V: Printable = do_transform()
Capabilities with Long Names
// Multiple capabilities fit
@fetch (url: str) -> Result<str, Error> uses Http, Logger = do_fetch()
// Capabilities break to new line
@complex_operation (input: Data) -> Result<Output, Error>
uses Http, FileSystem, Logger, Cache, Database = do_it()
Lambdas in Various Contexts
// Simple lambda in chain
items.map(x -> x * 2)
// Lambda with type annotation
items.map((x: int) -> int = x * 2)
// Lambda as standalone value
let transform: (int) -> int = x -> x * 2
// Lambda with complex body in chain
items.map(
x -> {
let doubled = x * 2
let validated = validate(doubled)
validated
},
)
// Multiple lambdas in call
combine(
first: x -> x + 1,
second: x -> x * 2,
third: x -> x - 1,
)
Match with Various Arm Complexities
// Simple arms
let result = match value {
Some(x) -> x
None -> 0
}
// Arms with guards
let result = match n {
x if x < 0 -> "negative"
0 -> "zero"
x if x < 10 -> "small"
_ -> "large"
}
// Arms with complex patterns
let result = match event {
Event.Click { x, y, button: Button.Left } -> handle_left_click(x, y)
Event.Click { x, y, button: Button.Right } -> handle_right_click(x, y)
Event.KeyPress { key, modifiers: Modifiers { ctrl: true, .. } } ->
handle_ctrl_key(key)
_ -> ignore()
}
// Arms with complex bodies
let result = match data {
Valid(content) -> {
let processed = process(content)
let validated = validate(processed)
Ok(validated)
}
Invalid(error) -> Err(error)
}
Conditionals at Boundaries
// Just fits - inline
let x = if condition then "yes" else "no"
// Slightly too long - breaks
let category =
if value > threshold then "above"
else "below"
// Complex condition that breaks
let result =
if is_valid(data)
&& has_permission(user)
&& is_within_quota(user)
then process(data)
else reject(data)
// Nested conditionals
let grade =
if score >= 90 then "A"
else if score >= 80 then "B"
else if score >= 70 then "C"
else if score >= 60 then "D"
else "F"
Import Edge Cases
// Single import
use std.math { sqrt }
// Many imports from one module - wraps
use std.collections {
BTreeMap,
BTreeSet,
HashMap,
HashSet,
LinkedList,
VecDeque,
}
// Alias
use std.net.http as http
use "./internal" { VeryLongTypeName as Short }
// Private import
use "./internal" { ::private_helper }
// Re-export
pub use "./internal" { Widget, Button, Label }
Struct Definition Edge Cases
// Empty struct
type Empty = {}
// Single field
type Wrapper = { value: int }
// Two short fields - inline
type Point = { x: int, y: int }
// Two long fields - breaks
type Range = {
start: Timestamp,
end: Timestamp,
}
// Generic struct
type Container<T> = { value: T, metadata: Metadata }
// Struct with derive
#derive(Eq, Clone, Debug, Default)
type Config = {
timeout: Duration,
retries: int,
base_url: str,
}
Sum Type Edge Cases
// All unit variants - may fit inline
type Direction = North | South | East | West
// Mixed variants
type Option<T> = Some(value: T) | None
// Complex variants - always breaks
type Expr =
| Literal(value: Value)
| Binary(left: Box<Expr>, op: BinaryOp, right: Box<Expr>)
| Unary(op: UnaryOp, operand: Box<Expr>)
| Call(func: Box<Expr>, args: Vec<Argument>)
| If(condition: Box<Expr>, then_branch: Box<Expr>, else_branch: Box<Expr>)
Tests with Multiple Targets
// Single target
@test_add tests @add () -> void =
assert_eq(actual: add(a: 1, b: 2), expected: 3)
// Multiple targets - stays on one line if fits
@test_math tests @add tests @subtract () -> void = {
assert_eq(actual: add(a: 1, b: 2), expected: 3)
assert_eq(actual: subtract(a: 5, b: 3), expected: 2)
}
// Many targets - may need to break (rare)
@test_all_operations tests @add tests @subtract tests @multiply tests @divide () -> void = {
// assertions
}
Contract Edge Cases
// Simple pre
@divide (a: int, b: int) -> int
pre(b != 0) = a / b
// Pre with message
@divide (a: int, b: int) -> int
pre(b != 0 | "divisor cannot be zero") = a / b
// Complex pre condition
@process (data: Data) -> Result<Output, Error>
pre(data.is_valid()
&& data.size() > 0
&& data.size() < MAX_SIZE
| "data must be valid and within size limits") = do_process(data)
// Both pre and post
@abs (n: int) -> int
post(r -> r >= 0) = if n >= 0 then n else -n
Trait and Impl Edge Cases
// Trait with associated type
trait Iterator {
type Item
@next (self) -> (Option<Self.Item>, Self)
}
// Trait with default implementation
trait Default {
@default () -> Self
}
// Generic impl
impl<T: Clone> Clone for Option<T> {
@clone (self) -> Self = match self {
Some(value) -> Some(value.clone())
None -> None
}
}
// Impl with where clause
impl<T, U> From<T> for Container<U>
where T: Into<U> {
@from (value: T) -> Self = Container { value: value.into() }
}
Nursery and Parallel Edge Cases
// Simple nursery
let results = nursery(
body: n -> {
n.spawn(task: fetch(url: "/a"))
n.spawn(task: fetch(url: "/b"))
},
on_error: CancelRemaining,
)
// Nursery with dynamic spawning
let results = nursery(
body: n ->
for url in urls do
n.spawn(task: fetch(url: url)),
on_error: CollectAll,
timeout: 30s,
)
// Parallel with all options
let results = parallel(
tasks: [
fetch_user(id: 1),
fetch_user(id: 2),
fetch_user(id: 3),
],
max_concurrent: 2,
timeout: 10s,
)
Comments in Various Positions
// Comment before function
// This function adds two numbers.
@add (a: int, b: int) -> int = a + b
// Comments in block
@process (data: Data) -> Result<Output, Error> = {
// First, validate the input
let validated = validate(data)
// Then transform it
let transformed = transform(validated)
// Finally, produce the result
Ok(transformed)
}
// Doc comments in correct order
// #Computes the factorial.
// @param n Must be non-negative.
// !Panics if n is negative.
// >factorial(n: 5) -> 120
@factorial (n: int) -> int = recurse(
condition: n <= 1,
base: 1,
step: n * self(n - 1),
)