Skip to content

own passes: split into per-analysis files, pin the review's missing tests - #667

Merged
ASDAlexander77 merged 25 commits into
mainfrom
own-passes-split
Oct 23, 2026
Merged

ASDAlexander77 merged 25 commits into
mainfrom
own-passes-split

Conversation

@ASDAlexander77

Copy link
Copy Markdown
Owner

Behaviour-preserving cleanup of the -mm=own passes, plus the missing test pins, from the own-raytrace final review (I1, I2, M1, M2, M4, M5, M9) and rulings follow-ups 15-23. No program changes from accepted to rejected or back.

Tests

  • own_err_global_kept_typeof pins the keep backstop in checkGlobalRead ("kept where its end at an assignment ... cannot be checked"). It has teeth: with only that error silenced, the program compiles.
  • own_err_record_literal_nested and own_err_record_literal_let_field pin the §21.2 object-literal message.
  • 191 negatives now pin :line:col: error: <message> instead of a tail several errors share (M1). Without --di every local is named 'this value', so names match as '[^']*'. Left alone: three whose text is in a note, and own_err_generator_yields_borrow (reported at a synthetic location).
  • The ThisVirtualSymbolRefOp branch of vtableWritten gets a comment instead of a test: MLIRGen makes that op only for methods, with a bound-function result, so no source program reaches it, and tslang takes no .mlir input.

Code

  • M4: the @lends index >= 64 error names the parameter ('@lends' of 'K.pick' names 'p63', ...) instead of its argument number.
  • I2: the five place-to-base walkers use one own_facts::placeBase; the nine MLIRTypeHelper constructions go through one typeHelper(ctx).
  • I1: analyze, placeOnUnmovedEdges and collectInterfaceFamilies are broken into named steps. Then each pass's class moves into a private header (own_signature, own_inference) with its comments, and its methods into one file per analysis: 7 for OwnershipSignaturePass, 10 for OwnershipInferencePass. Each split commit is a pure move, checked as line multisets, and builds on its own.

Verification (Windows, Release)

Notes

🤖 Generated with Claude Code

ASDAlexander77 and others added 25 commits October 23, 2026 13:13
…il negatives

- own_err_global_kept_typeof: `k.w = M.w` with `k: typeof M` reaches checkGlobalRead's keep
  backstop alone (teeth: with that rejection silenced the program compiles). Spec 25 now says
  the rule is a backstop and names its one known shape.
- own_err_record_literal_nested / own_err_record_literal_let_field pin the spec 21.2
  object-literal message, unpinned since T7; the 21.2 row names them.
- M1: 191 negatives whose regex matched only a shared tail (a `.*`, no quoted name, or the
  same text as another case) now pin `:line:col: error: <message>` from the baseline binary.
  Names are matched as '[^']*': without --di every local is named by nameAt's fallback
  'this value'. Left as they were: three whose text is in a note, and
  own_err_generator_yields_borrow, whose error sits at a synthetic location (12:1025).
- vtableWritten: a comment that MLIRGen makes ts.ThisVirtualSymbolRef only for methods (a
  bound function, never a !ts.ref), so no program reaches that branch and no test can.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
"'@Lends' of 'K.pick' names its argument 64" counted the receiver, which the user never
wrote; it now names the parameter as `@lends` did, from the function's declared parameter
names: "'@Lends' of 'K.pick' names 'p63', but a method's '@Lends' can name only its first 64
arguments, the receiver among them". Without the names it falls back to the argument number.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…onstructor (I2)

own_facts::placeBase(ref) is now the one definition of a place - a field, an element, a
handle's payload, a field through an interface - and of the value it is reached through; isPlace
is placeBase's answer. The five walkers that listed the place ops by hand (reachesSharedValue,
borrowedParam, chainOf, pathOf, reachesOutside) take the base from it and keep their own
decision per kind: a handle's payload is still "reaches outside" / "reaches a shared value",
still no parameter's for borrowedParam, still `.value` in a path. A new kind of place is now
seen by all of them.

The nine `MLIRTypeHelper mth(ctx, CompileOptions{})` constructions go through
own_facts::typeHelper(ctx), and the single ownsHeapMemory questions through
own_facts::ownsHeap(location, type). MLIRTypeHelper holds only the context and the options, so
one per loop as before.

