Skip to content

feat(MachOSwiftSection): introduce ReadingContext API#84

Merged
Mx-Iris merged 21 commits intomainfrom
feature/reading-context-api
May 4, 2026
Merged

feat(MachOSwiftSection): introduce ReadingContext API#84
Mx-Iris merged 21 commits intomainfrom
feature/reading-context-api

Conversation

@Mx-Iris
Copy link
Copy Markdown
Member

@Mx-Iris Mx-Iris commented May 3, 2026

Summary

  • Wire ContextProtocol and ContextWrapper so ReadingContext flows through MachO descriptor reads
  • Close ReadingContext gaps in partial files
  • Note that ResilientWitness.implementationAddress is MachO-only
  • Add fixture-based test coverage design notes

Test plan

  • swift test --filter MachOSwiftSectionTests
  • swift test --filter SwiftDumpTests
  • Verify ReadingContext flows correctly through both MachOFile and MachOImage paths

Mx-Iris added 16 commits May 2, 2026 19:06
Scopes a focused completion pass to add ReadingContext-based overloads to
the ~45 model files in Sources/MachOSwiftSection/Models/ that currently
expose only MachO and InProcess APIs. Adds a single ReadingContext
extension `runtimePointer(at:)` to express runtime-pointer-returning
methods (e.g. `metadataAccessorFunction`) under the unified abstraction.
Implementation plan for the design doc at
docs/superpowers/specs/2026-05-02-reading-context-api-design.md.
Twelve tasks: one infrastructure (runtimePointer extension), nine
content batches (per sub-directory), and two wrap-up tasks
(ContextWrapper.forContextDescriptorWrapper, partial-file audit).
Default returns nil. MachOContext returns machO.ptr + address when the
underlying reader is a MachOImage; InProcessContext returns the address
itself. Enables runtime-pointer-returning methods (e.g.
metadataAccessorFunction) to be expressed under the unified ReadingContext
abstraction without per-call type dispatch.
Mirror the MachO init(descriptor:in:) overloads on AnonymousContext,
ModuleContext, and ExtensionContext under the ReadingContext abstraction.
Mirror the MachO overloads on Class, ClassDescriptor, the AnyClassMetadata
and FinalClassMetadata protocols, and the Method*Descriptor types. Call
sites pass the context through to nested methods so the unified path is
end-to-end.
Mirror init(descriptor:in:) and metadata helpers on Enum, Struct,
EnumMetadataProtocol, StructMetadataProtocol, and
MultiPayloadEnumDescriptor.
…tors

Mirror MachO overloads on TypeContextDescriptor, TypeContextWrapper,
TypeReference, and ValueMetadataProtocol. Add the missing
fieldDescriptor(in:context:) and metadataAccessorFunction(in:context:)
overloads on TypeContextDescriptorProtocol — the latter uses the new
runtimePointer(at:) extension to return the function pointer for
InProcess and MachOImage contexts and nil for MachOFile.

Also retarget EnumMetadataProtocol.enumDescriptor and
StructMetadataProtocol.structDescriptor to call descriptor(in:context:)
now that the helper exists.
…nce types

Mirror MachO overloads on Protocol, ProtocolDescriptor, ProtocolDescriptorRef,
ProtocolRecord, ProtocolRequirement, ResilientWitness, GlobalActorReference,
ProtocolConformance, and ProtocolConformanceDescriptor.

Also adds GenericRequirement.init<Context> and ObjCProtocolPrefix.name<Context>
upfront, since Protocol.init<Context> and ProtocolDescriptorRef.name<Context>
require them. (GenericRequirement was scheduled for Task 8 but is needed for
Task 7 to compile.)
…ociated-type

Mirror MachO overloads on FieldDescriptor, FieldRecord, and the
AssociatedType family.

GenericRequirement.init<Context> was added as a prerequisite in the
preceding protocol/conformance batch, so this batch covers only the
remaining field/associated-type files.
…/wrapper

