Skip to content

Correct core/stdlib signatures to match Ruby 4.0#2967

Merged
ksss merged 2 commits into
ruby:masterfrom
zonuexe:fix/stdlib-signature-corrections
May 28, 2026
Merged

Correct core/stdlib signatures to match Ruby 4.0#2967
ksss merged 2 commits into
ruby:masterfrom
zonuexe:fix/stdlib-signature-corrections

Conversation

@zonuexe
Copy link
Copy Markdown
Contributor

@zonuexe zonuexe commented May 21, 2026

Summary

Several core/stdlib signatures were inaccurate against the Ruby 4.0 implementation. This corrects them.

Ruby Method Change
IO#pathconf Add the method — (Integer name) -> Integer?
Digest::Instance#finish Return String, not self
Digest::Class.digest / .hexdigest / .bubblebabble Accept trailing *args (passed through to the constructor)
Digest::Class.file / .base64digest Accept trailing *args
Etc.sysconf Return type is nilable — -> Integer?
Etc.systmpdir Return type is nilable — -> String?
Etc::Group.each / Etc::Passwd.each Add block / Enumerator overloads instead of -> untyped
Etc::Passwd Add the age, comment, and quota members (with their setters)
StringIO.open Add the non-block overload — (?String, ?String?) -> StringIO
StringIO#fcntl Always raises NotImplementedError — return bot
StringIO#fsync Always returns 0-> Integer (not Integer?)
StringIO#internal_encoding Always returns nil
StringIO#external_encoding Return type is nilable — -> Encoding?
StringIO#pread Add the method
StringIO#read_nonblock Accept exception:; return type is nilable
StringIO#write_nonblock Add the method
StringIO#sysread outbuf is optional
StringIO#ungetc Also accepts an Integer
StringIO#set_encoding_by_bom Add the method

Notes

Test plan

  • bundle exec rbs validate
  • bundle exec rbs -r digest -r etc -r stringio validate
  • bundle exec rubocop core/io.rbs stdlib/digest/0/digest.rbs stdlib/etc/0/etc.rbs stdlib/stringio/0/stringio.rbs

Update several signatures that were inaccurate against the Ruby 4.0
implementation:

- `IO#pathconf`: add the method (`(Integer) -> Integer?`).
- `Digest::Instance#finish`: return `String`, not `self`.
- `Digest::Class.{digest,hexdigest,bubblebabble,file,base64digest}`:
  accept the trailing `*args` passed to the constructor.
- `Etc.sysconf` / `Etc.systmpdir`: return types are nilable.
- `Etc::Group.each` / `Etc::Passwd.each`: add block / Enumerator overloads.
- `Etc::Passwd`: add the `age`, `comment`, and `quota` members.
- `StringIO`: non-block `self.open` overload; `fcntl` always raises
  (`bot`); `fsync` returns `0`; `internal_encoding` returns `nil`;
  `external_encoding` is nilable; add `pread` and `write_nonblock`;
  `read_nonblock` takes `exception:` and is nilable; `sysread` `outbuf`
  is optional; `ungetc` also accepts an `Integer`; add `set_encoding_by_bom`.
@ksss ksss added this to the RBS 4.1 milestone May 23, 2026
@ksss ksss merged commit 12b95e4 into ruby:master May 28, 2026
24 checks passed
# is properly padded with '=' and contains no line feeds.
#
def self.base64digest: (string str) -> String
def self.base64digest: (string str, *untyped args) -> String
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I have already merged it, but I believe there is an issue with these changes.
For example, the following code will cause an ArgumentError in actual behavior, but it passes the type check.

Digest::SHA256.base64digest("aaa", :bbb) #=> ArgumentError

While these methods are indeed delegated to the constructor, since it is not possible to describe this delegation in RBS, I believe we should add appropriate overloads in each class.

I will fix it soon.

We will address the issue that the existing test cases failed to detect the problem as a problem with the test harness.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Done #2980

ksss added a commit that referenced this pull request May 28, 2026
The original definition allows for flexible behavior in subclasses,
but it can also lead to overlooking issues that should be discovered.
If we want to increase the number of arguments in a subclass,
we should write an overload in that class.

```
Digest::SHA256.base64digest("aaa", :bbb) #=> ArgumentError
```

ref: #2967
@zonuexe zonuexe deleted the fix/stdlib-signature-corrections branch May 28, 2026 02:45
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.

2 participants