Windows full suite 5251/5251.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
analyze (391 lines) keeps its order and reads as the steps it runs: resetFunctionState, the
classifications, collectOwnershipOps (the walk, now filling a FunctionOps of the candidates,
retains, place and global reads and keeping calls it declared as locals), checkOwnershipOps
(the owner checks; the proven values), decideRetains, giveKeptArguments, the decide/check
calls, the erase, and stripFacts. The bodies are moved as they were; SlotReceiver moves up
beside the Receivers map the steps pass. No behaviour change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
placeOnUnmovedEdges (340 lines) keeps its order and its exits and reads as its steps:
slotReleasesInBody (the slot's releases, all in the body), slotStates (the slot's state at
each block's entry and exit and before each op - the exit map is the old exitOf, folded once
over the same ops), the releases a moved value reaches, unmovedEdges (the releases placed on
the edges into the join), and noUseWhereJoined (the taint walk; it still sets joinedUse). The
bodies are moved as they were. No behaviour change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
collectInterfaceFamilies (534 lines) keeps its order and reads as its steps over an
InterfaceScan, which holds what the steps share and the function declared as locals:
readInterfaceVTables, traceInterfaceValues (the op walk, with its vtableOf / readFromClass /
onlyMakesValues helpers), openExposedInterfaces, openThroughMembers, openLooseVTables,
buildInterfaceFamilies (with isOpen), collectFieldFunctions, markInterfaceReached. The bodies
are moved as they were; InterfaceVTable moves to class scope for the scan to hold. No
behaviour change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The class moves out of its anonymous namespace into a private header (namespace own_signature),
its comments staying with the declarations, as MLIRGenImpl.h did. OwnershipSignaturePass.cpp
keeps the pass itself, the facts a signature says, the facts callers must know and their
fixpoint, drops, and the facts a library exports. The other methods stay inline in the header
until the next commits give each analysis a file of its own. A pure move: checked as line
multisets, the only lines not carried over verbatim are the declarations, the qualified
definitions and the anonymous namespace.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ss.h (I1)

Globals - what an initializer moves in, immortal globals (spec 25), globals given a borrow,
calls in a global's initializer, the globals a call may assign.

A pure move of movesIntoResult, holdsOnlyConstants, mayRunAgain, findImmortalGlobals,
moveIntoGlobals, rejectBorrowedGlobalInitializers, rejectGlobalArgumentsDropped,
ownGlobalInitializerCalls, moveIntoCallee, pinAssignedGlobals.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ePass.h (I1)

Interfaces closed in this module (G9, spec 31) - their method and field families, and the casts
that open them.

A pure move of slotField, collectFieldFunctions, valueInterfaces, anyInterfaces, functionValues,
signatureOf, castReinterpretsFunction, memberTypeInterfaces, isNullish, castMakesInterface,
slotFunction, addressOfThroughCasts, exportedWords, collectInterfaceFamilies,
readInterfaceVTables, traceInterfaceValues, openExposedInterfaces, openThroughMembers,
openLooseVTables, buildInterfaceFamilies, markInterfaceReached.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ss.h (I1)

A call resolved to its callees - class vtables and their families, imported declarations and the
C-scalar surface (spec 31).

A pure move of collectClassVTables, storageTupleOf, classVTableEntries, isClassVTableEntry,
methodName, familyOf, addDefined, addImported, scalarType, scalarSignature, scalarDeclaration,
addImportedByAddress, resolve, resolveValue, resolveFamily, isInstanceOfSlot.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rePass.h (I1)

The closed world - which functions another module can call, which escape as values, and the
families that are open.

A pure move of callableFromOutside, holdsFunction, cppClassOfMethod, addressType,
findEscapingFunctions, collectClassStorages, onlyCalled, findOpen, openFamily.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ePass.h (I1)

Generators - the iterator protocol, the fields a generator yields, and states that borrow their
arguments (phase 7b).

A pure move of isIteratorNext, findImportedStates, makesGeneratorState, storageTupleOfType,
isRecordFieldStore, findYieldedFields, findBoundedForwarders, fieldIndex, boxStoredIntoState,
calledOnlyDirectly, isParameterCell, readsParameterSlot, readsParameterField,
findBorrowingStates, readsBorrowed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…Pass.h (I1)

Callbacks (spec 33) - the functions passed for a parameter, and the facts their families agree
on.

A pure move of isFunctionValueType, onlyCalledParam, passedFunction, passedOnly,
collectCallbackFamilies, resolveCallback, shiftFacts, canReleaseParam, meetCallbacks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ss.h (I1)

Borrowing records (spec 32) - the boxes an object literal is made into, and the parameters a
record result borrows.

A pure move of classifyRecordBoxes, classifyRecordBox, recordParamsOf.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The class moves out of its anonymous namespace into a private header (namespace own_inference),
its comments staying with the declarations, as MLIRGenImpl.h did. OwnershipInferencePass.cpp
keeps the pass itself - each function analyzed, its retains decided and erased, string copies
made. The other methods stay inline in the header until the next commits give each analysis a
file of its own. A pure move: checked as line multisets, the only lines not carried over
verbatim are the declarations, the qualified definitions and the anonymous namespace.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ass.h (I1)

