Under heavy development. This site describes the intended 1.0 language. Current features and performance vary. Development status
Sn50SnThe SnAPI programming language
Development · Evolving reference

Enums

Classifies the semantic shape of a reflected type.

Sn is under heavy development. This reference includes the intended 1.0 design; features may be incomplete in the current compiler. Read the status →

Module std.reflection

import std.reflection;

Public declaration contracts and authored examples. A page can document several related symbols. Implementation bodies are excluded.

TypeKind

pub enum TypeKind

Classifies the semantic shape of a reflected type.

Example

module example.reflection;
from std.reflection import Argument, CopySlot, DestroySlot, Erase,
    EraseForeign, EraseForeignMut, FindType, FindTypeByStableId,
    InvocationFrame, Invoke, MemberQuery, MethodSignature, ParameterMode,
    ParameterSignature, PrivateAccess, ReadField, ReadProperty, RegisteredTypeAt,
    RegisteredTypeCount, ReturnMode, SlotFromStorage, TakeSlot, TypeInfo,
    TypeKind, TypeOf, WriteBorrow, WriteField, WriteProperty;

pub struct Sample {
    pub Value: i32;
    pub Total: i32 { get; set; }

    pub readonly fn Add(Amount: i32) -> i32 {
        return Value + Amount;
    }

    pub fn Reset() -> void {
        Value = 0;
    }
}
pub struct StaticSample { pub static Value: i32; }

fn SameType(Left: TypeInfo, Right: TypeInfo) -> bool {
    let LeftId = Left.StableId;
    let RightId = Right.StableId;
    return LeftId.High == RightId.High && LeftId.Low == RightId.Low;
}