Mirror the existing MachO-parameterized overloads on MetadataProtocol and
MetadataWrapper with sibling <Context: ReadingContext>(in:) overloads. New
methods live in `// MARK: - ReadingContext Support` extensions at the bottom
of each file.

MetadataProtocol gains:
- asMetadataWrapper(in: Context)
- asMetadata(in: Context)
- asFullMetadata(in: Context)
- valueWitnesses(in: Context)
- typeLayout(in: Context)
- typeContextDescriptorWrapper(in: Context)

MetadataWrapper gains:
- valueWitnessTable(in: Context)
- static resolve(at: Context.Address, in: Context)

The static resolve takes Context.Address directly (not an Int offset), since
the caller already produces a Context-native address.

Includes two small prerequisite mirrors (originally planned for Task 10) that
typeContextDescriptorWrapper<Context> depends on:
- ForeignClassMetadata.classDescriptor(in: Context)
- ForeignReferenceTypeMetadata.classDescriptor(in: Context)
…a types

Mirror MachO overloads on ExistentialTypeMetadata, TupleTypeMetadata,
OpaqueType, BuiltinType, and BuiltinTypeDescriptor.

ForeignClassMetadata.classDescriptor and
ForeignReferenceTypeMetadata.classDescriptor were added as prerequisites
in the preceding Metadata batch.
…ingContext

Add parent(in:context:) on ContextProtocol and ContextWrapper, and the
forContextDescriptorWrapper(_:in:context:) static factory on ContextWrapper.

These three methods were deferred from earlier batches because
forContextDescriptorWrapper(_:in:context:) depends on every concrete
Context type having an init(descriptor:in:context:) overload — and those
landed across Tasks 2, 4, 5, 6, and 7. Now that all dependencies exist,
this commit closes the dependency and completes the parent traversal API
under the unified ReadingContext abstraction.
Audit pass over the 15 files that previously had partial ReadingContext
coverage. Adds the few overloads that were missing relative to each
file's MachO API surface.
…is MachO-only

implementationAddress(in:) is a debug formatter built on
MachORepresentableWithCache.addressString(forOffset:) — a MachO display
helper with no counterpart on ReadingContext. Document the deliberate
omission in source so future audits do not re-flag it.
…pleted

Task 3 (ContextDescriptor batch) was bundled with Task 11 in commit
d5d1d74; update the plan checkboxes to reflect the completed state.
Spec describes a four-pillar test system for MachOSwiftSection/Models/:
- MachOSwiftSectionFixtureTests base (dlopen + MachOFile/MachOImage/InProcess)
- Per-method @test suites mirroring Models/ structure
- baseline-generator executable producing literal Swift expected values
- Coverage invariant via SwiftSyntax static scan + Suite reflection

Strategy: cross-reader equality + full ABI literal assertions, baselines
generated once and frozen in git, regenerated on toolchain/fixture churn.
Copilot AI review requested due to automatic review settings May 3, 2026 15:59
Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request implements comprehensive ReadingContext API coverage across the MachOSwiftSection models, providing a unified abstraction for reading Swift metadata from in-process memory and Mach-O files. It introduces the runtimePointer(at:) extension to support methods returning runtime pointers and includes design and implementation plans. Feedback points out a logic error in TypeContextWrapper.swift where return keywords are missing in a switch statement, and identifies several instances of a typo in the moduleContextDescriptor method name.

Comment on lines +66 to +73
switch typeContextDescriptorWrapper {
case .enum(let enumDescriptor):
try .enum(.init(descriptor: enumDescriptor, in: context))
case .struct(let structDescriptor):
try .struct(.init(descriptor: structDescriptor, in: context))
case .class(let classDescriptor):
try .class(.init(descriptor: classDescriptor, in: context))
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The switch statement is missing return keywords for each case. While Swift 5.9+ supports switch expressions, they must be used in a context that expects a value (like a return statement or assignment) to function as an implicit return for the method. For consistency with ContextWrapper.forContextDescriptorWrapper and clarity, explicit return statements should be added.


func genericContext<Context: ReadingContext>(in context: Context) throws -> GenericContext?
func parent<Context: ReadingContext>(in context: Context) throws -> SymbolOrElement<ContextDescriptorWrapper>?
func moduleContextDesciptor<Context: ReadingContext>(in context: Context) throws -> (any ModuleContextDescriptorProtocol)?
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Typo in method name: moduleContextDesciptor should be moduleContextDescriptor (missing 'r').

return try GenericContext(contextDescriptor: self, in: context)
}