Closures (spec 2.5, phase 5) - captures, cells, generator state boxes and the fields they
borrow, and the slots a closure takes.

A pure move of classifyClosures, borrowingFieldsOf, isYieldedField, isBorrowingField,
classifyBorrowingFields, isBorrowingCell, isBorrowingBoxField, checkBorrowedReads,
checkBoundedResults, checkBoundedByBox, boundedUses, classifyStateBoxes, isStoreIntoState,
retainBefore, followClosure, holdsCaptures, decideClosures, movesCellAway, decideEscaping,
decideCells, decideSlot, decideSlotReceiver, takeValuesOfTheirOwn.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ePass.h (I1)

A kept parameter released where it is not moved (spec 33).

A pure move of parameterSlot, isReleasedParam, readsSlot, releaseKeptParamsAtExits, decideParam,
isReadOutOfException, keptParamLoadOf, decideSlotReceivers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…Pass.h (I1)

Locals that borrow - the borrower of a value, and every use of the borrow up to where the owner
ends; a local lent to a call and given a new value before the call takes it.

A pure move of borrowerOf, borrowWith, consumingLetOf, slotEnds, tryBorrow, collectBorrowerUses,
isAssignmentOf, passesOn, walkBorrowed, callResultIsOwn, isCalleeOperand,
checkArgumentsAssigned, closureAssigns.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ss.h (I1)

Borrowing records (spec 32).

A pure move of mayPointInto, borrowingRecordOf, classifyRecords, walkRecord, recordName,
describeRecordSource, checkBorrowingRecords, checkRecordResults.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ePass.h (I1)

Reads out of containers (spec 2.3, phase 3) - handle reads, the chain from a read to its roots,
and what may drop it.

A pure move of placeReadOf, handleReadUses, isCountedHandleRead, isCountedHandleReceiver,
isHandOff, isCountedHandOff, retainedRightBefore, collectCountedStoreReleases,
countedStoreRetain, borrowingCall, chainOf, rootEnds, rootSources, derivedFrom, dropsChain,
checkPlaceRead, keptParamOutlives, checkReturnedParam.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…cePass.h (I1)

A read of a mortal global, ended at the global's assignment, and the locals that hold it (spec
25).

A pure move of borrowHolderOf, holderRenewals, pathsMeet, isGlobalRead, checkGlobalRead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
….h (I1)

Moves - the one taker of a fresh value, the retains that are its bookkeeping, and the paths that
use it after the move.

A pure move of slotHoldsInitializerAt, retainedValue, ownsHeap, holdsConstantsOrMoves,
recordRetainOf, isBuiltArrayRead, isBuiltArrayReturned, onlyRetainSlotOf, isResultSlot,
recordRetainOfStore, isImmortalLiteral, isBorrow, isBoundForCall, isKeptArgument,
checkValueMoves, checkReleasedOnce, movesOf, callGivenAgain, takerLoops, reachableAfter,
orderedInBody, takerOf, soleUser, twinReadAfter, checkSlotMove.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ncePass.h (I1)

A move on some paths only (spec 30) - the release placed on the edges where the paths that did
not move join the ones that did.

A pure move of isJoined, carriesPointer, reachableFrom, handlerBlocks, placeOnUnmovedEdges,
slotReleasesInBody, slotStates, unmovedEdges, noUseWhereJoined, placeEdgeReleases,
slotAssignments, readUsedAfter.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rencePass.h (I1)

Reads after a move, through the new owner (spec 29).

A pure move of onlyReadThroughOwner, isReadAfterMove, destinationChain, readsThroughOwner,
acquirePoint, takerAcquires.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…cePass.h (I1)

Names and diagnostics - what a value, a place or a call is called in an error, and the errors
themselves.

A pure move of describeCall, calleeName, describePlace, pathOf, fieldName, ownerName, varName,
nameAt, describe, reportSecondReference, reportShapeOfSecondReference, paramName, isReturned,
otherReturn, noteLostFacts, reportKeptOnSomePaths, reportHandleInOwningUnion, printed,
reportGivenNotOwned, reportUseAfterMove, reportMovedInLoop, reportBorrowOutlives,
reportPlaceBorrowOutlives, reportPlaceBorrowerAssigned, reportPlaceBorrowEscapes,
reportMovedWhileBorrowed, reportBorrowEscapes, reportBorrowerAssigned,
reportEscapingCellNotOwned, reportUsedAfterEscapingCapture, reportClosureOutlives,
reportCaptureNotOwned, reportCapturedParamAssigned, reportMovedOnSomePaths.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ASDAlexander77
ASDAlexander77 merged commit 144528a into main Oct 23, 2026
2 checks passed
@ASDAlexander77
ASDAlexander77 deleted the own-passes-split branch October 23, 2026 12:43
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.

1 participant