fn Main() -> i32 {
    let Type = TypeOf<Sample>();
    if Type.Kind != .Struct || Type.Name != "Sample" ||
        Type.ModulePath != "example.reflection" || Type.ByteSize == 0 ||
        Type.Alignment == 0 || Type.IsOpaque {
        return 1;
    }
    if Type.BaseCount() != 0 || Type.InterfaceCount() != 0 ||
        Type.GenericArgumentCount() != 0 || Type.AttributeCount() != 0 {
        return 2;
    }
    if Type.BaseAt(0) is .Some { Value = _ } {
        return 3;
    }
    if Type.InterfaceAt(0) is .Some { Value = _ } {
        return 4;
    }
    if Type.GenericArgumentAt(0) is .Some { Value = _ } {
        return 5;
    }
    if Type.AttributeAt(0) is .Some { Value = _ } {
        return 6;
    }

    let StableId = Type.StableId;
    let StableMatch = switch FindTypeByStableId(StableId) {
        case .Ok { Value = Found } => break Found;
        case .Err { Error = _ } => return 7;
    };
    if StableMatch.StableId.High != StableId.High ||
        StableMatch.StableId.Low != StableId.Low {
        return 8;
    }
    let NamedMatch = switch FindType(Type.ModulePath, Type.QualifiedName) {
        case .Ok { Value = Found } => break Found;
        case .Err { Error = _ } => return 9;
    };
    if !SameType(NamedMatch, Type) || RegisteredTypeCount() == 0 {
        return 10;
    }
    if RegisteredTypeAt(RegisteredTypeCount()) is .Some { Value = _ } {
        return 11;
    }

    if Type.FieldCount(.Declared) != 1 ||
        Type.FieldAt(.Declared, 1) is .Some { Value = _ } {
        return 12;
    }
    let Field = switch Type.FindField("Value", .Declared) {
        case .Ok { Value = Found } => break Found;
        case .Err { Error = _ } => return 13;
    };
    if Field.Name != "Value" || !SameType(Field.DeclaringType, Type) ||
        Field.ValueType.Kind != .Integer || Field.Visibility != .Pub ||
        Field.IsStatic || !Field.IsMutable || Field.IsCompilerGenerated ||
        Field.AttributeCount != 0 ||
        Field.AttributeAt(0) is .Some { Value = _ } {
        return 14;
    }
    if Field.AutoProperty is .Some { Value = _ } {
        return 15;
    }

    if Type.PropertyCount(.Declared) != 1 ||
        Type.PropertyAt(.Declared, 1) is .Some { Value = _ } {
        return 16;
    }
    let Property = switch Type.FindProperty("Total", .Declared) {
        case .Ok { Value = Found } => break Found;
        case .Err { Error = _ } => return 17;
    };
    if Property.Name != "Total" ||
        !SameType(Property.DeclaringType, Type) ||
        Property.ValueType.Kind != .Integer ||
        Property.Visibility != .Pub || Property.Getter.IsStatic ||
        Property.IsVirtual || Property.IsOverride ||
        Property.IsSealedOverride || Property.AttributeCount != 0 ||
        Property.AttributeAt(0) is .Some { Value = _ } {
        return 18;
    }
    if (Property.Setter is .None) {
        return 19;
    }
    let BackingField = switch Property.BackingField {
        case .Some { Value = Found } => break Found;
        case .None => return 20;
    };
    if !BackingField.IsCompilerGenerated ||
        BackingField.AutoProperty is .None {
        return 21;
    }

    let ParameterTypes: ParameterSignature[1] = [
        ParameterSignature.Create(TypeOf<i32>(), .Value)
    ];
    let Signature = MethodSignature.Create(
        false,
        ParameterTypes,
        TypeOf<i32>(),
        .Value
    );
    if Signature.IsStatic || Signature.Parameters.Length != 1 ||
        Signature.Parameters[0].Mode != ParameterMode.Value ||
        !SameType(Signature.Parameters[0].Type, TypeOf<i32>()) ||
        !SameType(Signature.ResultType, TypeOf<i32>()) ||
        Signature.ResultMode != ReturnMode.Value {
        return 22;
    }
    let Method = switch Type.FindMethod("Add", Signature, .Declared) {
        case .Ok { Value = Found } => break Found;
        case .Err { Error = _ } => return 23;
    };
    if Method.Name != "Add" || !SameType(Method.DeclaringType, Type) ||
        Method.Visibility != .Pub || Method.IsStatic || Method.IsVirtual ||
        Method.IsOverride || Method.ParameterCount != 1 ||
        Method.AttributeCount != 0 || Method.ResultMode != .Value ||
        !SameType(Method.ResultType, TypeOf<i32>()) ||
        Method.AttributeAt(0) is .Some { Value = _ } {
        return 24;
    }
    let Parameter = switch Method.ParameterAt(0) {
        case .Some { Value = Found } => break Found;
        case .None => return 25;
    };
    if Parameter.Name != "Amount" || Parameter.Position != 0 ||
        Parameter.Mode != .Value ||
        !SameType(Parameter.Type, TypeOf<i32>()) ||
        Parameter.AttributeCount != 0 ||
        Parameter.AttributeAt(0) is .Some { Value = _ } {
        return 26;
    }
    if Method.ParameterAt(1) is .Some { Value = _ } ||
        Type.MethodCount(MemberQuery.Declared) < 2 ||
        Type.MethodAt(.Declared, Type.MethodCount(.Declared))
            is .Some { Value = _ } {
        return 27;
    }

    var Instance: Sample = .{ Value = 7 };
    let InstanceRef = Erase(Instance);
    if InstanceRef.Address == null || InstanceRef.Access != .Write ||
        !SameType(InstanceRef.Type, Type) {
        return 28;
    }
    let SafeRead = switch Field.Read<i32>(Instance) {
        case .Ok { Value = Copied } => break Copied;
        case .Err { Error = _ } => return 53;
    };
    if SafeRead != 7 { return 54; }
    switch Field.Borrow<i32>(Instance) {
        case .Ok { Value = View } => { if View.Get() != 7 { return 201; } }
        case .Err { Error = _ } => return 202;
    }
    var Writable = Field.BorrowMut<i32>(Instance);
    switch Writable {
        case .Ok { Value = View: mut WriteBorrow<i32>& } => { View.Get() = 7; }
        case .Err { Error = _ } => return 203;
    }

    var ResultStorage: i32 = 0;
    var ResultSlot = unsafe {
        // Safety: ResultStorage is live, exact i32 storage for this scope.
        break SlotFromStorage(
            (&ResultStorage) as! mut void*,
            TypeOf<i32>(),
            TypeOf<i32>().ByteSize,
            TypeOf<i32>().Alignment,
            .Live
        );
    };
    if ResultSlot.Address == null || ResultSlot.Capacity == 0 ||
        ResultSlot.Alignment == 0 || ResultSlot.State != .Live ||
        !SameType(ResultSlot.Type, TypeOf<i32>()) {
        DestroySlot(ResultSlot);
        return 29;
    }
    if DestroySlot(ResultSlot) != .Success ||
        ResultSlot.State != .Empty {
        return 29;
    }

    if ReadField(Field, InstanceRef, ResultSlot, .Deny) != .Success {
        return 30;
    }
    let ReadValue = switch CopySlot<i32>(ResultSlot) {
        case .Ok { Value = Value } => break Value;
        case .Err { Error = _ } => {
            DestroySlot(ResultSlot);
            return 31;
        }
    };
    if ReadValue != 7 || ResultSlot.State != .Live {
        DestroySlot(ResultSlot);
        return 32;
    }
    if DestroySlot(ResultSlot) != .Success ||
        ResultSlot.State != .Empty {
        return 32;
    }

    let Replacement: i32 = 11;
    let WriteArgument = Argument.CopyValue(Erase(Replacement));
    if WriteArgument.Mode != .CopyValue ||
        WriteField(Field, InstanceRef, WriteArgument, .Deny) != .Success ||
        Instance.Value != 11 {
        return 33;
    }
    let PublicAccess: PrivateAccess = .Deny;
    switch Field.Write<i32>(Instance, Replacement) {
        case .Ok => {}
        case .Err { Error = _ } => return 55;
    }
    switch Field.Write<i32>(Instance, Replacement, PublicAccess) {
        case .Ok => {}
        case .Err { Error = _ } => return 56;
    }
    if Instance.Value != 11 || Replacement != 11 { return 57; }
    let StaticType = TypeOf<StaticSample>();
    let StaticField = switch StaticType.FindField("Value", .Declared) {
        case .Ok { Value = Found } => break Found;
        case .Err { Error = _ } => return 58;
    };
    switch StaticField.WriteStatic<i32>(Replacement) {
        case .Ok => {}
        case .Err { Error = _ } => return 59;
    }
    switch StaticField.WriteStatic<i32>(Replacement, PublicAccess) {
        case .Ok => {}
        case .Err { Error = _ } => return 60;
    }
    if StaticSample.Value != 11 { return 61; }

    let PropertyValue: i32 = 23;
    let PropertyArgument = Argument.CopyValue(Erase(PropertyValue));
    if WriteProperty(Property, InstanceRef, PropertyArgument, .Deny) !=
        .Success || Instance.Total != 23 {
        return 34;
    }
    if ReadProperty(Property, InstanceRef, ResultSlot, .Deny) != .Success {
        return 35;
    }
    let ReflectedProperty = switch TakeSlot<i32>(ResultSlot) {
        case .Ok { Value = Value } => break Value;
        case .Err { Error = _ } => {
            DestroySlot(ResultSlot);
            return 36;
        }
    };
    if ReflectedProperty != 23 || ResultSlot.State != .Empty {
        return 37;
    }

    let Amount: i32 = 5;
    let Arguments: Argument[1] = [Argument.CopyValue(Erase(Amount))];
    var Frame = InvocationFrame.WithResult(
        InstanceRef,
        Arguments,
        ResultSlot,
        .Deny
    );
    if !Frame.HasResult || Frame.Arguments.Length != 1 ||
        Frame.Access != .Deny || Frame.Instance is .None ||
        Invoke(Method, Frame) != .Success {
        return 38;
    }
    let InvokedValue = switch CopySlot<i32>(ResultSlot) {
        case .Ok { Value = Value } => break Value;
        case .Err { Error = _ } => {
            DestroySlot(ResultSlot);
            return 39;
        }
    };
    if InvokedValue != 16 || ResultSlot.State != .Live {
        DestroySlot(ResultSlot);
        return 40;
    }
    if DestroySlot(ResultSlot) != .Success ||
        ResultSlot.State != .Empty {
        return 40;
    }

    let NoParameters: ParameterSignature[0] = [];
    let ResetSignature = MethodSignature.Create(
        false,
        NoParameters,
        TypeOf<void>(),
        .Void
    );
    let ResetMethod = switch Type.FindMethod(
        "Reset",
        ResetSignature,
        .Declared
    ) {
        case .Ok { Value = Found } => break Found;
        case .Err { Error = _ } => return 41;
    };
    let NoArguments: Argument[0] = [];
    var ResetFrame = InvocationFrame.WithoutResult(
        InstanceRef,
        NoArguments,
        .Deny
    );
    if ResetFrame.HasResult || Invoke(ResetMethod, ResetFrame) != .Success ||
        Instance.Value != 0 {
        return 42;
    }

    var DelayedSource: i32 = 9;
    let MoveArgument = Argument.MoveValue(Erase(DelayedSource));
    let ReadArgument = Argument.RefRead(Erase(Amount));
    let WriteReference = Argument.RefWrite(Erase(DelayedSource));
    let RValueArgument = Argument.RValue(Erase(DelayedSource));
    let OutArgument = Argument.Out(ResultSlot);
    if DelayedSource != 9 || MoveArgument.Mode != .MoveValue ||
        ReadArgument.Mode != .RefRead ||
        WriteReference.Mode != .RefWrite ||
        RValueArgument.Mode != .RValue || OutArgument.Mode != .Out {
        return 43;
    }

    let ForeignRead = unsafe {
        // Safety: Amount is an exact live i32 for the complete view use.
        break EraseForeign((&Amount) as! void*, TypeOf<i32>());
    };
    var ForeignValue: i32 = 3;
    let ForeignWrite = unsafe {
        // Safety: ForeignValue is writable exact i32 storage for this scope.
        break EraseForeignMut(
            (&ForeignValue) as! mut void*,
            TypeOf<i32>()
        );
    };
    if ForeignRead.Access != .Read || ForeignWrite.Access != .Write ||
        ForeignRead.Address == null || ForeignWrite.Address == null {
        return 44;
    }
    if !SameType(TypeOf(Instance), Type) {
        return 45;
    }
    let Pointer: readonly Sample* = unsafe {
        // Safety: Instance remains live throughout the pointer query.
        break (&Instance) as! readonly Sample*;
    };
    let Pointee = unsafe { break TypeOf(Pointer); };
    switch Pointee {
        case .Some { Value = Actual } => {
            if !SameType(Actual, Type) { return 46; }
        }
        case .None => return 47;
    }
    return 0;
}