public func moduleContextDesciptor<Context: ReadingContext>(in context: Context) throws -> (any ModuleContextDescriptorProtocol)? {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Typo in method name: moduleContextDesciptor should be moduleContextDescriptor.

}

public func isCImportedContextDescriptor<Context: ReadingContext>(in context: Context) throws -> Bool {
guard let moduleContextDescriptor = try moduleContextDesciptor(in: context) else { return false }
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Typo in method call: moduleContextDesciptor should be moduleContextDescriptor.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR completes the ReadingContext adoption across MachOSwiftSection/Models by adding <Context: ReadingContext>(in:) overloads that mirror existing MachO/InProcess APIs, plus a small runtimePointer(at:) capability to express runtime-pointer-returning methods (e.g. metadata accessors). It also adds design/plan documentation (including fixture-based test coverage notes) to guide follow-on testing work.

Changes:

  • Add ReadingContext.runtimePointer(at:) (default nil) with overrides for MachOContext (MachOImage-only) and InProcessContext.
  • Add missing ReadingContext overloads across many model types/descriptors/wrappers so context can flow end-to-end.
  • Add/expand internal design + implementation plan docs for ReadingContext coverage and fixture-based test coverage.

Reviewed changes

Copilot reviewed 57 out of 57 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
docs/superpowers/specs/2026-05-03-machoswift-section-fixture-tests-design.md New spec describing fixture-based test coverage strategy for MachOSwiftSection.
docs/superpowers/specs/2026-05-02-reading-context-api-design.md New spec for completing ReadingContext API coverage + runtimePointer(at:).
docs/superpowers/plans/2026-05-02-reading-context-api.md New detailed implementation plan for rolling out ReadingContext overloads.
Sources/MachOSwiftSection/Models/Type/ValueMetadataProtocol.swift Add descriptor(in: ReadingContext) overload.
Sources/MachOSwiftSection/Models/Type/TypeReference.swift Add resolve(at:in: ReadingContext) overload.
Sources/MachOSwiftSection/Models/Type/TypeContextWrapper.swift Add ReadingContext factory for TypeContextWrapper.
Sources/MachOSwiftSection/Models/Type/TypeContextDescriptorProtocol.swift Add fieldDescriptor(in:) + metadataAccessorFunction(in:) for ReadingContext.
Sources/MachOSwiftSection/Models/Type/TypeContextDescriptor.swift Add kind-specific descriptor accessors for ReadingContext.
Sources/MachOSwiftSection/Models/Type/Struct/StructMetadataProtocol.swift Add ReadingContext descriptor + fieldOffsets helpers.
Sources/MachOSwiftSection/Models/Type/Struct/Struct.swift Add ReadingContext initializer and parsing logic.
Sources/MachOSwiftSection/Models/Type/Enum/MultiPayloadEnumDescriptor.swift Add ReadingContext accessors for enum descriptor data.
Sources/MachOSwiftSection/Models/Type/Enum/Metadata/EnumMetadataProtocol.swift Add ReadingContext helpers for enum metadata (descriptor + payloadSize).
Sources/MachOSwiftSection/Models/Type/Enum/Enum.swift Add ReadingContext initializer and parsing logic.
Sources/MachOSwiftSection/Models/Type/Class/Method/MethodOverrideDescriptor.swift Add ReadingContext accessors for override descriptors.
Sources/MachOSwiftSection/Models/Type/Class/Method/MethodDescriptor.swift Add ReadingContext accessor for implementation symbols.
Sources/MachOSwiftSection/Models/Type/Class/Method/MethodDefaultOverrideDescriptor.swift Add ReadingContext accessors for default override descriptors.
Sources/MachOSwiftSection/Models/Type/Class/Metadata/FinalClassMetadataProtocol.swift Add ReadingContext fieldOffsets + descriptor helpers.
Sources/MachOSwiftSection/Models/Type/Class/Metadata/AnyClassMetadataObjCInterop/AnyClassMetadataObjCInteropProtocol.swift Add ReadingContext helpers for ObjC interop metadata.
Sources/MachOSwiftSection/Models/Type/Class/Metadata/AnyClassMetadata/AnyClassMetadataProtocol.swift Add ReadingContext asFinalClassMetadata(in:).
Sources/MachOSwiftSection/Models/Type/Class/ClassDescriptor.swift Add ReadingContext resilient metadata/superclass helpers.
Sources/MachOSwiftSection/Models/Type/Class/Class.swift Add ReadingContext initializer and parsing logic.
Sources/MachOSwiftSection/Models/TupleType/TupleTypeMetadata.swift Add ReadingContext tuple element reader.
Sources/MachOSwiftSection/Models/ProtocolConformance/ProtocolConformanceDescriptor.swift Add ReadingContext descriptor/type/witness accessors.
Sources/MachOSwiftSection/Models/ProtocolConformance/ProtocolConformance.swift Add ReadingContext initializer and parsing logic.
Sources/MachOSwiftSection/Models/ProtocolConformance/GlobalActorReference.swift Add ReadingContext typeName(in:).
Sources/MachOSwiftSection/Models/Protocol/ResilientWitness.swift Document MachO-only helper; add ReadingContext accessors.
Sources/MachOSwiftSection/Models/Protocol/ProtocolRequirement.swift Add ReadingContext default-implementation symbol lookup.
Sources/MachOSwiftSection/Models/Protocol/ProtocolRecord.swift Add ReadingContext protocol-descriptor resolver.
Sources/MachOSwiftSection/Models/Protocol/ProtocolDescriptorRef.swift Add ReadingContext name resolution for objc/swift protocol refs.
Sources/MachOSwiftSection/Models/Protocol/ProtocolDescriptor.swift Add ReadingContext associatedTypes(in:).
Sources/MachOSwiftSection/Models/Protocol/Protocol.swift Add ReadingContext initializer and parsing logic.
Sources/MachOSwiftSection/Models/Protocol/ObjC/ObjCProtocolPrefix.swift Add ReadingContext name(in:).
Sources/MachOSwiftSection/Models/OpaqueType/OpaqueType.swift Add ReadingContext initializer and parsing logic.
Sources/MachOSwiftSection/Models/Module/ModuleContext.swift Add ReadingContext initializer.
Sources/MachOSwiftSection/Models/Metadata/MetadataWrapper.swift Add ReadingContext metadata wrapper resolution + VWT accessor.
Sources/MachOSwiftSection/Models/Metadata/MetadataProtocol.swift Add ReadingContext metadata wrapper/metadata/full-metadata helpers.
Sources/MachOSwiftSection/Models/Generic/GenericRequirementDescriptor.swift Add ReadingContext-only comparison helper used for de-duping requirements.
Sources/MachOSwiftSection/Models/Generic/GenericRequirement.swift Add ReadingContext initializer.
Sources/MachOSwiftSection/Models/Generic/GenericContext.swift Add ReadingContext helper to compute unique requirements.
Sources/MachOSwiftSection/Models/ForeignType/ForeignReferenceTypeMetadata.swift Add ReadingContext classDescriptor(in:).
Sources/MachOSwiftSection/Models/ForeignType/ForeignClassMetadata.swift Add ReadingContext classDescriptor(in:).
Sources/MachOSwiftSection/Models/FieldRecord/FieldRecord.swift Add ReadingContext accessors for type/name fields.
Sources/MachOSwiftSection/Models/FieldDescriptor/FieldDescriptor.swift Add ReadingContext accessors for records + mangled name.
Sources/MachOSwiftSection/Models/Extension/ExtensionContext.swift Add ReadingContext initializer.
Sources/MachOSwiftSection/Models/ExistentialType/ExistentialTypeMetadata.swift Add ReadingContext helpers for superclass constraint + protocols.
Sources/MachOSwiftSection/Models/ContextDescriptor/ContextWrapper.swift Add ReadingContext factory + parent traversal.
Sources/MachOSwiftSection/Models/ContextDescriptor/ContextProtocol.swift Add ReadingContext parent traversal helper.
Sources/MachOSwiftSection/Models/ContextDescriptor/ContextDescriptorProtocol.swift Add ReadingContext requirements + implementations for module lookup / C-import checks.
Sources/MachOSwiftSection/Models/BuiltinType/BuiltinTypeDescriptor.swift Add ReadingContext typeName(in:).
Sources/MachOSwiftSection/Models/BuiltinType/BuiltinType.swift Add ReadingContext initializer.
Sources/MachOSwiftSection/Models/AssociatedType/AssociatedTypeRecord.swift Add ReadingContext accessors for name/substituted type.
Sources/MachOSwiftSection/Models/AssociatedType/AssociatedTypeDescriptor.swift Add ReadingContext accessors for type/protocol/records.
Sources/MachOSwiftSection/Models/AssociatedType/AssociatedType.swift Add ReadingContext initializer.
Sources/MachOSwiftSection/Models/Anonymous/AnonymousContext.swift Add ReadingContext initializer.
Sources/MachOReading/ReadingContext/ReadingContext.swift Add default runtimePointer(at:) extension (returns nil).
Sources/MachOReading/ReadingContext/MachOContext.swift Override runtimePointer(at:) for MachOImage-backed contexts.
Sources/MachOReading/ReadingContext/InProcessContext.swift Override runtimePointer(at:) for in-process contexts.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +53 to +55
public func replacementMethodDescriptor<Context: ReadingContext>(in context: Context) throws -> SymbolOrElement<MethodDescriptor>? {
return try layout.replacement.resolve(at: try context.addressFromOffset(offset(of: \.original)), in: context).asOptional
}
Comment on lines +19 to +20
func moduleContextDesciptor<Context: ReadingContext>(in context: Context) throws -> (any ModuleContextDescriptorProtocol)?
func isCImportedContextDescriptor<Context: ReadingContext>(in context: Context) throws -> Bool
Mx-Iris added 5 commits May 4, 2026 07:46
…irement

Declaring runtimePointer(at:) as a protocol requirement (with the existing
nil default kept in an extension) lets existential `any ReadingContext`
calls dynamic-dispatch to the concrete context's override, instead of
silently picking up the static default. Generic call sites are unchanged;
external conformers stay non-breaking thanks to the default.
…talError

MetadataWrapper.resolve previously called fatalError() when it hit
.lastEnumerated, which would crash the whole process if a future Swift
runtime introduced a new metadata kind. Replace with a typed
MachOSwiftSectionError.unknownMetadataKind, applied to all three resolve
overloads (MachO, InProcess, ReadingContext).
…scriptor

All three replacementMethodDescriptor overloads (MachO, InProcess,
ReadingContext) were resolving layout.replacement using the offset of
\.original, which reads from the wrong field given the layout's
{replacement, original, implementation} ordering.
The protocol method had a long-standing misspelling (Desciptor) that the
recent ReadingContext overload propagated into the new API surface.
Rename across all three overloads (MachO, InProcess, ReadingContext) plus
the one call site in SnapshotDumpableTests.
TypeContextWrapper used Swift 5.9+ implicit-return switch expressions
while ContextWrapper and the rest of the project use explicit return.
Switch the four affected switches to explicit return for consistency.
@Mx-Iris Mx-Iris merged commit f006467 into main May 4, 2026
2 checks passed
@Mx-Iris Mx-Iris deleted the feature/reading-context-api branch May 4, 2026 00:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants