Skip to content

Conversation

@XrXr
Copy link
Member

@XrXr XrXr commented Aug 27, 2025

  • When reading from stdin, put a wrapper around the IO object
  • Bump PRISM version number to avoid collision with RubyGems version

Because this bugfix touches the Prism gem, there is
a problem of having two versions of the gem sharing
the same version number. With that users would get
different copies depending on the version they
install the gem from, or get a checksum error from
RubyGems or Bundler, which is undesirable.

I don't think we can bump to the latest Prism gem
because that would also bring in syntax changes
that are only in Ruby 3.5.

I've picked a version number that ruby/prism hasn't
used yet. Maybe as an optional step, we should also
release this version of Prism to RubyGems when
releasing the next 3.4 version. Otherwise, Prism
needs to remember to avoid this version number
in the future to make sure versions are uniquely
identifiable.

CC @kddnewton

tenderlove and others added 2 commits August 26, 2025 20:55
The purpose of this commit is to fix Bug #21188.  We need to detect when
stdin has run in to an EOF case.  Unfortunately we can't _call_ the eof
function on IO because it will block.

Here is a short script to demonstrate the issue:

```ruby
x = STDIN.gets
puts x
puts x.eof?
```

If you run the script, then type some characters (but _NOT_ a newline),
then hit Ctrl-D twice, it will print the input string.  Unfortunately,
calling `eof?` will try to read from STDIN again causing us to need a
3rd Ctrl-D to exit the program.

Before introducing the EOF callback to Prism, the input loop looked
kind of like this:

```ruby
loop do
  str = STDIN.gets
  process(str)

  if str.nil?
    p :DONE
  end
end
```

Which required 3 Ctrl-D to exit.  If we naively changed it to something
like this:

```ruby
loop do
  str = STDIN.gets
  process(str)

  if STDIN.eof?
    p :DONE
  end
end
```

It would still require 3 Ctrl-D because `eof?` would block.  In this
patch, we're wrapping the IO object, checking the buffer for a newline
and length, and then using that to simulate a non-blocking eof? method.

This commit wraps STDIN and emulates a non-blocking `eof` function.