TypeKind.Void

Void;

No stored value/result.

TypeKind.Bool

Bool;

Boolean primitive.

TypeKind.Integer

Integer;

Any fixed-width integer primitive.

TypeKind.Float

Float;

Any accepted floating primitive.

TypeKind.RawPointer

RawPointer;

Nullable raw pointer.

TypeKind.Reference

Reference;

Nonnull borrowed reference.

TypeKind.Array

Array;

Inline fixed array.

TypeKind.Slice

Slice;

Nonowning contiguous slice.

TypeKind.Optional

Optional;

Structural optional.

TypeKind.Tuple

Tuple;

Heterogeneous structural tuple.

TypeKind.Unique

Unique;

Canonical unique ownership wrapper.

TypeKind.Shared

Shared;

Canonical shared ownership wrapper.

TypeKind.Weak

Weak;

Canonical weak ownership wrapper.

TypeKind.Function

Function;

Callable function type.

TypeKind.Struct

Struct;

Nominal concrete struct.

TypeKind.Enum

Enum;

Closed/open/tagged enum.

TypeKind.Union

Union;

Visibly unsafe raw union.

TypeKind.Interface

Interface;

Runtime interface view/type.

TypeKind.Class

Class;

Native inline object with class construction and optional inheritance.

Visibility

