DevMeeting-2025-03-13
https://bugs.ruby-lang.org/issues/21134
DateTime and location
- 2025/03/13 (Thu) 13:00-17:00 JST @ Online
Next Date
- 2025/04/15 (Tue) 16:00-19:00 JST @ Matsuyama
Announce
About release timeframe
Ordinary tickets
[Bug #21089] Missing methods on enumerators created from Enumerator::product and Enumerator::Chain (jeremyevans0)
- Is this behavior expected?
- It seems odd that it doesn’t work by default, but it does work if you call
to_enum. - Maybe we should have
to_enumcalled implicitly so that it works, unless there are performance or other reasons not to?
Preliminary discussion:
g = Enumerator.product([1, 2, 3], [4, 5, 6])
g.next #=> NoMethodError
Discussion:
- knu: It would be nice if the superclass method works also for subclasses.
- mame: The deletion seems intentional because of its performance.
- matz: This would greatly reduce the performance when introduced, which is not something welcomed.
Conclusion:
- matz: We need a method which is not that slow. Until someone tackles this problem, we want to resort to calling
to_enumexplicitly. - knu: Let me take a look at it.
[Bug #21026] def __FILE__.a; end should be a syntax error (jeremyevans0)
- I’m not sure it is worth making this a syntax error.
- Do we want to make this change?
Preliminary discussion:
def __FILE__.a # parsed
end
def (__FILE__).a
^~~~~~~~ cannot define singleton method for literals
end
def nil.a = nil; # OK
def __dir__.a = nil; # OK
Discussion:
- mame:
__FILE__generates strings each time it is evaluated, which effectively deletes the method. - akr: Isn’t it nice if we could also define methods to literals?
- matz: For instance two bignums can have different identity, but there is no way to say if a numeric literal is a bignum or not.
- shyouhei: I don’t see any benefit allowing this because no one wants to define methods to
__FILE__ - akr: it is either we should allow both, or prohibit both.
Conclusion:
- matz: Let me think about it for a while.
- nobu: the error message seems strange though.
[Bug #21016] What should massign with shareable_constant_value: experimental_everything freeze? (jeremyevans0)
- What is the desired behavior in this case?
Preliminary discussion:
- ko1: How about constantly inserting
makeshareableinsn immediately beforesetconstant? - nobu: It brings overhead
- ko1: don’t care
Discussion:
- shyouhei: what is happening?
- ko1: we simply did not implement this feature for multiple assignments.
- shyouhei: nobody practically want to combine constant assignment with massign I guess
- ko1: maybe. but we can support this.
A, b = "foo", "bar"
A, B = "foo", "bar"
Conclusion:
- ko1: let me implemt it.
[Bug #20968] Array#fetch_values unexpected method name in stack trace (jeremyevans0)
- I think this is expected behavior and not a bug.
- If we consider this a bug, how do we plan to address it as we move methods from C to Ruby?
Preliminary discussion:
- (this discussuion was from last dev meeting)
Discussion:
- matz: I still want to remove the useless information
- mame: How to fix. The chunk of
<internal:backtraces should be merged to one backtrace entry and its location (filename:lineno) should be the one of the below - mame: Not only an exception raised, but also Kernel#caller, caller_locations, etc. should be fixed
- ko1: TracePoint should not trap the events within the internal. It is practically problematic for debugger: for example, when stepping into
ary.map {}, I expect to jump to the first line of the block, but currently, it jumpes to the first line ofArray#map, which is not very useful
Conclusion:
- matz: My feeling is not changed yet
- mame: Let’s try to implement the skipping algorithm. I will give it a try after RubyKaigi (if no one tries)
[Bug #21166] Fiber Scheduler is unable to be interrupted by IO#close. (ioquatix)
The fiber scheduler provides hooks for io_read, io_write and io_wait which are used by IO#read, IO#write, IO#wait, IO#wait_readable and IO#wait_writable, but those hooks are not interrupted when IO#close is invoked. That is because rb_notify_fd_close is not scheduler aware, and the fiber scheduler is unable to register itself into the “waiting file descriptor” list. We propose to fix this issue by:
- Introducing
VALUE rb_thread_io_interruptible_operation(VALUE self, VALUE(*function)(VALUE), VALUE argument)tointernal/thread.hwhich allows us to execute a callback that may be interrupted. Internally, this registers the current execution context into the existingwaiting_fdslist before executing the callback, and removes it afterwards. - Update all the relevant fiber scheduler hooks to use
rb_thread_io_interruptible_operation, e.g.io_wait,io_read,io_writeand so on. - Introduce
VALUE rb_fiber_scheduler_fiber_interrupt(VALUE scheduler, VALUE fiber, VALUE exception)which can be used to interrupt a fiber, e.g. with anIOErrorexception. The signature of the hook in Ruby isFiber::Scheduler#fiber_interrupt(fiber, exception). - Modify
rb_notify_fd_closeto correctly interrupt fibers using the newrb_fiber_scheduler_fiber_interruptfunction.
Preliminary discussion:
- New public interface:
Fiber::Scheduler#fiber_interrupt(fiber, exception)- is it acceptable?- All other implementation hidden.
-
I would like to backport this to Ruby 3.4, 3.3 and 3.2 if possible.
- See https://github.com/ruby/ruby/pull/12839 for the proposed implementation.
Discussion:
*
Conclusion:
*
https://bugs.ruby-lang.org/issues/21141 Time#utc? does not work with a timezone object
- akr: it is by design. It returns true only when it is, say, “UTC mode”, not necessarily when it is UTC.
- nobu: I will try to improve the document
https://bugs.ruby-lang.org/issues/16993 Sets: from hash keys using Hash#key_set
- matz: I don’t see the use case. I will ask it
- akr: I wonder if the proposed patch does not handle
compare_by_identitywell
https://bugs.ruby-lang.org/issues/21143 Speficy order of execution const_added vs inherited
class C
def self.inherited(subclass)
p subclass.name
end
end
class D < C
end
- matz: I want to change the order:
inheritedshould be called beforeconst_added - nobu: When
inheritedis called, the new subclass is not named yet. Is it okay? - matz: Let’s try.
https://bugs.ruby-lang.org/issues/21155 File scoped namespace declarations as in C#
module Foo
X = 1
class Bar
X
end
end
class Foo::Bar
X # cannot find Foo::X
end
namespace module Foo
module = Foo
class = Bar < Baz
in module Foo
in class Bar < Baz
for module Foo
for class Bar < Baz
class Bar # defines Foo::Bar
X # access Foo::X
end
function (*f X).foo(s string) {
}
module Foo
X = 1
class Bar < ZZZ
class Baz < Qux
include Quux
X # This tries to find Baz::Z, Qux::X, Quux::X, Bar::X, Foo::X, ::X (not ZZZ::X)
X # In this case, Foo::X is found
end
end
end
class Foo::Bar::Baz
X # cannot access to Foo:X
end
class namespace Foo::Bar::Baz < ZZZ
# module Foo; class Bar; class Baz < ZZZ
# We want not to indent the whole code
# We want to access Foo::X simply by "X"
X
Y # Bar::Y
# end;end;end # implicitly
- mame: I like this proposal. The recent languages usually places function definition with no indentation
- matz: I don’t like it. This is inherent to the object-oriented programming. I hope the indent problem will be fixed by the namespace proposal (currently being implemented by tagomoris)
- matz: I will close this
https://bugs.ruby-lang.org/issues/21151 IO and StringIO raise FrozenError even for read-only methods
- ko1: There was a similar discussion about Thread::Queue. That was prohibited to freeze. I don’t say the same should go to IO, though.
- mame: Is there a reasonable use case where we want to freeze IO?
- no one came up such a use case
- matz: I have no strong opinion, but I don’t see any use case to freeze IO.
- nobu: Let’s prohibit freezing IO
- knu: if user-defined deep_freeze is blindly freezing all instance variables including IOs, prohibiting IO#freeze will break it.
- ko1: Personally I want to prohibit such a program
- matz: I will write a reply. I want to ask its use case/reason first.
https://bugs.ruby-lang.org/issues/20953 Array#fetch_values vs #values_at protocols
- mame: nobu please review it
https://bugs.ruby-lang.org/issues/21160 Local return from proc
def foo
yield
end
def bar
foo {
return
}
end
def foo
yield
rescue LocalJumpError
1
end
x = foo { break 2 }
p x
proc do
return next 10
end.call #=> 10 (actual: unexpected void value expression)
- matz: I will reject
https://bugs.ruby-lang.org/issues/21152 Enumerator’s #size returned by Range#reverse_each raises an exception for endless Range
- akr: I think the new behavior (raising an exception) is correct because
reverse_eachfor an endless range does not work (even start). Infinity means infinite loop. - matz: Agreed
https://bugs.ruby-lang.org/issues/21042 Add and expose Thread#memory_allocations memory allocation counters
Thread.current.memory_allocations
#=> {
# total_allocated_objects: 1,
# total_malloc_bytes: 111,
# total_mallocs: 11,
# }
GC.stat_per_current_thread
GC.stat_for_thread(Thread.current)
- ko1: It brings a little overhead. Also, I am afraid if people want more performance indexes, which may bring bigger overhead. Also, people may want per-fiber indexes next. No end.
- matz: Is this implementation-defined?
- mame: Is
Thread.current.memory_allocationsa suitable API? Should it be underGC? - matz: I am a bit positive. ko1, could you please reply to the ticket?
- ko1: ok
https://bugs.ruby-lang.org/issues/21168 Prism doesn’t require argument parentheses (in some cases) when a block is present but parse.y does
foo(
x y, z do
end
)
# currently Prism parses the above as
foo(
x(y, z) do end
)
# possible another interpretation
foo(
x(y),
z do end
)
# parse.y accepts this
foo(x y, z) # as foo(x(y, z))
foo(x do end)
# matz: I allowed the above two calls (only when one argument for "foo"), though it was a wrong decision. However, I think we cannot fix this from now
# parse.y rejects this
foo(w, x y, z)
Conclusion:
matz: I’ll reply it. I like parse.y behavior. I don’t want to allow the code any more
off-topic: the following is SyntaxError
foo(
1
,
2
)
foo(1,2,)
foo(,1,2)
a = [
, 2
, 3
]
https://bugs.ruby-lang.org/issues/21139 Prism and parse.y parses it = it differently
42.tap do
# prism
it<local> = it<special>
# parse.y
it<local> = it<local>
end
def x = 1
x = x # x = x() ?
def x(); end
def foo(x = x) # expected x=x(), but the principle was prioritized
end
- mame: I think that the principle that an identifier is interpreted as a local variable access after its assignment is strong. Should we break the principle for this theoretical case of “it”?
- matz: I changed my mind
off-topic:
- ko1: 861 assignments to
itin all rubygems. https://gist.github.com/ko1/d2c5719a5576487045676f051736d786
https://bugs.ruby-lang.org/issues/19908 Update to Unicode 15.1
- naruse: I will review the PR
https://bugs.ruby-lang.org/issues/21029 Prism behavior for defined? (;x) differs
- mame: Should
defined? (x;)be “expression”? - matz: Yes
https://bugs.ruby-lang.org/issues/21154 Document or change Module#autoload?
# main.rb
require 'foo'
M::Foo
# foo.rb
require 'm'
module M::Foo
end
# m.rb
module M
autoload :Foo, 'foo'
p constants #=> [:Foo]
p const_defined?(:Foo) #=> false
p autoload?(:Foo) #=> nil
end
$ ruby -e 'module M; autoload(:Foo, "xxx"); p constants; p const_defined?(:Foo); p autoload?(:Foo); end'
lv l[:Foo]
true
"xxx"
- mame: may I add a document that autoload cannot be used for a file that is currently being loaded
- no one against the addition
- akr: Can we make circular autoload raise an exception?
- akr: It brings an overhead, which might not be acceptable