[Backport #21188]
@XrXr XrXr requested a review from k0kubun as a code owner August 27, 2025 00:59
@kddnewton
Copy link
Contributor

A couple of things:

  • It's actually okay to use the latest version, since we gate all syntax changes on a flag for the version of Ruby that you want to parse.
  • If I understand the problem you're describing, I think maybe we should rethink the change a make it so that it can support both versions (with and without the callback). Is the issue basically that libprism that is shipped with Ruby is different?

@k0kubun
Copy link
Member

k0kubun commented Aug 27, 2025

Maybe as an optional step, we should also release this version of Prism to RubyGems when releasing the next 3.4 version.

This is the general expectations for default gems when they cannot be upgraded to the latest version of the gem in Ruby's stable branches.

If we introduced a feature/syntax to Prism that Ruby 3.4 shouldn't have, ruby/prism probably should cut a ruby_3_4 branch and make releases separately from the main branch.

I'll merge this now, but can you either release such a version and backport the version bump to this branch now, or make me an owner of the gem so that I can do it myself now or when I release Ruby 3.4.6?

@k0kubun k0kubun merged commit b97a159 into ruby:ruby_3_4 Aug 27, 2025
76 checks passed
@k0kubun k0kubun deleted the prism-eof-fix branch August 27, 2025 16:07
@tenderlove
Copy link
Member

I'll merge this now, but can you either release such a version and backport the version bump to this branch now, or make me an owner of the gem so that I can do it myself now or when I release Ruby 3.4.6?

I don't understand what we're trying to accomplish here.

Are we backporting the Prism fix just because it's a bugfix? As such, we need to ship a new version of Prism? Bumping the prism version in ruby/ruby without doing it upstream first doesn't seem like what we should be doing (unless I'm misunderstanding). I guess I don't understand why we needed to bump the Prism version.

@XrXr
Copy link
Member Author

XrXr commented Aug 27, 2025

It's actually okay to use the latest version, since we gate all syntax changes on a flag for the version of Ruby that you want to parse.

Cool, that's a valid option, to bump to the latest version. We'd still need to coordinate a release to keep the version number unique and meaningful though. Looks like no current release contains the API change in this diff yet. Though a bump like that might be risky for the branch maintainer, it's useful to know that it's an option.

If I understand the problem you're describing, I think maybe we should rethink the change a make it so that it can support both versions (with and without the callback). Is the issue basically that libprism that is shipped with Ruby is different?

The problem is that making any changes at all will make the default gem version 1.2.0 of Prism different from the 1.2.0 one can get on rubygems.org. Making changes to support both versions still runs into this problem.

PS. we may want to pick a better version name than I did. I picked 1.3.1 because this is a breaking change, but this version is more closely related to 1.2.0 than 1.3.0... Maybe we need a separate versioning scheme for these backport Prism versions.

@k0kubun
Copy link
Member

k0kubun commented Aug 27, 2025

It's actually okay to use the latest version, since we gate all syntax changes on a flag for the version of Ruby that you want to parse.

it's useful to know that it's an option.

Sorry I guess I overlooked this discussion.

Though a bump like that might be risky for the branch maintainer

As a branch maintainer, I'm generally open to bumping gem versions to the latest, which may include new features, as long as they are backward-compatible. We backport rubygems and bundler which tend to have way riskier changes :p

So which one do you all want in the ruby_3_4 branch, the latest version or a ruby_3_4-specific release? With the flag maintaining the integrity of the syntax for the Ruby version, I'm fine with both ways. If a version with the fix is already published and you don't see any issue, let's just synchronize the whole Prism code in the branch to it.

@XrXr
Copy link
Member Author

XrXr commented Aug 27, 2025

I vote for cutting a new Prism gem release and pointing to it. It's been a while since the last Prism release anyways: ruby/prism#3553 and also, doing that will also do the backport for https://bugs.ruby-lang.org/issues/21337

Will take a little bit of integration work to set the syntax version correctly so we don't accidentally pull in https://bugs.ruby-lang.org/issues/20925 and ruby/prism#3337 which Matz just approved but this seems like the best long term play.

@k0kubun
Copy link
Member

k0kubun commented Sep 12, 2025

@kddnewton WDYT about making @tenderlove and @eileencodes gem owners of prism.gem? I, as a release manager of Ruby 3.4, think we need at least one person who has full-time attention to Ruby and can cut a release of Prism as needed.

@kddnewton
Copy link
Contributor

v1.5.0 is released. Please let me know if there's something I should do with this specific ticket or any backport.

@k0kubun
Copy link
Member

k0kubun commented Sep 12, 2025

Thanks! I'll work on sync-ing Prism to that version on ruby_3_4 and let you know if I need help.

Have you also invited them to be gem owners?

@k0kubun
Copy link
Member

k0kubun commented Sep 12, 2025

It doesn't compile 😞

/Users/runner/work/ruby/ruby/build/rbconfig.rb:315:in 'String#replace': can't modify frozen String: "$(SDKROOT)$(prefix)/include" (FrozenError)
	from /Users/runner/work/ruby/ruby/build/rbconfig.rb:315:in 'RbConfig.expand'
	from /Users/runner/work/ruby/ruby/build/rbconfig.rb:308:in 'block in RbConfig.expand'
	from /Users/runner/work/ruby/ruby/build/rbconfig.rb:301:in 'String#gsub'
	from /Users/runner/work/ruby/ruby/build/rbconfig.rb:301:in 'RbConfig.expand'
	from /Users/runner/work/ruby/ruby/build/rbconfig.rb:308:in 'block in RbConfig.expand'
	from /Users/runner/work/ruby/ruby/build/rbconfig.rb:301:in 'String#gsub'
compiling ../src/enc/cesu_8.c
	from /Users/runner/work/ruby/ruby/build/rbconfig.rb:301:in 'RbConfig.expand'
	from /Users/runner/work/ruby/ruby/build/rbconfig.rb:308:in 'block in RbConfig.expand'
	from /Users/runner/work/ruby/ruby/build/rbconfig.rb:301:in 'String#gsub'
compiling ../src/enc/trans/cesu_8.c
	from /Users/runner/work/ruby/ruby/build/rbconfig.rb:301:in 'RbConfig.expand'
	from /Users/runner/work/ruby/ruby/build/rbconfig.rb:319:in 'block in <module:RbConfig>'
	from /Users/runner/work/ruby/ruby/build/rbconfig.rb:318:in 'Hash#each_value'
	from /Users/runner/work/ruby/ruby/build/rbconfig.rb:318:in '<module:RbConfig>'
	from /Users/runner/work/ruby/ruby/build/rbconfig.rb:11:in '<top (required)>'
	from ../src/ext/extmk.rb:42:in 'Kernel#require'
	from ../src/ext/extmk.rb:42:in '<main>'

https://github.com/ruby/ruby/actions/runs/17684937914/job/50267562914?pr=14532#step:9:176
#14532

@k0kubun
Copy link
Member

k0kubun commented Sep 12, 2025

It builds correctly on my local Linux environment, but every macOS-based CI seems to be failing with it.

@k0kubun
Copy link
Member

k0kubun commented Sep 12, 2025

It works fine on my local macOS environment too 🤔

@k0kubun
Copy link
Member

k0kubun commented Sep 12, 2025

It seems like we also can't use Prism 1.5.0 for Ruby 3.4 anyway? Do we need to create a Prism branch and version for ruby_3_4?

    1) Failure:
  TestSyntax#test_methoddef_endless_command [/home/runner/work/ruby/ruby/src/test/ruby/test_syntax.rb:1800]:
  /home/runner/work/ruby/ruby/src/test/ruby/test_syntax.rb:1800:in 'TestSyntax#test_methoddef_endless_command'.
  ```
  private def foo = puts "Hello"
  ```
  no-newline.
  SyntaxError expected but nothing was raised.
  
    2) Failure:
  Prism::TestCompilePrism#test_concatenated_StringNode [/home/runner/work/ruby/ruby/src/test/ruby/test_compile_prism.rb:624]:
  @/home/runner/work/ruby/ruby/src/test/ruby/test_compile_prism.rb:624.
   expected but was
  .
  
  Finished tests in 221.929572s, 147.4747 tests/s, 29655.7955 assertions/s.
  32729 tests, 6581498 assertions, 2 failures, 0 errors, 364 skips

