Skip to content

Conformance Reflection

Accepted

Accepted for the V1 conformance predicate and public metadata API names.

Conformance reflection describes the resolved visible implementation for one concrete type and one fully applied semantic contract in one lookup scope.

T.conformance(C, scope) Type.Conformance!Type.ConformanceLookupError

This answers:

  • whether concrete type T visibly implements semantic contract C in scope
  • which implementation satisfies the contract
  • how each active contract operation is satisfied
  • which dependency or intersection conformances participate

It does not enumerate every conformance of a type, every implementer of a contract, hidden private implementations outside the lookup scope, structural satisfaction, or dynamic runtime conformance lookup.

Lookup API

Conformance lookup has a predicate API and a metadata API:

T.implements(C, scope: ?Scope = null) Type.Predicate

T.conformance(C, scope: ?Scope = null) Type.Conformance!Type.ConformanceLookupError

The optional scope argument defaults to null, not Scope.caller(). The called API resolves null to Scope.caller() in its body before delegating. See Predicate Reflection for scope forwarding and predicate facts.

The T.conformance(C) API and the metadata structs, enum cases, fields, and helper names shown below are frozen public V1 reflection surface.

T.implements(C) returns false when conformance is missing or ambiguous. T.conformance(C) reports structured errors for both cases.

V1 requirements:

  • T must be a concrete type.
  • C must be a fully applied semantic contract constraint.
  • C may be a normalized intersection of semantic contracts.
  • C must not be a structural constraint from satisfies(...).
  • C must not be written as dyn C; dyn C is an erased concrete object type, not a conformance lookup target.

Conformance Metadata

Type.Conformance describes the resolved visible implementation as ordinary deterministic comptime data:

The declarations in this page describe public metadata members exposed through Type. They use source-shaped const Name = struct { ... } bindings rather than invalid qualified declarations such as struct Type.Name { ... }.

const ConformanceKind = enum {
  explicit,
  compiler_builtin,
  generated,
  intersection,
}

const ConformanceGenerationReason = enum {
  base_contract,
}

const ImplDecl = struct {
  ty: Type
  contract: Type
  visibility: Visibility
  source: ?SourceLocation
  docs: ?[]const u8
  attributes: []const Type.Attribute
  origin: Type.DeclOrigin
}

const Conformance = struct {
  ty: Type
  contract: Type
  kind: Type.ConformanceKind
  visibility: Visibility
  lookup_scope: Scope

  impl_decl: ?Type.ImplDecl
  source: ?SourceLocation
  docs: ?[]const u8
  origin: Type.DeclOrigin

  components: []const Type.Conformance
  dependencies: []const Type.Conformance
  generated_from: []const Type.Conformance
  generation_reason: ?Type.ConformanceGenerationReason

  operations: []const Type.ConformanceOperation
}

kind meanings:

explicit
A visible source impl.
compiler_builtin
Compiler-owned conformance for native or language-defined behavior.
generated
Conformance materialized by language rules from visible source conformance, such as a base contract conformance implied by a derived contract impl.
intersection
Synthetic composite conformance for a normalized contract intersection.

impl_decl is the source implementation declaration when one exists. Compiler-builtin conformances and synthetic intersection conformances normally have impl_decl = null; generated conformances normally point at their inputs through generated_from.

components is used only for intersection conformances. dependencies records base contract conformances. These are separate because intersection composition and contract dependency graphs are different relationships.

generated_from is empty for explicit and compiler-builtin conformances. For generated conformances, it lists the conformance inputs that produced the result. For intersection conformances, use components, not generated_from.

Generated conformances are visible through lookup when the language says the base conformance exists. Their visibility follows the source conformance or conformances that generated them.

Conformance metadata exposes facts, not lint policy. Public API lints compute policy from visibility, lookup scope, source, generated inputs, dependencies, and operations.

Operation Metadata

In conformance reflection, an operation is a function-like or method-like callable that a contract exposes. For example, Sequence(T).len, Iterator(Item).next, and PartialEq(T).eq are contract operations.

Operations come from function declarations inside a contract body. A required function and a default method are both operations:

fn Sequence(comptime T: Type) => contract {
  fn len(self: *const Self) usize

  fn is_empty(self: *const Self) bool {
    return self.len() == 0
  }
}

Here, len is a required operation and is_empty is a default method operation. After applying the contract as Sequence(u8) for a concrete type such as Buffer, reflection records those operations with contract parameters and Self substituted into their signatures.

The applied contract surface is the final set of operations visible through that specific contract application. It includes inherited base-contract operations and excludes guarded operations whose conditions are false.

Operation rules:

  • a function declaration without a body is a required operation
  • a function declaration with a body is a default method operation
  • inherited/base contract operations keep their original declaring identity
  • guarded operations appear only when their guard is active for the applied contract and implementing type

