Skip to content

Partial hardening for discovery-pass tolerance during nested object-literal method resolution#260

Merged
ASDAlexander77 merged 1 commit into
mainfrom
fix-chained-sibling-method-return
Jul 19, 2026
Merged

Partial hardening for discovery-pass tolerance during nested object-literal method resolution#260
ASDAlexander77 merged 1 commit into
mainfrom
fix-chained-sibling-method-return

Conversation

@ASDAlexander77

Copy link
Copy Markdown
Owner

Summary

Investigates (does not fully fix) the "chained sibling-method return" gap found in #259: a value-returning method can't return this.sibling(...) or let x = this.sibling(...) within the same object literal — even though calling the same sibling as a bare statement (discarding the result) works fine.

Root cause (traced via --debug-only=mlir)

An enclosing function with no explicit return type runs a speculative discovery pass (dummyRun=true/allowPartialResolve=true) to infer its return type and captured variables. That pass recurses into any nested object literal's methods, including ones unrelated to the enclosing function's own return type. A method's prototype is only registered into the literal's (mutable) storage type after its own discovery completes — so an earlier-declared sibling can still be missing from this's type when a later method's body is walked, regardless of source order.

What's fixed here (2 of ≥3 layers)

Both changes use the same dummyRun/allowPartialResolve tolerance idiom already established elsewhere in both files (mlirGenCallExpression's existing !result.value && genContext.allowPartialResolve case):

  • mlirGenPropertyAccessExpressionBaseLogic (MLIRGenAccessCall.cpp) — "Can't resolve property" now returns mlir::success() (no value) instead of hard-failing during a dummy/partial-resolve run.
  • discoverFunctionReturnTypeAndCapturedVars (MLIRGenFunctions.cpp) — "'return' is not found" is skipped (still signals non-convergence via mlir::failure(), but without emitting a diagnostic) when the outer context is itself a dummy/partial-resolve run.

What's NOT fixed

The original repro still fails — now with a bare error: failed statement and no specific diagnostic. A third, more fundamental layer remains: mlir::failure(), even without an emitted diagnostic, still propagates as a hard abort through ordinary sequential statement processing. So the nested discovery's now-silent non-convergence still aborts the entire enclosing function's discovery via a statement (let calc = {...}) that has nothing to do with that function's own return type. Fixing this needs the statement-processing layer to tolerate it too, and it's not yet known how many more call sites need the same treatment — each of the two layers fixed here needed its own separately-targeted gate.

Full mechanism and the remaining gap are documented in docs/interface-vtable-simplification-design.md for whoever picks this up next.

Test plan

Both changes verified individually and together to cause zero behavior change for the existing suite: 730/730 passed, unchanged. No regression test added — the repro this was investigating is still broken, so there's nothing passing yet to lock in.

🤖 Generated with Claude Code

…iteral method resolution

Investigates the "chained sibling-method return" gap found while extending
test coverage (a value-returning method can't `return this.sibling(...)` or
`let x = this.sibling(...)` within the same object literal, even though a
bare-statement call to the same sibling works fine).

Root-caused via --debug-only=mlir tracing: an enclosing function with no
explicit return type runs a speculative discovery pass (dummyRun=true,
allowPartialResolve=true) that recurses into any nested object literal's
methods. A method's prototype is only registered into the literal's
(mutable) storage type AFTER its own discovery completes, so an
earlier-declared sibling can still be missing from `this`'s type when a
later method's body is walked for captured-variable/return-type discovery,
regardless of source order.

Fixes two of the (at least three) layers this surfaces, both using the same
dummyRun/allowPartialResolve tolerance idiom already established elsewhere
in both files (mlirGenCallExpression's existing
`!result.value && genContext.allowPartialResolve` case):

- mlirGenPropertyAccessExpressionBaseLogic (MLIRGenAccessCall.cpp): the
  "Can't resolve property" error now returns mlir::success() (no value)
  instead of hard-failing during a dummy/partial-resolve run.
- discoverFunctionReturnTypeAndCapturedVars (MLIRGenFunctions.cpp): the
  "'return' is not found" error is skipped (still returns mlir::failure()
  to signal non-convergence, but without emitting a diagnostic) when the
  OUTER context is itself a dummy/partial-resolve run.

NOT a complete fix - the original repro still fails, now with a bare
"failed statement" and no specific diagnostic. A third, more fundamental
layer remains: mlir::failure() without an emitted error still propagates as
a hard abort through ordinary sequential statement processing, so the
nested discovery's now-silent non-convergence still aborts the whole
enclosing function's discovery via a statement (`let calc = {...}`)
entirely unrelated to that function's own return type. Full mechanism and
the remaining gap are documented in
docs/interface-vtable-simplification-design.md for whoever picks this up
next - it's not yet known how many more call sites need the same
tolerance, and each layer found so far needed a separately-targeted fix.

Both changes verified individually and together to cause zero change in
behavior for the existing suite: 730/730 passed, unchanged. No regression
test added (the repro this was investigating is still broken).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@ASDAlexander77
ASDAlexander77 merged commit a53800c into main Jul 19, 2026
2 checks passed
@ASDAlexander77
ASDAlexander77 deleted the fix-chained-sibling-method-return branch July 19, 2026 23:32
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