mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-10-08 03:08:13 +00:00
fix(resolution): name-free steps were vetoed by the construction selector (#2766)
A defect I introduced two commits earlier, not a pre-existing one.
`foldReceiverChain` opens each step with:
if (options.constructionSyntax?.selector === step.name) return undefined;
Correct as written. It became wrong the moment name-free step kinds were
added: `step.name` is `undefined` for `await` and `index`, and
`constructionSyntax?.selector` is `undefined` for any language that
declares none — so `undefined === undefined` matched EVERY name-free step
and vetoed the whole fold before it ran.
That is why subscript and await receivers minted a chain, fired the Case 0
gate, had a resolvable base binding, and still produced no edge. The fold
logic downstream was fine; nothing downstream ever executed. Three reading
passes missed it because the line looks obviously correct — you have to
watch `step.name` be `undefined` at runtime. An instrumented run found it
immediately, which is the lesson: when captures, plumbing, payload and
gate all verify clean, stop reading and instrument.
Guarded on `step.name !== undefined`. Load-bearing, not defensive.
Shape matrix, RESOLVES 46 -> 55, VISIBLE-GAP 32 -> 23:
awaitParen now resolves in typescript, python, csharp, kotlin, dart
indexElement now resolves in typescript, cpp, go, python, rust, kotlin
Every canonical TypeScript shape now resolves, which broke the #2744
drop-recorder test: it needs a receiver that FAILS to type, and its own
comment records that `!` served until structural typing resolved it, then
await-paren served until this fix. Both were shapes the resolver merely
did not SUPPORT yet, so each improvement moved the goalposts. Re-fixtured
to an UNANNOTATED parameter — no type information exists, so no resolver
work can type it. Stable by construction rather than by
not-yet-implemented.
Verified: resolver integration + scope-resolution unit 4367 green,
typescript resolver 270 green, scope-capture unchanged (this is resolution,
not capture), callDrops unchanged at 102.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
aefb162280
commit
10d872529e
3 changed files with 29 additions and 16 deletions
|
|
@ -29,9 +29,9 @@
|
|||
"plainDeepChain": "RESOLVES",
|
||||
"optionalChain": "RESOLVES",
|
||||
"nonNullAssert": "RESOLVES",
|
||||
"awaitParen": "VISIBLE-GAP",
|
||||
"awaitParen": "RESOLVES",
|
||||
"explicitTypeArgs": "RESOLVES",
|
||||
"indexElement": "VISIBLE-GAP",
|
||||
"indexElement": "RESOLVES",
|
||||
"fourHopChain": "RESOLVES",
|
||||
"fieldReceiverCall": "RESOLVES",
|
||||
"decoratedReceiverBase": "N/A",
|
||||
|
|
@ -60,7 +60,7 @@
|
|||
"nonNullAssert": "N/A",
|
||||
"awaitParen": "N/A",
|
||||
"explicitTypeArgs": "VISIBLE-GAP",
|
||||
"indexElement": "VISIBLE-GAP",
|
||||
"indexElement": "RESOLVES",
|
||||
"fieldReceiverCall": "INVISIBLE-GAP",
|
||||
"decoratedReceiverBase": "N/A",
|
||||
"decoratedFieldType": "INVISIBLE-GAP"
|
||||
|
|
@ -72,7 +72,7 @@
|
|||
"nonNullAssert": "N/A",
|
||||
"awaitParen": "N/A",
|
||||
"explicitTypeArgs": "N/A",
|
||||
"indexElement": "VISIBLE-GAP",
|
||||
"indexElement": "RESOLVES",
|
||||
"fieldReceiverCall": "RESOLVES",
|
||||
"decoratedReceiverBase": "RESOLVES",
|
||||
"decoratedFieldType": "RESOLVES"
|
||||
|
|
@ -94,9 +94,9 @@
|
|||
"plainDeepChain": "RESOLVES",
|
||||
"optionalChain": "N/A",
|
||||
"nonNullAssert": "N/A",
|
||||
"awaitParen": "VISIBLE-GAP",
|
||||
"awaitParen": "RESOLVES",
|
||||
"explicitTypeArgs": "N/A",
|
||||
"indexElement": "VISIBLE-GAP",
|
||||
"indexElement": "RESOLVES",
|
||||
"fieldReceiverCall": "RESOLVES",
|
||||
"decoratedReceiverBase": "N/A",
|
||||
"decoratedFieldType": "RESOLVES"
|
||||
|
|
@ -118,7 +118,7 @@
|
|||
"plainDeepChain": "RESOLVES",
|
||||
"optionalChain": "INVISIBLE-GAP",
|
||||
"nonNullAssert": "VISIBLE-GAP",
|
||||
"awaitParen": "VISIBLE-GAP",
|
||||
"awaitParen": "RESOLVES",
|
||||
"explicitTypeArgs": "VISIBLE-GAP",
|
||||
"indexElement": "VISIBLE-GAP",
|
||||
"fieldReceiverCall": "RESOLVES",
|
||||
|
|
@ -144,7 +144,7 @@
|
|||
"nonNullAssert": "N/A",
|
||||
"awaitParen": "N/A",
|
||||
"explicitTypeArgs": "INVISIBLE-GAP",
|
||||
"indexElement": "VISIBLE-GAP",
|
||||
"indexElement": "RESOLVES",
|
||||
"fieldReceiverCall": "RESOLVES",
|
||||
"decoratedReceiverBase": "RESOLVES",
|
||||
"decoratedFieldType": "INVISIBLE-GAP"
|
||||
|
|
@ -168,7 +168,7 @@
|
|||
"nonNullAssert": "VISIBLE-GAP",
|
||||
"awaitParen": "RESOLVES",
|
||||
"explicitTypeArgs": "RESOLVES",
|
||||
"indexElement": "VISIBLE-GAP",
|
||||
"indexElement": "RESOLVES",
|
||||
"fieldReceiverCall": "RESOLVES",
|
||||
"decoratedReceiverBase": "N/A",
|
||||
"decoratedFieldType": "RESOLVES"
|
||||
|
|
|
|||
|
|
@ -479,7 +479,15 @@ export function foldReceiverChain(
|
|||
// first. That turned a correct edge into a WRONG one (Ruby
|
||||
// `Factory.new.run` → `Product.run`), which is the failure mode this whole
|
||||
// line of work exists to avoid. Decline and let the cascade answer.
|
||||
if (options.constructionSyntax?.selector === step.name) return undefined;
|
||||
// `step.name !== undefined` is load-bearing, not defensive. The name-free
|
||||
// step kinds (`await`, `index`) carry no name, and a language with no
|
||||
// `constructionSyntax` has no selector — so the bare equality below was
|
||||
// `undefined === undefined`, which matched EVERY name-free step and vetoed
|
||||
// the whole fold before it ran. That is why subscript and await receivers
|
||||
// minted a chain, fired the gate, and still produced no edge.
|
||||
if (step.name !== undefined && options.constructionSyntax?.selector === step.name) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// A position whose declared type named no class can only be advanced by an
|
||||
// unwrapping step. Folding an ordinary member off it would look the member
|
||||
|
|
|
|||
|
|
@ -3344,12 +3344,17 @@ export class Service {
|
|||
`,
|
||||
'main.ts': `import { Service } from './models';
|
||||
|
||||
export async function droppedCall(svc: Service): Promise<void> {
|
||||
// An await-parenthesized receiver. Structural typing does NOT cover this
|
||||
// shape — \`extractMixedChain\` reaches \`await …\`, which is not a chain node,
|
||||
// so no chain is minted and the site still reaches the drop recorder. The
|
||||
// \`!\` spelling used to serve here until structural typing resolved it.
|
||||
(await svc.getUserAsync()).save();
|
||||
export async function droppedCall(svc): Promise<void> {
|
||||
// An UNANNOTATED parameter. The chain mints fine, but the base has no type
|
||||
// binding to resolve against, so the site reaches the drop recorder.
|
||||
//
|
||||
// Third fixture for this case: \`!\` served until structural typing resolved
|
||||
// it, then the await-parenthesized form served until name-free step kinds
|
||||
// resolved that too. Both were shapes the resolver merely did not SUPPORT
|
||||
// yet, so each fix moved the goalposts. An untyped receiver carries no type
|
||||
// information at all, so no amount of resolver work can type it — which is
|
||||
// what makes it a stable choice rather than the next one to be fixed.
|
||||
svc.getUser().save();
|
||||
}
|
||||
|
||||
export function droppedWrite(svc: Service | null): void {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue