Skip to content

Don't copy the singleton class in Proc#dup#9523

Merged
headius merged 1 commit into
jruby:masterfrom
shugo:fix-proc-dup-singleton
Jul 21, 2026
Merged

Don't copy the singleton class in Proc#dup#9523
headius merged 1 commit into
jruby:masterfrom
shugo:fix-proc-dup-singleton

Conversation

@shugo

@shugo shugo commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

procDup() passed getMetaClass() to the copy, which is the receiver's singleton class when the proc has singleton methods, so the dup unexpectedly responded to the receiver's singleton methods; MRI drops the singleton class on dup:

pr = proc { }
def pr.tag; end
pr.dup.respond_to?(:tag)  # JRuby: true, MRI: false

Pass the real class instead. Proc#clone is unaffected because cloneSetup already replaces the copy's metaclass with a clone of the receiver's singleton class, and Proc subclasses are preserved since the real class of a subclass instance is the subclass itself.

private RubyProc procDup() {
return newProc(getRuntime(), getMetaClass(), block, type, file, line);
// The real class, not the receiver's metaclass: dup must not carry the receiver's
// singleton class over to the copy (MRI drops it), and dupSetup does not reset the

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is fairly apparent from the code itself, no need for LLM generated 5 line comment (also okay if you just compress and keep these 2 lines).

# Proc#dup went through the receiver's metaclass, so a proc with singleton
# methods handed its singleton state to the dup (MRI drops it; only clone
# keeps a copy of the singleton class).
describe 'Proc#dup' do

@kares kares Jul 12, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the regression spec suite is a bit deprecated, these would make sense as ruby/spec (there might be one already, maybe it's just excluded)

@kares

kares commented Jul 12, 2026

Copy link
Copy Markdown
Member

👍 good catch

procDup() passed getMetaClass() to the copy, which is the receiver's
singleton class when the proc has singleton methods, so the dup
unexpectedly responded to the receiver's singleton methods; MRI drops
the singleton class on dup:

    pr = proc { }
    def pr.tag; end
    pr.dup.respond_to?(:tag)  # JRuby: true, MRI: false

Pass the real class instead.  Proc#clone is unaffected because
cloneSetup already replaces the copy's metaclass with a clone of the
receiver's singleton class, and Proc subclasses are preserved since
the real class of a subclass instance is the subclass itself.

Co-Authored-By: Claude Fable 5 <[email protected]>
@shugo
shugo force-pushed the fix-proc-dup-singleton branch from 6e18256 to a00577a Compare July 12, 2026 09:28
@shugo

shugo commented Jul 12, 2026

Copy link
Copy Markdown
Contributor Author

@kares Thanks for your review.

I've removed obvious comments, and have removed the regression spec.
I'll check ruby/spec later.

@headius

headius commented Jul 21, 2026

Copy link
Copy Markdown
Member

Thanks @shugo!

@headius
headius merged commit 02fd9d6 into jruby:master Jul 21, 2026
134 checks passed
@kares kares added this to the JRuby 10.1.1.0 milestone Jul 22, 2026
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.

3 participants