Skip to content

rubyspec shim: a nested describe can see the helpers of the one around it (+28) - #624

Merged
tannevaled merged 1 commit into
mainfrom
wave25/shim
Sep 21, 2026
Merged

tannevaled merged 1 commit into
mainfrom
wave25/shim

Conversation

@tannevaled

Copy link
Copy Markdown
Contributor

Refs #621.

The shim runs each describe block with instance_eval, so a helper written with def inside the block lands on that context object's singleton. A nested describe runs on a different object and could not see it.

It was the harness, not the VM

core/string/valid_encoding/utf_8_spec.rb paid the whole bill — its examples call an outer def utf8, so all 28 raised NoMethodError. The proof it was ours: the file scored 0/28 under MRI 4.0.5 too, run through the same shim. With this change both engines score 28/28.

Why explicit forwarding and not method_missing

The first attempt added a method_missing to SpecContext that forwarded to the parent. It fixed utf_8_spec and broke two other files:

language/send_spec.rb        69 -> 67
core/random/bytes_spec.rb     9 -> 8

language/send_spec asserts by name that method_missing does not appear in the backtrace of a genuinely missing method:

expected "…/spec_helper.rb:0:in 'method_missing'" not to include?("method_missing")

A method_missing on the context object puts a shim frame in exactly the backtrace that spec is inspecting. Forwarding only the helpers that already exist leaves a missing method raising from the caller, untouched — and both files return to their previous counts.

Measurement

One binary, built from main, used for both runs, so the shim is the only difference. Whole pinned corpus, per file:

passing
old shim 20905
new shim 20936

Per-file, exactly two files move and both upward:

core/string/valid_encoding/utf_8_spec.rb    0 -> 28
core/module/autoload_spec.rb               54 -> 57

28 of the 31 are attributable; the other 3 are autoload_spec, the file that crashes intermittently (#615), so they are run-to-run noise rather than a second win.

Note for whoever bumps FLOOR next

This raises the ruby/spec total without improving the VM — it removes harness noise that was being counted as VM failure. A floor bump that includes it should say so, or the number will later be read as conformance work.

🤖 Generated with Claude Code

…d it

The shim runs each describe block with instance_eval, so a helper written with
`def` inside the block lands on THAT context object's singleton. A nested
describe runs on a different object and could not see it.

core/string/valid_encoding/utf_8_spec.rb paid the whole bill: its examples call
an outer `def utf8`, so all 28 raised NoMethodError. The file scored 0/28 under
MRI 4.0.5 as well, run through the same shim — this was our harness, not a VM
gap. With the fix both engines score 28/28.

Each existing helper is forwarded explicitly to the enclosing context rather
than routed through a method_missing. That distinction is not cosmetic: a
method_missing on SpecContext puts a shim frame in the backtrace of a genuinely
missing method, and language/send_spec asserts by name that method_missing does
NOT appear there. The first attempt did exactly that and cost send_spec two
examples and core/random/bytes_spec one; forwarding only methods that exist
leaves a missing method raising from the caller, untouched.

Measured over the whole pinned corpus with ONE binary built from main, so only
the shim differs: 20905 -> 20936 passing. 28 of the 31 are utf_8_spec; the other
3 are core/module/autoload_spec, the file that crashes intermittently (#615),
so they are noise rather than a second win.

Refs #621.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@tannevaled
tannevaled merged commit 1c14a39 into main Sep 21, 2026
7 checks passed
@tannevaled
tannevaled deleted the wave25/shim branch September 21, 2026 19:22
tannevaled added a commit that referenced this pull request Sep 23, 2026
Seven units since the last bump:

  #617  core/process: spawn, exec, the rlimits, priorities, process groups,
        kill, the wait family                     (pass 20 -> 165)
  #618  core/kernel + core/string: require_relative with an absolute path,
        the require/load argument contract, LoadError#path, byteindex/
        byterindex, split, chop/chars/each_char   (kernel 233 -> 184,
                                                   string 179 -> 153 failing)
  #620  language: compound assignment evaluation order, the flip-flop
        operator, magic-comment encodings, loop break values
                                                  (pass 1308 -> 1443)
  #622  object: Float#to_s laid out by MRI's rule rather than Go's %g  (+11)
  #624  the mspec shim: a nested describe can see the helpers of the one
        around it                                                     (+28)
  #625  deps: parser v0.2.0                        (language +333)
  #626  compiler: for-loop targets, block-local variables, what defined?
        declares                                   (language +382)

Measured with scripts/conformance/rubyspec/run.sh against the pinned corpus at
87b1631, 16-way, TIMEOUT=25, three consecutive runs: 21749, 21750, 21750. The
floor is set nine below the lowest, the same margin rule as the last bump: it
absorbs the run-to-run jitter without being wide enough to hide the loss of a
whole spec file, which is what the ratchet exists to catch. #615 (an
intermittent frame-pop crash) is still open and can cost a file when it fires.

TWO OF THESE ARE NOT VM CONFORMANCE, and the number should not be read as if
they were. #624 fixed our own mspec shim: core/string/valid_encoding/utf_8_spec
scored 0/28 under MRI 4.0.5 too, so those 28 were harness noise counted as VM
failure. #625 is a dependency bump; the VM did not change, but thirteen
language spec files became parseable for the first time and brought 333 already-
passing examples into view. Both are real gains in what the measurement can
see, not in what the VM can do.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
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