Issue #20468 has been reported by kddnewton (Kevin Newton).
----------------------------------------
Bug #20468: Segfault on safe navigation in for target
https://bugs.ruby-lang.org/issues/20468
* Author: kddnewton (Kevin Newton)
* Status: Open
* Backport: 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN
----------------------------------------
```ruby
for foo&.bar in []; end
```
--
https://bugs.ruby-lang.org/
Issue #15554 has been updated by nobu (Nobuyoshi Nakada).
I want the message to be separated for caller and callee, to tag jump.
Current:
> /home/runner/.rubies/ruby-head/lib/ruby/gems/3.4.0+0/gems/test-unit-3.6.2/lib/test/unit/fixture.rb:284: warning: the block passed to 'priority_setup' defined at /home/runner/.rubies/ruby-head/lib/ruby/gems/3.4.0+0/gems/test-unit-3.6.2/lib/test/unit/priority.rb:183 may be ignored
Such as:
> /home/runner/.rubies/ruby-head/lib/ruby/gems/3.4.0+0/gems/test-unit-3.6.2/lib/test/unit/fixture.rb:284: warning: the block may be ignored
> /home/runner/.rubies/ruby-head/lib/ruby/gems/3.4.0+0/gems/test-unit-3.6.2/lib/test/unit/priority.rb:183: info: passed to 'priority_setup'
----------------------------------------
Feature #15554: warn/error passing a block to a method which never use a block
https://bugs.ruby-lang.org/issues/15554#change-108192
* Author: ko1 (Koichi Sasada)
* Status: Assigned
* Assignee: matz (Yukihiro Matsumoto)
----------------------------------------
# Abstract
Warn or raise an ArgumentError if block is passed to a method which does not use a block.
In other words, detect "block user methods" implicitly and only "block user methods" can accept a block.
# Background
Sometimes, we pass a block to a method which ignores the passed block accidentally.
```
def my_open(name)
open(name)
end
# user hopes it works as Kernel#open which invokes a block with opened file.
my_open(name){|f| important_work_with f }
# but simply ignored...
```
To solve this issue, this feature request propose showing warnings or raising an exception on such case.
Last developer's meeting, matz proposed `&nil` which declares this method never receive a block. It is explicit, but it is tough to add this `&nil` parameter declaration to all of methods (do you want to add it to `def []=(i, e, &nil)`?).
(I agree `&nil` is valuable on some situations)
# Spec
## Define "use a block" methods
We need to define which method accepts a block and which method does not.
* (1) method has a block parameter (`&b`)
* (2) method body has `yield'
* (3) method body has `super` (ZSUPER in internal terminology) or `super(...)`
* (4) method body has singleton method (optional)
(1) and (2) is very clear. I need to explain about (3) and (4).
(3). `super` (ZSUPER) passes all parameters as arguments. So there is no surprise that which can accept `block`.
However `super(...)` also passes a block if no explicit block passing (like `super(){}` or `super(&b)`) are written.
I'm not sure we need to continue this strange specification, but to keep compatibility depending this spec, I add this rule.
(4). surprisingly, the following code invoke a block:
```
def foo
class << Object.new
yield
end
end
foo{ p :ok } #=> :ok
```
I'm also not sure we need to keep this spec, but to allow this spec, I added (4) rule.
Strictly speaking, it is not required, but we don't keep the link from singleton class ISeq to lexical parent iseq now, so I added it.
## Exceptional cases
A method called by `super` doesn`t warn warning even if this method doesn't use a block.
The rule (3) can pass blocks easily and there are many methods don`t use a block.
So my patch ignores callings by `super`.
## corner cases
There are several cases to use block without (1)-(4) rules.
### `Proc.new/proc/lambda` without a block
Now it was deprecated in r66772 (commit:9f1fb0a17febc59356d58cef5e98db61a3c03550).
Related discussion: [Bug #15539]
### `block_given?`
`block_given?` expects block, but I believe we use it with `yield` or a block parameter.
If you know the usecase without them, please tell us.
### `yield` in `eval`
We can't know `yield` (or (3), (4) rule) in an `eval` evaluating string at calling time.
```
def foo
eval('yield`)
end
foo{} # at calling time,
# we can't know the method foo can accept a block or not.
```
So I added a warning to use `yield` in `eval` like that: `test.rb:4: warning: use yield in eval will not be supported in Ruby 3.`
Workaround is use a block parameter explicitly.
```
def foo &b
eval('b.call')
end
foo{ p :ok }
```
# Implementation
Strategy is:
* [compile time] introduce `iseq::has_yield` field and check it if the iseq (or child iseq) contains `yield` (or something)
* [calling time] if block is given, check `iseq::has_yield` flag and show warning (or raise an exception)
https://gist.github.com/ko1/c9148ad0224bf5befa3cc76ed2220c0b
On this patch, now it raises an error to make it easy to detect.
It is easy to switch to show the warning.
# Evaluation and discussion
I tried to avoid ruby's tests.
https://gist.github.com/ko1/37483e7940cdc4390bf8eb0001883786
Here is a patch.
There are several patterns to avoid warnings.
## tests for `block_given?`, `Proc.new` (and similar) without block
Add a dummy block parameter.
It is test-specific issue.
## empty `each`
Some tests add `each` methods do not `yield`, like: `def each; end`.
Maybe test-specific issue, and adding a dummy block parameter.
## Subtyping / duck typing
https://github.com/ruby/ruby/blob/c01a5ee85e2d6a7128cccafb143bfa694284ca87/…
This `parse` method doesn't use `yield`, but other sub-type's `parse` methods use.
## `super` with `new` method
https://gist.github.com/ko1/37483e7940cdc4390bf8eb0001883786#file-tests-pat…
This method override `Class#new` method and introduce a hook with block (yield a block in this hook code).
https://github.com/ruby/ruby/blob/trunk/lib/rubygems/package/tar_writer.rb#…
In this method, call `super` and it also passing a block. However, called `initialize` doesn't use a block.
## Change robustness
This change reduce robustness for API change.
`Delegator` requires to support `__getobj__` for client classes.
Now `__getobj__` should accept block but most of `__getobj__` clients do not call given block.
https://github.com/ruby/ruby/blob/trunk/lib/delegate.rb#L80
This is because of delegator.rb's API change.
https://gist.github.com/ko1/37483e7940cdc4390bf8eb0001883786#file-tests-pat…
Nobu says calling block is not required (ignoring a block is no problem) so it is not a bug for delegator client classes.
## Found issues.
```
[ 2945/20449] Rinda::TestRingServer#test_do_reply = 0.00 s
1) Error:
Rinda::TestRingServer#test_do_reply:
ArgumentError: passing block to the method "with_timeout" (defined at /home/ko1/src/ruby/trunk/test/rinda/test_rinda.rb:787) is never used.
/home/ko1/src/ruby/trunk/test/rinda/test_rinda.rb:635:in `test_do_reply'
[ 2946/20449] Rinda::TestRingServer#test_do_reply_local = 0.00 s
2) Error:
Rinda::TestRingServer#test_do_reply_local:
ArgumentError: passing block to the method "with_timeout" (defined at /home/ko1/src/ruby/trunk/test/rinda/test_rinda.rb:787) is never used.
/home/ko1/src/ruby/trunk/test/rinda/test_rinda.rb:657:in `test_do_reply_local'
[10024/20449] TestGemRequestSetGemDependencyAPI#test_platform_mswin = 0.01 s
3) Error:
TestGemRequestSetGemDependencyAPI#test_platform_mswin:
ArgumentError: passing block to the method "util_set_arch" (defined at /home/ko1/src/ruby/trunk/lib/rubygems/test_case.rb:1053) is never used.
/home/ko1/src/ruby/trunk/test/rubygems/test_gem_request_set_gem_dependency_api.rb:655:in `test_platform_mswin'
[10025/20449] TestGemRequestSetGemDependencyAPI#test_platforms = 0.01 s
4) Error:
TestGemRequestSetGemDependencyAPI#test_platforms:
ArgumentError: passing block to the method "util_set_arch" (defined at /home/ko1/src/ruby/trunk/lib/rubygems/test_case.rb:1053) is never used.
/home/ko1/src/ruby/trunk/test/rubygems/test_gem_request_set_gem_dependency_api.rb:711:in `test_platforms'
```
These 4 detection show the problem. `with_timeout` method (used in Rinda test) and `util_set_arch` method (used in Rubygems test) simply ignore the given block.
So these tests are simply ignored.
I reported them. (https://github.com/rubygems/rubygems/issues/2601)
## raise an error or show a warning?
At least, Ruby 2.7 should show warning for this kind of violation with `-w`.
How about for Ruby3?
--
https://bugs.ruby-lang.org/
Issue #20205 has been reported by byroot (Jean Boussier).
----------------------------------------
Feature #20205: Enable `frozen_string_literal` by default
https://bugs.ruby-lang.org/issues/20205
* Author: byroot (Jean Boussier)
* Status: Open
* Priority: Normal
----------------------------------------
### Context
The `frozen_string_literal: true` pragma was introduced in Ruby 2.3, and as far as I'm aware the plan was initially to make it the default for Ruby 3.0, but this plan was abandoned because it would be too much of a breaking change without any real further notice.
According to Matz, he still wishes to enable `frozen_string_literal` by default in the future, but a reasonable migration plan is required.
The main issue is backward compatibility, flipping the switch immediately would break a lot of code, so there must be some deprecation period.
The usual the path forward for this kind of change is to emit deprecation warnings one of multiple versions in advance.
One example of that was the Ruby 2.7 keyword argument deprecation. It was quite verbose, and some users were initially annoyed, but I think the community pulled through it and I don't seem to hear much about it anymore.
So for frozen string literals, the first step would be to start warning when a string that would be frozen in the future is mutated.
### Deprecation Warning Implementation
I implemented a quick proof of concept with @etienne in https://github.com/Shopify/ruby/pull/549
In short:
- Files with `# frozen_string_literal: true` or `# frozen_string_literal: false` don't change in behavior at all.
- Files with no `# frozen_string_literal` comment are compiled to use `putchilledstring` opcode instead of regular `putstring`.
- This opcode mark the string with a user flag, when these strings are mutated, a warning is issued.
Currently the proof of concept issue the warning at the mutation location, which in some case can make locating where the string was allocated a bit hard.
But it is possible to improve it so the message also include the location at which the literal string was allocated, and learning from the keyword argument warning experience,
we can record which warnings were already issued to avoid spamming users with duplicated warnings.
As currently implemented, there is almost no overhead. If we modify the implementation to record the literal location,
we'd incur a small memory overhead for each literal string in a file without an explicit `frozen_string_literal` pragma.
But I believe we could do it in a way that has no overhead if `Warning[:deprecated] = false`.
### Timeline
The migration would happen in 3 steps, each step can potentially last multiple releases. e.g. `R0` could be `3.4`, `R1` be `3.7` and `R2` be `4.0`.
I don't have a strong opinion on the pace.
- Release `R0`: introduce the deprecation warning (only if deprecation warnings enabled).
- Release `R1`: make the deprecation warning show up regardless of verbosity level.
- Release `R2`: make string literals frozen by default.
### Impact
Given that `rubocop` is quite popular in the community and it has enforced the usage of `# frozen_string_literal: true` for years now,
I suspect a large part of the actively maintained codebases in the wild wouldn't see any warnings.
And with recent versions of `minitest` enabling deprecation warnings by default (and [potentially RSpec too](https://github.com/rspec/rspec-core/issues/2867)),
the few that didn't migrate will likely be made compatible quickly.
The real problem of course are the less actively developed libraries and applications. For such cases, any codebase can remain compatible by setting `RUBYOPT="--disable=frozen_string_literal"`,
and so even after `R2` release. The flag would never be removed any legacy codebase can continue upgrading Ruby without changing a single line of cod by just flipping this flag.
### Workflow for library maintainers
As a library maintainer, fixing the deprecation warnings can be as simple as prepending `# frozen_string_literal: false` at the top of all their source files, and this will keep working forever.
Alternatively they can of course make their code compatible with frozen string literals.
Code that is frozen string literal compatible doesn't need to explicitly declare it. Only code that need it turned of need to do so.
### Workflow for application owners
For application owners, the workflow is the same than for libraries.
However if they depend on a gem that hasn't updated, or that they can't upgrade it, they can run their application with `RUBYOPT="--disable=frozen_string_literal"` and it will keep working forever.
Any user running into an incompatibility issue can set `RUBYOPT="--disable=frozen_string_literal"` forever, even in `4.x`, the only thing changing is the default value.
And any application for which all dependencies have been made fully frozen string literal compatible can set `RUBYOPT="--enable=frozen_string_literal"` and start immediately removing magic comment from their codebase.
--
https://bugs.ruby-lang.org/
Issue #20472 has been reported by kddnewton (Kevin Newton).
----------------------------------------
Bug #20472: Ractor support for ** into hash literal
https://bugs.ruby-lang.org/issues/20472
* Author: kddnewton (Kevin Newton)
* Status: Open
* Backport: 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN
----------------------------------------
```ruby
# shareable_constant_value: experimental_copy
a = { "foo" => "bar" }
A = { **a }
```
In this example, Ruby fails an assertion and crashes. I think we should either provide support for this, or we should explicitly provide a syntax error indicating that ** isn't allowed in constant writes when ractor pragmas are enabled.
--
https://bugs.ruby-lang.org/
Issue #18995 has been updated by javanthropus (Jeremy Bopp).
@jeremyevans, did you ever take a look at this issue when I referenced it in #18899? The behavior is unchanged in Ruby 3.3.
The script above prints the following:
```
external encoding: #<Encoding:UTF-8> internal encoding: #<Encoding:ISO-8859-2>
external encoding: #<Encoding:UTF-8> internal encoding: #<Encoding:ISO-8859-1>
external encoding: #<Encoding:UTF-8> internal encoding: #<Encoding:ISO-8859-3>
```
I expected it to print this:
```
external encoding: #<Encoding:UTF-8> internal encoding: #<Encoding:ISO-8859-2>
external encoding: #<Encoding:UTF-8> internal encoding: #<Encoding:ISO-8859-2>
external encoding: #<Encoding:UTF-8> internal encoding: #<Encoding:ISO-8859-4>
```
----------------------------------------
Bug #18995: IO#set_encoding sometimes set an IO's internal encoding to the default external encoding
https://bugs.ruby-lang.org/issues/18995#change-108185
* Author: javanthropus (Jeremy Bopp)
* Status: Open
* ruby -v: ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [x86_64-linux]
* Backport: 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN
----------------------------------------
This script demonstrates the behavior:
```ruby
def show(io)
printf(
"external encoding: %-25p internal encoding: %-25p\n",
io.external_encoding,
io.internal_encoding
)
end
Encoding.default_external = 'iso-8859-1'
Encoding.default_internal = 'iso-8859-2'
File.open('/dev/null') do |f|
f.set_encoding('utf-8', nil)
show(f) # f.internal_encoding is iso-8859-2, as expected
f.set_encoding('utf-8', 'invalid')
show(f) # f.internal_encoding is now iso-8859-1!
Encoding.default_external = 'iso-8859-3'
Encoding.default_internal = 'iso-8859-4'
show(f) # f.internal_encoding is now iso-8859-3!
end
```
In the 1st case, we see that the IO's internal encoding is set to the current setting of Encoding.default_internal. In the 2nd case, the IO's internal encoding is set to Encoding.default_external instead. The 3rd case is more interesting because it shows that the IO's internal encoding is actually following the current setting of Encoding.default_external. It didn't just copy it when #set_encoding was called. It changes whenever Encoding.default_external changes.
What should the correct behavior be?
--
https://bugs.ruby-lang.org/
Issue #20471 has been reported by budiljak (Benjamin Udiljak).
----------------------------------------
Bug #20471: Problem creating a file on a windows share and copy it afterwards
https://bugs.ruby-lang.org/issues/20471
* Author: budiljak (Benjamin Udiljak)
* Status: Open
* Backport: 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN
----------------------------------------
Hi,
in my Rails application I have the requirement to create a file and copy it to another place on the same windows share. But if I write the file with `File` class and try to copy it with `FileUtils.cp` it hangs indefinitely without any error message. I can't even kill the ruby process.
You can easily reproduce the bug by entering this in IRB:
```
filename = "/mnt/windows_share/abc"; File.open(filename, 'wb') { |f| f.write("123" * 1000) }; FileUtils.cp(filename, filename + "d")
```
I tested this on a Ubuntu 22.04 server in the AWS cloud.
I also tried `f.fsync` , `f.fdatasync` , `f.flush`, but it didn't help.
Probably it's a problem in connection with the `cifs-utils` package.
Please come back to me if you need further information.
Regards!
Ben
--
https://bugs.ruby-lang.org/
Issue #20469 has been reported by shan (Shannon Skipper).
----------------------------------------
Feature #20469: Add a JSON addition for Enumerator::ArithmeticSequence
https://bugs.ruby-lang.org/issues/20469
* Author: shan (Shannon Skipper)
* Status: Open
----------------------------------------
There's a JSON addition for `Range` but one wasn't added for `Enumerator::ArithmeticSequence` when it was introduced. This little PR adds a JSON addition for ArithmeticSequence for parity with a normal Range. https://github.com/ruby/ruby/pull/10720/files
``` ruby
##
# Already supported
require 'json/add/range'
(0..42).to_json
##
# Proposed addition
require 'json/add/arithmetic_sequence'
((0..42) % 3).to_json
```
I was curious about adding it to `add/core.rb` but it seems like that could be considered separately, especially since there are classes like Set that could also be considered for inclusion now that it's a core class.
--
https://bugs.ruby-lang.org/