Operations are contract-surface entries, not arbitrary functions on the concrete type. An inherent method can satisfy a required operation only through the explicit conformance rules for inherent-member fill.

operations contains the active flattened operation surface for the requested contract. Inherited or base contract operations are included, with owner identity preserved.

Inactive guarded operations are absent. Contract surface metadata may separately expose inactive guarded declarations and guard status when diagnostics need to explain why an operation is unavailable.

const ContractOperation = struct {
  declaring_contract: Type
  name: []const u8
  signature: Type.Function
  source: ?SourceLocation
  docs: ?[]const u8
}

const ConformanceOperationKind = enum {
  implementation_body,
  inherent_member_fill,
  default_method,
  compiler_builtin,
  generated,
}

const ConformanceOperation = struct {
  operation: Type.ContractOperation
  implementation: Type.FunctionDecl
  required_signature: Type.Function
  implementation_signature: Type.Function
  kind: Type.ConformanceOperationKind
}

Type.ContractOperation identifies an operation by declaration identity in the applied contract surface, not merely by name. Two base contracts with the same operation name and signature do not automatically define the same operation.

Type.ConformanceOperation is the mapping from that contract operation to the function declaration or compiler-owned behavior that satisfies it for this conformance.

Operation kinds:

implementation_body
An operation body written in the impl.
inherent_member_fill
A required operation filled from a compatible inherent member inside an explicit impl.
default_method
A contract default method used because the impl did not override it.
compiler_builtin
A compiler-owned operation mapping.
generated
An operation mapping materialized by language rules, such as generated base conformance forwarding.

For .inherent_member_fill, implementation is the inherent member declaration used to fill the required operation. This fill only occurs inside an explicit semantic implementation; it is not structural conformance.

Default methods are included because they are part of the active contract surface and can participate in static dispatch and dyn vtables. If a default is overridden, the operation kind reflects the overriding source instead.

Conformance operation mappings do not own vtable slot metadata. Dynamic dispatch metadata belongs to Dynamic Contract Metadata.

Intersections

T.conformance(A & B, scope) succeeds when T visibly implements every normalized component.

For an intersection conformance:

  • kind is .intersection.
  • contract is the normalized intersection.
  • components lists component conformances in deterministic normalized order.
  • dependencies is empty unless the intersection itself has normalized dependency facts that need exposing separately.
  • operations is the active flattened composite surface.

Missing or ambiguous component lookup fails the whole lookup with structured component errors.

Operation lookup through the composite surface follows the same ambiguity rules as static and dynamic intersection use. Same-name operations retain distinct identities unless contract composition deliberately unifies them.

Lookup Errors

Failed metadata lookup returns structured errors:

const ConformanceLookupErrorKind = enum {
  not_concrete_subject,
  not_contract_target,
  not_fully_applied_contract,
  structural_constraint_target,
  dyn_contract_target,
  missing,
  ambiguous,
  component_failed,
}

const ConformanceLookupError = struct {
  kind: Type.ConformanceLookupErrorKind
  subject: Type
  contract: Type
  scope: Scope
  candidates: []const Type.ConformanceCandidate
  component_errors: []const Type.ConformanceLookupError
}

For ambiguous, candidates includes the visible conflicting candidates. For missing, candidates may include visible near misses when sema can report them deterministically. Ordinary reflection does not expose private or non-visible impls from outside the lookup scope.

For intersection lookup, component_errors explains which component failed.

Candidates

Candidate metadata should be sufficient for diagnostics without exposing hidden impls:

const ConformanceCandidate = struct {
  contract: Type
  impl_decl: ?Type.ImplDecl
  source: ?SourceLocation
  visibility: Visibility
  origin: Type.DeclOrigin
}

Candidate lists are deterministic. They contain visible candidates by default. Privileged IDE/compiler internals may use deeper data, but that is outside ordinary Type reflection.

Built-In and Generated Conformances

Compiler-owned conformances for primitive types, arrays, slices, enums, and other language-defined behavior appear as ordinary conformance results:

  • kind = .compiler_builtin
  • impl_decl = null
  • source = null unless useful synthetic source exists
  • origin = .builtin
  • visibility is public or universal
  • operation mappings are still present

Generated conformances are distinct from compiler-builtins. They are source-driven but compiler-materialized. For example, a visible derived-contract conformance may generate visible base-contract conformances.

Boundaries

Conformance metadata does not include:

  • vtable slot metadata
  • dyn-safety status as a primary conformance field
  • law documentation copied from the contract
  • lint policy or public API stability judgments
  • private or non-visible impl candidates outside the lookup scope
  • runtime conformance lookup or sidecast metadata

Dyn safety belongs to contract surface and dynamic metadata reflection. Contract law docs belong to contract and operation metadata. Impl docs and operation docs remain available through impl_decl, docs, operation, and implementation.