Skip to content

fix(prelude): Pathname#/ is an alias of #+, not a forwarding def - #766

Merged
tannevaled merged 1 commit into
mainfrom
wave61-pathname-alias
Oct 4, 2026
Merged

tannevaled merged 1 commit into
mainfrom
wave61-pathname-alias

Conversation

@tannevaled

Copy link
Copy Markdown
Contributor

What

CRuby's pathname.rb writes alias / +. rbgo's prelude wrote a forwarding def
instead:

def /(other)
  self + other
end

because the parser refused the alias: after alias, a / opened a regexp
rather than naming the division method. Fixed in go-ruby-parser v0.11.1
(go-ruby-parser/parser#47), which this bumps to.

Measured — and it was not only a reflection difference

ruby 4.0.5 before after
Pathname.instance_method(:/).original_name :+ :/ :+
instance_method(:/) == instance_method(:+) true false true
with #+ redefined, Pathname.new("/a") / "b" #<Pathname:/a/b> "HIJACKED" #<Pathname:/a/b>

The third row is behaviour: an alias keeps the body it was made from, while
a forwarding def follows whatever #+ later becomes. That is the row that makes
this more than a tidy-up, and it is in the test.

Conformance

library/pathname/divide_spec.rb goes 0 → 1, which is MRI's own ceiling for
it. The file holds one example, and its title is "is an alias of Pathname#+" —
the corpus naming exactly this. The pathname library specs go 38 → 39 with
no file down.

That suite lives under library/, which the ratchet does not sweep (only
language/ and core/), so the gain is real but ungated — and nothing in
language/ or core/ moves.

Scope

A scan for the workaround's shape — an operator-named def whose body just
forwards to another operator — found one site in the prelude, this one.

How it was found

A test written to pin the parser README's claims swept CI's stdlib. CI's runner
carries Ruby 3.2, not the 4.0.5 the project targets, so it swept 66 files
instead of 47 and refused pathname.rb on alias / + — a construct valid in
every Ruby that no 4.0.5 top-level file happens to use. Fixing the lexer
upstream is what made this prelude change possible.

Green

go test ./... -count=1 -timeout=90m exit 0 (10 packages), gofmt clean,
go vet clean, GOOS=wasip1 and GOOS=js clean. The frozen prelude was
regenerated, as its drift test requires.

🤖 Generated with Claude Code

CRuby's pathname.rb writes `alias / +`. rbgo's prelude wrote

    def /(other)
      self + other
    end

because the parser refused the alias: after `alias`, a `/` opened a regexp
instead of naming the division method. That is fixed in go-ruby-parser v0.11.1
(go-ruby-parser/parser#47), which this bumps to.

The workaround was not only a reflection difference. Three things diverged,
measured against ruby 4.0.5:

    Pathname.instance_method(:/).original_name   ruby :+     before :/
    instance_method(:/) == instance_method(:+)   ruby true   before false
    with #+ redefined, `Pathname.new("/a") / "b"`
                                                 ruby #<Pathname:/a/b>
                                                 before "HIJACKED"

The third is BEHAVIOUR: an alias keeps the body it was made from, while a
forwarding def follows whatever #+ later becomes. All three now match.

Measured: library/pathname/divide_spec.rb goes 0 -> 1, which is MRI's own
ceiling for it, and the spec is one example whose title is "is an alias of
Pathname#+" -- the corpus naming exactly this. The pathname library specs go
38 -> 39 overall with no file down. That suite is under library/, which the
ratchet does not sweep (only language/ and core/), so the gain is real but
ungated; nothing in language/ or core/ moves.

The prelude was the only site with this shape: a scan for an operator-named def
whose body just forwards to another operator found one, this one.

Closes nothing; enabled by go-ruby-parser/parser#47, which was itself found by
a README-claims test sweeping CI's Ruby 3.2 stdlib.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@tannevaled
tannevaled merged commit 7bcba88 into main Oct 4, 2026
9 checks passed
@tannevaled
tannevaled deleted the wave61-pathname-alias branch October 4, 2026 19:01
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