pub enum Visibility

Reports authored member visibility.

Visibility.Priv

Priv;

Declaring-type-only access.

Visibility.Prot

Prot;

Declaring type and descendants.

Visibility.Internal

Internal;

Declaring package access.

Visibility.Pub

Pub;

Ordinary public access.

MemberQuery

pub enum MemberQuery

Selects declared/inherited and compiler-generated member enumeration.

MemberQuery.Declared

Declared;

Authored members declared directly on the type.

MemberQuery.DeclaredIncludingCompilerGenerated

DeclaredIncludingCompilerGenerated;

Direct authored and compiler-generated members.

MemberQuery.IncludeInherited

IncludeInherited;

Authored members including inherited members.

MemberQuery.IncludeInheritedAndCompilerGenerated

IncludeInheritedAndCompilerGenerated;

Authored/compiler-generated members including inherited members.

LookupError

pub enum LookupError

Classifies exact descriptor lookup failure.

LookupError.NotFound

NotFound;

No exact candidate exists.

LookupError.Ambiguous

Ambiguous;

More than one exact candidate remains.

AccessMode

pub enum AccessMode

Records erased-place read/write authority.

AccessMode.Read

Read;

Read-only access.

AccessMode.Write

Write;

Writable access.

ParameterMode

pub enum ParameterMode

