Function Reflection¶
Accepted
Accepted for V1 function signature, declaration, default-expression, and implementation-compatibility reflection.
Function signature reflection is separate from function declaration reflection.
Type.Function represents the resolved function type/signature:
const Function = struct {
params: []const Type.Param
receiver: ?Type.Receiver
return_type: Type
callconv: Type.CallConv
}
Parameters include names when available, but names are non-semantic for function type identity:
const Param = struct {
name: ?[]const u8
ty: Type
binding: ?Type.BindingPattern
}
callconv records the resolved calling convention. The default is CallConv.catalyst; V1 also includes CallConv.c for C ABI calls. See Function Types and Pointers.
Parameter names and binding patterns are retained for diagnostics, documentation, tooling, and possible future named-argument or named-parameter rules. Whether names become part of public API compatibility is deferred to CEP-0015: Named Arguments.
Capabilities are not reflected as a separate semantic category. Tooling and lints infer likely capability parameters from ordinary names, types, binding patterns, structural constraints, and project policy.
All parameters are represented uniformly in params. receiver optionally classifies the first parameter when it is a receiver. This preserves ordinary function type structure while supporting method-call sugar, contract dyn-safety checks, and documentation.
Receiver classification is based on the first resolved parameter type in a type, contract, or implementation namespace, not on the parameter name. The first parameter is a receiver when its semantic form is Self, *Self, or *const Self. Parameter names such as self, this, or buffer are ordinary non-semantic binding names.
Self is available in type bodies, contract definitions, and contract implementation bodies. In an implementation body, Self means the implementing concrete type.
Receiver metadata is derived declaration metadata:
const ReceiverKind = enum {
value,
pointer,
const_pointer,
}
const Receiver = struct {
param_index: usize
kind: Type.ReceiverKind
self_type: Type
}
Receiver metadata does not affect function type equality. Receiver mutability is already represented by the first parameter type, such as *Self or *const Self.
Function type equality should be exposed because it has non-trivial rules:
Type.Function.equals(a, b) bool
Function equality compares parameter types in order, ignores parameter names and destructuring patterns, compares return_type exactly, and compares callconv exactly. Receiver metadata does not affect equality.
Contract implementation checking uses separate compatibility-style queries:
Type.Function.can_implement(required, candidate) bool
Type.Function.check_implementation(required, candidate) Type.FunctionImplementationCheck!Type.ReflectionError
can_implement answers whether a candidate implementation signature can satisfy a required contract operation signature. check_implementation returns structured details for diagnostics and tooling. These APIs allow the implementation-side relaxations documented in Implementation Declarations: narrower error set and parameter pointer/slice const relaxation.
The check result should include both accepted relaxations and failures:
const FunctionImplementationCheck = struct {
ok: bool
accepted_relaxations: []const Type.FunctionRelaxation
failures: []const Type.FunctionImplementationFailure
}
Parameter destructuring is reflected as binding metadata, not as a separate function-type dimension:
const BindingPatternKind = enum {
name,
struct_destructure,
array_destructure,
}
const BindingPattern = struct {
kind: Type.BindingPatternKind
}
The nested metadata shape should preserve enough information for diagnostics, documentation, and tooling to reconstruct which fields or positions are bound. It must not make two functions different types merely because one writes ctx: *Context and another writes { alloc, diag }: *Context.
Error returns are part of return_type, not a separate field on Type.Function. Return-type reflection exposes success and error components:
ReturnType.success_type() Type
ReturnType.error_type() ?Type
For a non-error return type, T.success_type() returns T and T.error_type() returns null.
Type.FunctionDecl represents declaration metadata:
const FunctionDecl = struct {
name: []const u8
signature: Type.Function
params: []const Type.ParamDecl
visibility: Visibility
docs: ?[]const u8
attributes: []const Type.Attribute
source: ?SourceLocation
origin: Type.DeclOrigin
success_type_was_inferred: bool
error_type_was_inferred: bool
}
Type.Function exposes resolved semantic type facts. Type.FunctionDecl preserves source spelling and inference metadata for diagnostics, tooling, and lints such as public APIs relying on inferred success or error types. Source locations are for diagnostics and navigation, not semantic identity or ordering.
Function declaration linkage metadata is total:
FunctionDecl.linkage() Type.Linkage
linkage() returns .none for ordinary functions and methods. V1 export linkage is valid only for free function definitions, so reflected methods have .none linkage in V1. Call ABI remains part of FunctionDecl.signature.callconv; linkage metadata describes external symbol binding only. Attribute Reflection owns the Type.Linkage shape.
FunctionDecl.params is aligned by index with FunctionDecl.signature.params:
const ParamDecl = struct {
param: Type.Param
attributes: []const Type.Attribute
default: ?Type.DefaultExpression
source: ?SourceLocation
}
ParamDecl.param equals the corresponding entry in signature.params. attributes contains parameter attributes. source covers the whole parameter declaration. V1 has no separate per-parameter docs field.
Default parameter values are declaration metadata, not function type identity. Defaults do not affect Type.Function.equals, contract signature compatibility, function pointer compatibility, or ABI shape, and they do not become available when calling through a function pointer.
Default expression metadata preserves provenance for declaration defaults, including function parameter defaults and struct field defaults:
const DefaultExpression = struct {
source: ?SourceLocation
source_text: ?[]const u8
}
DefaultExpression.source covers only the default expression. source_text is optional normalized source text for display and documentation. Public Type.Expr, Type.Value, and general comptime-known value reflection are deferred from V1; defaults expose source/provenance metadata, not reusable reflected expression trees or values.
Documentation metadata is nullable normalized source doc text. Comment markers are stripped and indentation is normalized according to Comments. Rendering to HTML or another presentation format is a tooling concern.
Declared fields have source locations. Synthetic or builtin fields may have source = null unless compiler or prelude metadata provides a useful location. Synthetic or builtin fields may also provide docs through compiler or prelude metadata.