🌐 AI搜索 & 代理 主页
Skip to content

Conversation

@osyoyu
Copy link
Contributor

@osyoyu osyoyu commented Dec 9, 2025

This patch makes procs which meet the following condition automatically be Ractor shareable.

  • The proc itself is frozen.
  • The proc's self is Ractor shareable.

Consider this code:

class C
  PROC = proc { p 1 }.freeze
end

Ractor.new { C::PROC.call }.value

In this case, C::PROC will be automatically Ractor shareable, since its self is C, which is also Ractor shareable.

Usecase:

The main usecase in mind is procs/lambdas in class-level constants. Some libraries store procs in constants as a convenient place for library-wide logic. Those procs usually do not access unshareable state, thus conceptually safe to be shared across Ractors. However, the current limitation completely blocks this.

Examples may be found in ruby/ruby:

class Pathname
 SAME_PATHS = if File::FNM_SYSCASE.nonzero?
   # Avoid #zero? here because #casecmp can return nil.
   proc {|a, b| a.casecmp(b) == 0}
 else
   proc {|a, b| a == b}
 end
end

https://github.com/search?q=repo%3Aruby%2Fruby%20%2F(%3F-i)%5BA-Z%5D%20%3D%20(proc%7Clambda)%2F&type=code

More examples can be found in public code.

https://github.com/search?q=language%3Aruby+%2F%28%3F-i%29%5BA-Z%5D+%3D+%28proc%7Clambda%29%2F&type=code

It can be observed that a good portion of these do not access unshareable state.

Appending .freeze would be much more acceptable than redefining using Ractor.shareable_proc, which is a Ruby 4.0-only feature.

[Feature #21767]

This patch makes procs which meet the following condition automatically
be Ractor shareable.

- The proc itself is frozen.
- The proc's `self` is Ractor shareable.

Consider this code:

    class C
      PROC = proc { p 1 }.freeze
    end

    Ractor.new { C::PROC.call }.value

In this case, C::PROC will be automatically Ractor shareable, since its
self is `C`, which is also Ractor shareable.

Usecase:

The main usecase in mind is procs/lambdas in class-level constants. Some libraries store procs in constants as a convenient place for library-wide logic. Those procs usually do not access unshareable state, thus conceptually safe to be shared across Ractors. However, the current limitation completely blocks this.

Examples may be found in ruby/ruby:

    class Pathname
     SAME_PATHS = if File::FNM_SYSCASE.nonzero?
       # Avoid #zero? here because #casecmp can return nil.
       proc {|a, b| a.casecmp(b) == 0}
     else
       proc {|a, b| a == b}
     end
    end

https://github.com/search?q=repo%3Aruby%2Fruby%20%2F(%3F-i)%5BA-Z%5D%20%3D%20(proc%7Clambda)%2F&type=code

More examples can be found in public code.

https://github.com/search?q=language%3Aruby+%2F%28%3F-i%29%5BA-Z%5D+%3D+%28proc%7Clambda%29%2F&type=code

It can be observed that a good portion of these do not access unshareable state.

Appending `.freeze` would be much more acceptable than redefining using `Ractor.shareable_proc`, which is a Ruby 4.0-only feature.

[Feature #21767]
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