Records one declared parameter passing mode.

ParameterMode.Value

Value;

By-value parameter.

ParameterMode.RefRead

RefRead;

Read-only reference parameter.

ParameterMode.RefWrite

RefWrite;

Writable reference parameter.

ParameterMode.RValue

RValue;

Direct rvalue-reference parameter.

ParameterMode.Out

Out;

Caller-owned output slot parameter.

ReturnMode

pub enum ReturnMode

Records one reflected callable result mode.

ReturnMode.Void

Void;

No result slot is accepted.

ReturnMode.Value

Value;

Result initializes caller-owned value storage.

ReturnMode.RefRead

RefRead;

Result is a read-only reference.

ReturnMode.RefWrite

RefWrite;

Result is a writable reference.

ValueSlotState

pub enum ValueSlotState

Tracks caller-owned reflected result/output storage lifetime.

ValueSlotState.Empty

Empty;

Storage contains no live value.

ValueSlotState.Live

Live;

Storage contains one live exact-type value.

ArgumentMode

pub enum ArgumentMode

Selects the delayed operation performed for one invocation argument.

ArgumentMode.CopyValue

CopyValue;

Copy one Copyable value at invocation.

ArgumentMode.MoveValue

MoveValue;

Select the move operation for one writable source; it stays live.

ArgumentMode.RefRead

RefRead;

Pass a read-only reference.

ArgumentMode.RefWrite

RefWrite;

Pass a writable reference.

ArgumentMode.RValue

RValue;

Pass direct rvalue-reference access.

ArgumentMode.Out

Out;

Initialize one caller-owned Empty slot.

PrivateAccess

pub enum PrivateAccess

Selects explicit private-member operation authority.

PrivateAccess.Deny

Deny;

Deny non-public operations.

PrivateAccess.Allow

Allow;

Authorize one checked non-public operation.

InvocationStatus

pub enum InvocationStatus

Reports one complete checked reflection operation outcome.

InvocationStatus.Success

Success;

Validation completed and the operation returned normally.

InvocationStatus.InvalidDescriptor

InvalidDescriptor;

Descriptor handle is malformed or stale.

InvocationStatus.NotReflected

NotReflected;

Owning module/type did not publish required metadata.

InvocationStatus.NotFound

NotFound;

Requested exact member/entry does not exist.

InvocationStatus.Ambiguous

Ambiguous;

Requested exact lookup has multiple results.

InvocationStatus.AccessDenied

AccessDenied;

Private/protected/internal authority is insufficient.

InvocationStatus.InvalidInstance

InvalidInstance;

Instance presence/type/access is invalid.

InvocationStatus.ArityMismatch

ArityMismatch;

Argument count differs from the descriptor.

InvocationStatus.TypeMismatch

TypeMismatch;

Exact semantic value type does not match.

InvocationStatus.AccessMismatch

AccessMismatch;

Writable/read-only access is insufficient or unexpected.

InvocationStatus.PassModeMismatch

PassModeMismatch;

Argument operation differs from declared pass mode.

InvocationStatus.OutputRequired

OutputRequired;

Nonvoid operation lacks a result slot.

InvocationStatus.OutputUnexpected

OutputUnexpected;

Void operation received a result slot.

InvocationStatus.OutputLive

OutputLive;

Result/output slot already contains a live value.

InvocationStatus.BadStorage

BadStorage;

Capacity, alignment, address, or slot state is invalid.

InvocationStatus.IllegalOverlap

IllegalOverlap;

Frame violates disjoint move/output/result storage rules.

InvocationStatus.UnmaterializedGeneric

UnmaterializedGeneric;

Requested generic declaration has no published closed instance.

Documentation snapshot: October 24, 2026 About versions ↗
Searching Development · language & standard library