Skip to content

Attribute Reflection

Accepted

Accepted for V1 accepted-attribute provenance and focused semantic metadata reflection.

Semantic reflection exposes semantically accepted and normalized attributes only. Normalized means resolved into semantic form; it does not mean sorted, deduplicated, or order-erased.

Unknown or invalid raw attributes are parser/AST tooling concerns, not valid type reflection metadata. The provider and evaluation model is documented in Attributes.

Attribute metadata is structured:

const Attribute = struct {
  name: []const u8
  provider: ?Type.AttributeProvider
  target_kind: Attribute.TargetKind
  args: []const Type.AttributeArg
  source: ?SourceLocation
}

const AttributeArg = struct {
  name: ?[]const u8
  source: ?SourceLocation
  source_text: ?[]const u8
}

V1 attribute names are strings. provider represents the resolved attribute provider identity when available. Type.AttributeProvider is stable identity metadata for diagnostics and tooling; its internal compiler/provider representation is not public reflection. Attribute arguments preserve optional names and provenance so future named attribute arguments can be represented without changing the metadata shape.

For accepted V1 attribute calls, AttributeArg.name is always null because named arguments are deferred to CEP-0015: Named Arguments. source_text is optional normalized source text for display and documentation; it may be null when source text is not retained or when the attribute metadata is generated.

source_text is not a semantic API, may differ from exact original source spelling, and must not be parsed by reflection consumers to recover argument values.

V1 does not expose raw normalized attribute argument values through semantic reflection. Attribute providers may still validate arguments and mutate semantic metadata through target setters. Reflection consumers should read the resulting semantic facts through focused APIs such as representation, alignment, copyability, and linkage metadata. Public Type.Value and public expression-tree reflection for attribute arguments are deferred.

Semantic Metadata

attributes() exposes accepted direct-target attribute provenance in source/evaluation order: resolved provider identity, target kind, argument source/provenance, and the attribute use site. It is not the primary query surface for the facts that attributes produce.

Only successfully applied attributes are reflected. Unknown attributes, target-kind failures, argument failures, provider hard errors, and setter hard errors are not reflected. A provider that emits notes or warnings and then completes successfully is still reflected as accepted provenance.

Attribute provenance is not inherited, propagated, or synthesized across aliases, containing declarations, type constructors, fields, parameters, contract operations, or implementation operations. An attribute on a const alias appears on the alias declaration only. An attribute on a struct_type appears on that type only. Focused semantic facts may affect the completed target, but provenance remains attached to the direct target.

Semantic facts live on the reflected target metadata they affect. V1 reflection should expose focused APIs for the current V1 attribute-produced facts:

  • representation metadata
  • alignment metadata
  • copyability metadata
  • calling-convention metadata
  • linkage/export/extern ABI metadata
  • explicit link-name metadata

For example, reflection consumers should ask a type for representation, alignment, and copyability facts rather than interpreting @repr, @align, or @resource argument provenance. This keeps semantic metadata independent of the particular attribute spelling that produced it. Provenance-only attributes such as @deprecated are the exception: V1 has no compiler-owned deprecation metadata. Lints and documentation tools inspect accepted attribute provenance directly.

Minimal V1 query shapes:

const Repr = enum {
  catalyst,
}

const Copyability = enum {
  copyable,
  forbidden,
}

const LinkageKind = enum {
  none,
  export,
  extern,
}

const Linkage = struct {
  kind: Type.LinkageKind
  abi: ?InteropAbi
  explicit_link_name: ?[]const u8
  effective_symbol_name: ?[]const u8
}

Focused target queries:

T.repr() Type.Repr!Type.ReflectionError
T.alignment() ?usize!Type.ReflectionError
T.copyability() Type.Copyability!Type.ReflectionError

field.alignment() ?usize

fn_decl.signature.callconv
fn_decl.linkage() Type.Linkage

extern_const.linkage() Type.Linkage

repr() is valid only for concrete struct types that can carry V1 representation metadata. V1 has only .catalyst; future representation modes such as .c and .packed are deferred to CEP-0063: Representation Modes and C Layout. copyability() is valid only for concrete types. T.alignment() is valid only for concrete struct types in V1, while field.alignment() reads explicit field alignment metadata. Wrong target kinds return Type.ReflectionError.

alignment() = null means no explicit minimum alignment metadata was set on that target. Layout reflection owns computed final size and alignment after representation and field layout are applied. fn_decl.signature.callconv is the resolved call ABI already represented by function signature reflection; linkage metadata describes external symbol binding, not call ABI.

For Linkage.kind = .none, abi, explicit_link_name, and effective_symbol_name are null. For exported or external declarations, abi is non-null, effective_symbol_name is the actual external symbol name after defaulting, and explicit_link_name is present only when the source used @link_name. V1 export and extern linkage use InteropAbi.c.

extern_const.linkage() names only the narrow external const-binding metadata needed by @extern(.c). V1 does not expose general const declaration reflection or namespace declaration enumeration.

Fields, inherent functions, and visible contract operations available through method lookup are distinct reflection categories:

T.fields()
T.inherent_functions()
T.visible_contract_methods(scope)

Visibility-dependent reflection takes an explicit comptime Scope value. The scope and predicate fact model is documented in Predicate Reflection.

const scope = Scope.current()

Buffer.visible_contract_methods(scope)
Buffer.implements(Sequence(f32), scope)
Buffer.satisfies(SomeShape, scope)

Structural constraints inspect inherent and source-visible shape, not contract operations available through method lookup. Structural satisfaction checks are visibility-aware: private members only count in scopes where ordinary code can access them.

Semantic conformance lookup has both a predicate API and a metadata API. Conformance Reflection owns conformance lookup, metadata, operation mappings, and lookup errors.

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

When the conformance check succeeds, the returned predicate carries an .implements fact for the checked type and contract in the checked scope.

Structural satisfaction follows the same predicate-plus-metadata pattern:

T.satisfies(Shape, scope: ?Scope = null) Type.Predicate
T.satisfaction(Shape, scope: ?Scope = null) Type.Satisfaction!Type.SatisfactionError

Structural Satisfaction Reflection owns satisfaction lookup, metadata, structural facts, and failure details.