Manuscript Documentation
v0.1.0

Type checking and source contracts#

The type checker decides whether source operations satisfy Manuscript’s rules before the compiler generates Go. The fact that a value can be represented in Go does not make every use of it legal in Manuscript.

Required checks#

Accept source according to the normative grammar ; then resolve names and check the compatibility rules . Each rejected program must identify the violated source rule. Backend assignability and Go compiler acceptance are not substitutes for those checks.

Source ruleChecker responsibility
Explicit function signaturesCheck parameter and result types against calls and returns
Names and scopesCollect module signatures, reject duplicate names, resolve locals in declaration order, and check assignments against fixed mutable binding types
OperatorsUse the closed precedence and operand table; enforce Bool conditions and short-circuit evaluation without implicit numeric conversion
Function valuesPreserve parameter labels/order and exact types; require explicit specialization of generic function values and contextual anonymous parameter types and inferred anonymous results
Return completenessAllow Unit fallthrough/bare returns; reject reachable non-Unit fallthrough; track Never and function-local loop/return boundaries
Argument labelsResolve optional labels and positional arguments left to right to unfilled parameters, preserving matching-name shorthand; apply the same rule to constructors, methods and function values; reject unknown labels, duplicate arguments, excess positional arguments, and missing required arguments
List literalsUse the canonical standard List from the prelude; check homogeneous element types and use annotations or the expected parameter type for empty lists
Typed tasksInfer Task[T] from the ordinary generic start signature; check each join against Result[T, ExecutionError]
Destructuring bindingsCheck positional arity, record fields, renaming, nesting, and duplicate bindings; infer each local’s type independently; see destructuring bindings
Nominal records and tagged alternativesPreserve type identity and check declared fields and cases
Expected typesPropagate known result context through literals, fields, parentheses, and generic calls; reject ambiguous or conflicting inference
Exhaustive matchCheck the scrutinee alternative, positional payload arity/bindings, exact qualified cases, missing alternatives, duplicate arms, and final nonredundant wildcard
Generic boundsCheck arity, invariant arguments, argument and expected-result inference, every nested application’s bounds, and generic bodies under their declared assumptions
Recursive types and specializationPermit direct and mutual recursive data; reject expanding generic type/function specialization, including signature references, mutual calls, and specialized function values
Equality and hashingDerive only the specified properties; reject Float/collection keys and data containing ineligible components
Explicit implementationsMatch substituted operation names/labels/order/types exactly, check generic bodies and receiver-determined parameters, reject overlap ignoring bounds, enforce module-local extension visibility, and require explicit contract views
Standard bindingsResolve the minimal intrinsic prelude and explicit standard imports by canonical identity; check ordinary function signatures and exact contract views. Passing values requires no sharing bound; queue synchronization is the caller’s responsibility
Public signaturesReject internal nominal types leaking through exported fields, signatures, bounds, or operation surfaces
IterationAdmit List/Set/Map only, bind fixed iteration names for elements/MapEntry references, evaluate iterable once, and reject loop control outside the current function’s loops
Result propagationRecognize the canonical standard Result identity; require the same exact error type at a try expression in the current function; do not infer missing operand type arguments backward
String literalsValidate escape/scalar syntax, support universal value conversion, and preserve left-to-right evaluation

These requirements derive from the core language guide , with accepted and rejected modules in core conformance . The rules specify observable inference and compatibility; checker data structures and internal pass organization remain implementation choices. A module-level test body is a zero-parameter Unit function for static checking: ordinary local scopes, bare-return/fallthrough rules, and Result propagation restrictions apply. Test discovery and runner execution remain separate tooling contracts.

Type information feeds typed IR and generated representations .