https://github.com/ruby/ruby/actions/runs/17684937953/job/50267562966?pr=14532

@Earlopain
Copy link
Contributor

It contains 3.5 specific syntax now and currently ruby always uses the latest version that prism knows about. You have to explicitly request 3.4 to get the correct behaviour like #14523

@k0kubun
Copy link
Member

k0kubun commented Sep 12, 2025

I see. Thanks for working on that. I hope backporting it will fix the rest of the problems too.

@kddnewton
Copy link
Contributor

@k0kubun would you be able to make it so that the ruby 3.4 branch requests ruby 3.4 syntax?

@Earlopain
Copy link
Contributor

Earlopain commented Sep 12, 2025

There is this commit: 7dbd9c2

I lack the context but it looks like it was never reverse synced (or mentioned in https://bugs.ruby-lang.org/issues/21187 for that matter)

@k0kubun
Copy link
Member

k0kubun commented Sep 12, 2025

Hm. So I guess this needs to be fixed (or just reverted) on Prism's end first?

@k0kubun
Copy link
Member

k0kubun commented Sep 12, 2025

So on July 21st at ruby-lang Slack (#general-ja), hsbt reported (probably non-GitHub Actions) CI failures because of the reverted commit and shared that he was going to revert it. Aaron acknowledged it and said he would fix Prism and Ruby together, but I guess we've never got to fix it.

For now, I'd like to suggest reverse sync-ing the revert to Prism, make another Prism release, and re-open the Redmine ticket if necessary. I'll just forward-fix the problem by merging the "almost Prism 1.5.0" (with the revert) to ruby_3_4, but it'd be nice to have a release with the revert soon. Otherwise I'll (revert backports and) postpone Prism backports to Ruby 3.4.7.

@Earlopain
Copy link
Contributor

The problem that this change intended to fix still seems to be fixed even with the revert. There is more context in #13966 for those that understand but I tested the repro from https://bugs.ruby-lang.org/issues/21187 and it is as expected on current master. 3.4.5 still fails since it never got backported.

So reverting seems ok? Although I cannot say why @tenderlove made that change to begin with. I assume there were reasons.

@k0kubun
Copy link
Member

k0kubun commented Sep 12, 2025

Huh, ok. Let's start from reverting it then. Unfortunately Aaron seems to be out next week (as well as this week), so I guess I'll need Kevin to make another release. I'll prepare the reverse sync PR.

@k0kubun
Copy link
Member

k0kubun commented Sep 12, 2025

So ruby_3_4 currently has Prism 1.5.0 with the revert #14532, which does fix the build issue on ruby_3_4 as well. I need a Prism release with the revert to make it consistent with the version it points to on rubygems.org.

@kddnewton Could you merge ruby/prism#3643 and make another release of Prism? @tenderlove is out until Sep 21st, so I don't think he has time to attempt to fix his patch before the Ruby 3.4.6 release (next Monday).

@kddnewton
Copy link
Contributor

v1.5.1 is out with the revert.

@hsbt hsbt added the Backport label Dec 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants