Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Superfluous Object:: in module name #3683

Closed
fxn opened this issue Oct 5, 2024 · 33 comments
Closed

Superfluous Object:: in module name #3683

fxn opened this issue Oct 5, 2024 · 33 comments
Assignees
Labels

Comments

@fxn
Copy link

fxn commented Oct 5, 2024

Hi! I am replacing TracePoint with Module#const_added in Zeitwerk, and noticed the new test suite does not pass on TruffleRuby (this work is still not released).

The root cause is this:

class Module
  def const_added(cname)
    puts const_get(cname).name
  end
end

module M
end

That prints "Object::M", instead of "M".

I suspect it is related to internal callback logic specifically, because M.name is "M" later.

Version is

% ruby -v
truffleruby 24.1.0, like ruby 3.2.4, Oracle GraalVM JVM [arm64-darwin20]

/cc @byroot

@fxn
Copy link
Author

fxn commented Oct 11, 2024

Hey! Just so that you know :), I just published Zeitwerk 2.7 with that change. Due to this issue, Zeitwerk 2.7 does not work with TruffleRuby right now.

@eregon
Copy link
Member

eregon commented Oct 11, 2024

Could you point me to something that breaks?

irb(main):001:0> module M;end
=> nil
irb(main):002:0> Object.const_get("Object::M")
=> M

works for example, so while this is still a bug in TruffleRuby, Object::M is a valid constant path to reference M.

@eregon
Copy link
Member

eregon commented Oct 11, 2024

I think it would be nice to workaround this in Zeitwerk if possible, so that the latest TruffleRuby release is not broken.
If it's just a test failing no big deal but if it means Rails doesn't boot on TruffleRuby 24.1 due to this then it's a big deal.

@byroot
Copy link

byroot commented Oct 11, 2024

"Object::M is a valid constant path to reference M." yeah, the problem is Zeitwerk keep the expected name in a Hash and need to look it up.

This can be worked around for sure, but it's a pretty hot loop, so should be done with care (or scoped under if RUBY_ENGINE == "truffleruby".

@byroot
Copy link

byroot commented Oct 11, 2024

f it means Rails doesn't boot on TruffleRuby 24.1 due to this then it's a big deal.

People can just require "zeitwerk", "< 2.7" for now. So might not be worth shipping a workaround.

@eregon
Copy link
Member

eregon commented Oct 11, 2024

Could you point me to the code doing that? Maybe the key could be the module itself instead of strings?

People can just require "zeitwerk", "< 2.7" for now. So might not be worth shipping a workaround.

I suppose the error won't be clear so it's still a very poor user experience.

I just tried rails new railsapp --minimal, that uses zeitwerk (2.7.0) but both be rake test and bin/rails s seem to work fine.

@byroot
Copy link

byroot commented Oct 11, 2024

Could you point me to the code doing that?

https://github.com/fxn/zeitwerk/blob/83277e0ff17728b07d99c1f8720332379b084456/lib/zeitwerk/core_ext/module.rb#L5

Maybe the key could be the module itself instead of strings?

No, the whole point is that this is registered before the module is loaded.

@fxn
Copy link
Author

fxn commented Oct 11, 2024

I just tried rails new railsapp --minimal, that uses zeitwerk (2.7.0) but both be rake test and bin/rails s seem to work fine.

Because the error only shows up with namespaces defined in files. Their child constants won't be found.

Maybe the key could be the module itself instead of strings?

There are projects where classes/modules are not hashable, learned that the hard way time ago.

@eregon
Copy link
Member

eregon commented Oct 11, 2024

No, the whole point is that this is registered before the module is loaded.

The constant already exists by the time const_added is called.

There are projects where classes/modules are not hashable, learned that the hard way time ago.

How is that possible? All Module instances have #hash via Kernel#hash. And if it's incorrectly overridden then one could use a {}.compare_by_identity Hash

@fxn
Copy link
Author

fxn commented Oct 11, 2024

How is that possible? All Module instances have #hash via Kernel#hash. And if it's incorrectly overridden then one could use a {}.compare_by_identity Hash

They had hash overridden to mean something else, and had a different signature (a debatable practice, yes).

In any case, this is a hot code path and the implementation was chosen among several options to be the most performant one. I'd need nested hashes to do this (because the key is a pair (mod, cname) conceptually).

I don't plan to revisit this implementation any time soon, unless I find something even more performant and backwards compatible.

@fxn
Copy link
Author

fxn commented Oct 11, 2024

@eregon, can you help me understand this thread?

TruffleRuby has a bug. I report it in advance. The reaction I would expect would be "thanks, we'll ship a fix as soon as possible". But I am feeling instead kind of a push back, and a proposal that consists on investigating in which way TruffleRuby is incompatible and that I release a new version to workaround the fact that TruffleRuby won't ship a new version. Or that I change an implementation that is correct.

Please don't get me wrong, I am asking this with sincerity.

Then, I see this as marked to be released in March 2025 (!).

Why?

@eregon
Copy link
Member

eregon commented Oct 11, 2024

First of all, thank you for reporting the bug, we forgot to say that.
Normally @andrykonchin or I would take a look at new reported bugs and at least reply that but we missed this one.

@andrykonchin made a fix today in #3688 and I reviewed, it should be good to go.
So at least the fix should be soon on master & dev builds.

#3683 (comment) worried me because it sounds like you released a new Zeitwerk version without caring about this issue. It's fair enough since you filed this issue and TruffleRuby is not currently in Zeitwerk's CI (due to #2431 which I tried to fix but I got endless complications and CI failures due to the complexity of CRuby autoload semantics and never got to merge it, it's still an open PR, in hindsight it could have been nice to only skip that flaky test but keep running the other tests).
And well of course this issue shouldn't block Zeitwerk to be released.

Then, I see this as marked to be released in March 2025 (!).

That is simply the next milestone & next TruffleRuby feature release (same schedule as GraalVM for releases).
So it's unfortunately only 1 feature release every 6 months.

From https://www.graalvm.org/release-calendar/#graal-languages it's too late for 24.1.1 (last fix was Oct 1).
We could and probably should backport this for 24.1.2 (January 21, 2025), but that's still in a while unfortunately.

I was asking these questions because indeed I was hoping for a quick workaround or fix in Zeitwerk, which could be released much sooner than TruffleRuby. Caching on the Module instead of its name feels intuitively better but of course you make good points that it would need nested hashes or [namespace, child] keys. Also I guess the name key might be needed because it persists over reloading, while the reloaded module could have a different identity.

@fxn
Copy link
Author

fxn commented Oct 11, 2024

#3683 (comment) worried me because it sounds like you released a new Zeitwerk version without caring about this issue.

I cared, and I reported it in advance. But got no feedback. If you guys had been like, "oh, let us work on this one, can you hold releasing a bit?" I would have certainly be glad to do so.

But the ticket was silent and TruffleRuby is the project interested in this. The ticket is not "could you please fix this for Zeitwerk?". The ticket is, "you probably want to know about this (and BTW the next release of Zeitwerk won't fully work without this fixed, but that is up to you guys)".

On the other hand, Zeitwerk 2.7 has been in the oven for some time, and it is a project milestone. So I shipped. And I optimistically thought TruffleRuby would eventually address this one.

And well of course this issue shouldn't block Zeitwerk to be released.

Yes, that.

So it's unfortunately only 1 feature release every 6 months.

Wow, I did not know that.

That makes me think about Rails 8, I planned to make it depend on Zeitwerk 2.7.

@eregon
Copy link
Member

eregon commented Oct 11, 2024

I'll try to make a PR to Zeitwerk to see what a workaround looks like (should be pretty trivial, like a start_with?("Object::") check).

@fxn
Copy link
Author

fxn commented Oct 11, 2024

Thanks @eregon. I'll also look for spots in which I can leverage comparing by identity, maybe we can save computing a few permanent names.

eregon added a commit to eregon/zeitwerk that referenced this issue Oct 12, 2024
* See oracle/truffleruby#3683
* Without this the test suite has 6 failures, 26 errors.
@eregon
Copy link
Member

eregon commented Oct 12, 2024

fxn/zeitwerk#303

eregon added a commit to eregon/zeitwerk that referenced this issue Oct 12, 2024
* See oracle/truffleruby#3683
* Without this the test suite has 6 failures, 26 errors.
@fxn
Copy link
Author

fxn commented Oct 12, 2024

I have also seen that

class Module
  def const_added(cname)
    p const_get(cname).name
  end
end

H = Class.new

prints nil in the stable release. Should print "H".

@eregon
Copy link
Member

eregon commented Oct 13, 2024

I think that's the same issue (will verify by adding a spec for that case), it's also because of the order in https://github.com/oracle/truffleruby/pull/3688/files#diff-c60ad35a6a0531d8ba253c54bce6ce93009fd357fee591615137609f1929c5ab where it used to be "set constant, call const_added, set full name" where the PR fixes it to "set full name, set constant, call const_added".

EDIT: const_added was implemented in #3099 I think it's worth taking a deeper look at it, I'm not sure calling it from inside the recursive getAdoptedByLexicalParent/updateAnonymousChildrenModules is correct.

@fxn
Copy link
Author

fxn commented Oct 14, 2024

"set constant, call const_added, set full name"

Interesting, why isn't the name nil instead of "Object::M" in the original example?

@eregon
Copy link
Member

eregon commented Oct 14, 2024

Because module M immediately gives a "basename" of "M" to that module as soon as the module is created.
And then we computed the name (from Module#name inside const_added) before the full name is set as part of the assignment, and that logic normally used mostly for anonymous modules would then do

return lexicalParent.fields.getName() + "::" + givenBaseName;

#3688 fixes that case though should it happen before the full name is set.

@eregon
Copy link
Member

eregon commented Oct 18, 2024

Fixed in 495a0e5

@eregon eregon closed this as completed Oct 18, 2024
eregon added a commit to eregon/zeitwerk that referenced this issue Oct 18, 2024
@eregon eregon modified the milestones: 24.2.0 Release (March 18, 2025), 24.1.2 Release (Jan 21, 2025) Oct 18, 2024
@eregon
Copy link
Member

eregon commented Oct 19, 2024

For the record and to document this, this issue causes rails new to fail on TruffleRuby 24.1.0 & 24.1.1 with:

...
         run  bundle install --quiet
         run  bundle lock --add-platform=x86_64-linux
Writing lockfile to /home/eregon/tmp/blog/Gemfile.lock
         run  bundle binstubs bundler
       rails  importmap:install
bin/rails aborted!
NameError: uninitialized constant ActionCable::Server (NameError)
Did you mean?  TCPServer
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/actioncable-7.2.1.1/lib/action_cable.rb:78:in `const_missing'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/actioncable-7.2.1.1/lib/action_cable.rb:78:in `server'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/actioncable-7.2.1.1/lib/action_cable/engine.rb:67:in `block (3 levels) in <class:Engine>'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/actionpack-7.2.1.1/lib/action_dispatch/routing/route_set.rb:467:in `instance_exec'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/actionpack-7.2.1.1/lib/action_dispatch/routing/route_set.rb:467:in `eval_block'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/actionpack-7.2.1.1/lib/action_dispatch/routing/route_set.rb:484:in `block in clear!'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/actionpack-7.2.1.1/lib/action_dispatch/routing/route_set.rb:484:in `each'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/actionpack-7.2.1.1/lib/action_dispatch/routing/route_set.rb:484:in `clear!'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/railties-7.2.1.1/lib/rails/application/routes_reloader.rb:45:in `block in clear!'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/railties-7.2.1.1/lib/rails/application/routes_reloader.rb:43:in `each'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/railties-7.2.1.1/lib/rails/application/routes_reloader.rb:43:in `clear!'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/railties-7.2.1.1/lib/rails/application/routes_reloader.rb:23:in `reload!'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/railties-7.2.1.1/lib/rails/application/routes_reloader.rb:38:in `block in updater'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/activesupport-7.2.1.1/lib/active_support/file_update_checker.rb:85:in `execute'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/railties-7.2.1.1/lib/rails/application/routes_reloader.rb:13:in `execute'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/railties-7.2.1.1/lib/rails/application/finisher.rb:162:in `block in <module:Finisher>'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/railties-7.2.1.1/lib/rails/initializable.rb:32:in `instance_exec'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/railties-7.2.1.1/lib/rails/initializable.rb:32:in `run'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/railties-7.2.1.1/lib/rails/initializable.rb:61:in `block in run_initializers'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/railties-7.2.1.1/lib/rails/initializable.rb:60:in `run_initializers'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/railties-7.2.1.1/lib/rails/application.rb:435:in `initialize!'
/home/eregon/tmp/blog/config/environment.rb:5:in `<top (required)>'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/bootsnap-1.18.4/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30:in `require'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/zeitwerk-2.7.1/lib/zeitwerk/core_ext/kernel.rb:34:in `require'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/railties-7.2.1.1/lib/rails/application.rb:411:in `require_environment!'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/railties-7.2.1.1/lib/rails/application.rb:559:in `block in run_tasks_blocks'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/rake-13.2.1/lib/rake/task.rb:281:in `block in execute'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/rake-13.2.1/lib/rake/task.rb:281:in `each'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/rake-13.2.1/lib/rake/task.rb:281:in `execute'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/rake-13.2.1/lib/rake/task.rb:219:in `block in invoke_with_call_chain'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/rake-13.2.1/lib/rake/task.rb:199:in `invoke_with_call_chain'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/rake-13.2.1/lib/rake/task.rb:243:in `block in invoke_prerequisites'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/rake-13.2.1/lib/rake/task.rb:241:in `each'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/rake-13.2.1/lib/rake/task.rb:241:in `invoke_prerequisites'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/rake-13.2.1/lib/rake/task.rb:218:in `block in invoke_with_call_chain'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/rake-13.2.1/lib/rake/task.rb:199:in `invoke_with_call_chain'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/rake-13.2.1/lib/rake/task.rb:188:in `invoke'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/importmap-rails-2.0.3/lib/tasks/importmap_tasks.rake:6:in `block (2 levels) in <top (required)>'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/rake-13.2.1/lib/rake/task.rb:281:in `block in execute'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/rake-13.2.1/lib/rake/task.rb:281:in `each'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/rake-13.2.1/lib/rake/task.rb:281:in `execute'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/rake-13.2.1/lib/rake/task.rb:219:in `block in invoke_with_call_chain'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/rake-13.2.1/lib/rake/task.rb:199:in `invoke_with_call_chain'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/rake-13.2.1/lib/rake/task.rb:188:in `invoke'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/rake-13.2.1/lib/rake/application.rb:188:in `invoke_task'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/rake-13.2.1/lib/rake/application.rb:138:in `block (2 levels) in top_level'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/rake-13.2.1/lib/rake/application.rb:138:in `each'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/rake-13.2.1/lib/rake/application.rb:138:in `block in top_level'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/rake-13.2.1/lib/rake/application.rb:147:in `run_with_threads'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/rake-13.2.1/lib/rake/application.rb:132:in `top_level'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/railties-7.2.1.1/lib/rails/commands/rake/rake_command.rb:27:in `block (2 levels) in perform'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/rake-13.2.1/lib/rake/application.rb:214:in `standard_exception_handling'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/railties-7.2.1.1/lib/rails/commands/rake/rake_command.rb:27:in `block in perform'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/railties-7.2.1.1/lib/rails/commands/rake/rake_command.rb:44:in `block in with_rake'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/rake-13.2.1/lib/rake/rake_module.rb:59:in `with_application'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/railties-7.2.1.1/lib/rails/commands/rake/rake_command.rb:41:in `with_rake'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/railties-7.2.1.1/lib/rails/commands/rake/rake_command.rb:20:in `perform'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/railties-7.2.1.1/lib/rails/command.rb:156:in `invoke_rake'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/railties-7.2.1.1/lib/rails/command.rb:73:in `block in invoke'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/railties-7.2.1.1/lib/rails/command.rb:149:in `with_argv'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/railties-7.2.1.1/lib/rails/command.rb:69:in `invoke'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/railties-7.2.1.1/lib/rails/commands.rb:18:in `<top (required)>'
/home/eregon/tmp/blog/vendor/bundle/truffleruby/3.2.4.24.1.0.1/gems/bootsnap-1.18.4/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30:in `require'
Tasks: TOP => app:template => environment
(See full trace by running task with --trace)
       rails  turbo:install stimulus:install
You must either be running with node (package.json) or importmap-rails (config/importmap.rb) to use this gem.
You must either be running with node (package.json) or importmap-rails (config/importmap.rb) to use this gem.

The easiest solution is to use truffleruby-head and truffleruby 24.1.2+ when it is released (21 Jan 2025).

Using a zeitwerk < 2.7 also works as documented here, by modifying the Gemfile after rails new fails, adding gem "zeitwerk", "< 2.7" and then running rails new again and not overwriting the Gemfile.

One can also generate the application on CRuby and then run it on TruffleRuby.

@eregon eregon modified the milestones: 24.1.2 Release (Jan 21, 2025), 24.2.0 Release (March 18, 2025) Oct 22, 2024
@bachos
Copy link

bachos commented Oct 22, 2024

Just for tracking sake, it seems that even with truffleruby 24.2.0 (dev), we are still facing some issues with bin/rails s after a successful rails new

I am getting an Internal Serve Error

NameError (uninitialized constant ActionCable::Server):

actioncable (8.0.0.rc1) lib/action_cable.rb:78:in `const_missing'
actioncable (8.0.0.rc1) lib/action_cable.rb:78:in `server'
actioncable (8.0.0.rc1) lib/action_cable/engine.rb:67:in `block (3 levels) in <class:Engine>'
actionpack (8.0.0.rc1) lib/action_dispatch/routing/route_set.rb:479:in `instance_exec'
actionpack (8.0.0.rc1) lib/action_dispatch/routing/route_set.rb:479:in `eval_block'
actionpack (8.0.0.rc1) lib/action_dispatch/routing/route_set.rb:496:in `block in clear!'
actionpack (8.0.0.rc1) lib/action_dispatch/routing/route_set.rb:496:in `each'
actionpack (8.0.0.rc1) lib/action_dispatch/routing/route_set.rb:496:in `clear!'
railties (8.0.0.rc1) lib/rails/application/routes_reloader.rb:55:in `block in clear!'
railties (8.0.0.rc1) lib/rails/application/routes_reloader.rb:53:in `each'
railties (8.0.0.rc1) lib/rails/application/routes_reloader.rb:53:in `clear!'
railties (8.0.0.rc1) lib/rails/application/routes_reloader.rb:25:in `reload!'
railties (8.0.0.rc1) lib/rails/application/routes_reloader.rb:48:in `block in updater'
activesupport (8.0.0.rc1) lib/active_support/file_update_checker.rb:85:in `execute'
railties (8.0.0.rc1) lib/rails/application/routes_reloader.rb:13:in `execute'
railties (8.0.0.rc1) lib/rails/application/routes_reloader.rb:35:in `execute_unless_loaded'
railties (8.0.0.rc1) lib/rails/application.rb:165:in `reload_routes_unless_loaded'
railties (8.0.0.rc1) lib/rails/engine/lazy_route_set.rb:67:in `call'
rack (3.1.8) lib/rack/tempfile_reaper.rb:20:in `call'
rack (3.1.8) lib/rack/etag.rb:29:in `call'
rack (3.1.8) lib/rack/conditional_get.rb:31:in `call'
rack (3.1.8) lib/rack/head.rb:15:in `call'
actionpack (8.0.0.rc1) lib/action_dispatch/http/permissions_policy.rb:38:in `call'
actionpack (8.0.0.rc1) lib/action_dispatch/http/content_security_policy.rb:35:in `call'
rack-session (2.0.0) lib/rack/session/abstract/id.rb:272:in `context'
rack-session (2.0.0) lib/rack/session/abstract/id.rb:266:in `call'
actionpack (8.0.0.rc1) lib/action_dispatch/middleware/cookies.rb:706:in `call'
activerecord (8.0.0.rc1) lib/active_record/migration.rb:671:in `call'
actionpack (8.0.0.rc1) lib/action_dispatch/middleware/callbacks.rb:31:in `block in call'
activesupport (8.0.0.rc1) lib/active_support/callbacks.rb:100:in `run_callbacks'
actionpack (8.0.0.rc1) lib/action_dispatch/middleware/callbacks.rb:30:in `call'
actionpack (8.0.0.rc1) lib/action_dispatch/middleware/executor.rb:16:in `call'
actionpack (8.0.0.rc1) lib/action_dispatch/middleware/actionable_exceptions.rb:18:in `call'
actionpack (8.0.0.rc1) lib/action_dispatch/middleware/debug_exceptions.rb:31:in `call'
web-console (4.2.1) lib/web_console/middleware.rb:132:in `call_app'
web-console (4.2.1) lib/web_console/middleware.rb:28:in `block in call'
<internal:core> core/throw_catch.rb:36:in `catch'
web-console (4.2.1) lib/web_console/middleware.rb:17:in `call'
actionpack (8.0.0.rc1) lib/action_dispatch/middleware/show_exceptions.rb:32:in `call'
railties (8.0.0.rc1) lib/rails/rack/logger.rb:41:in `call_app'
railties (8.0.0.rc1) lib/rails/rack/logger.rb:29:in `call'
actionpack (8.0.0.rc1) lib/action_dispatch/middleware/remote_ip.rb:96:in `call'
actionpack (8.0.0.rc1) lib/action_dispatch/middleware/request_id.rb:34:in `call'
rack (3.1.8) lib/rack/method_override.rb:28:in `call'
rack (3.1.8) lib/rack/runtime.rb:24:in `call'
actionpack (8.0.0.rc1) lib/action_dispatch/middleware/server_timing.rb:61:in `block in call'
actionpack (8.0.0.rc1) lib/action_dispatch/middleware/server_timing.rb:26:in `collect_events'
actionpack (8.0.0.rc1) lib/action_dispatch/middleware/server_timing.rb:60:in `call'
actionpack (8.0.0.rc1) lib/action_dispatch/middleware/executor.rb:16:in `call'
actionpack (8.0.0.rc1) lib/action_dispatch/middleware/static.rb:27:in `call'
rack (3.1.8) lib/rack/sendfile.rb:114:in `call'
actionpack (8.0.0.rc1) lib/action_dispatch/middleware/host_authorization.rb:143:in `call'
railties (8.0.0.rc1) lib/rails/engine.rb:535:in `call'
puma (6.4.3) lib/puma/configuration.rb:272:in `call'
puma (6.4.3) lib/puma/request.rb:100:in `block in handle_request'
puma (6.4.3) lib/puma/thread_pool.rb:378:in `with_force_shutdown'
puma (6.4.3) lib/puma/request.rb:99:in `handle_request'
puma (6.4.3) lib/puma/server.rb:464:in `process_client'
puma (6.4.3) lib/puma/server.rb:245:in `block in run'
puma (6.4.3) lib/puma/thread_pool.rb:155:in `block in spawn_thread'`
=> Booting Puma
=> Rails 8.0.0.rc1 application starting in development
=> Run `bin/rails server --help` for more startup options
Puma starting in single mode...
* Puma version: 6.4.3 (truffleruby 24.2.0-dev-5aa58980 - ruby 3.2.4) ("The Eagle of Durango")

The workaround gem "zeitwerk", "< 2.7" is still working

@andrykonchin
Copy link
Member

andrykonchin commented Oct 22, 2024

Cannot reproduce the issue mentioned above with Rails 8.0.0.rc1 and rails s on a just generated application (checked Rails 7.2 as well).

Rails 8.0.0.rc1:

$ rails s
=> Booting Puma
=> Rails 8.0.0.rc1 application starting in development
=> Run `bin/rails server --help` for more startup options
Puma starting in single mode...
* Puma version: 6.4.3 (truffleruby 24.2.0-dev-44ded821 - ruby 3.2.4) ("The Eagle of Durango")
*  Min threads: 3
*  Max threads: 3
*  Environment: development
*          PID: 44411
* Listening on http://127.0.0.1:3000
* Listening on http://[::1]:3000
Use Ctrl-C to stop
^C- Gracefully stopping, waiting for requests to finish
=== puma shutdown: 2024-10-22 21:16:10 +0300 ===
- Goodbye!
Exiting

$ gem list | grep zei
zeitwerk (2.7.1)

Rails 7.2.1.1:

rails s
=> Booting Puma
=> Rails 7.2.1.1 application starting in development
=> Run `bin/rails server --help` for more startup options
Puma starting in single mode...
* Puma version: 6.4.3 (truffleruby 24.2.0-dev-44ded821 - ruby 3.2.4) ("The Eagle of Durango")
*  Min threads: 3
*  Max threads: 3
*  Environment: development
*          PID: 43165
* Listening on http://127.0.0.1:3000
* Listening on http://[::1]:3000
Use Ctrl-C to stop
^C- Gracefully stopping, waiting for requests to finish
=== puma shutdown: 2024-10-22 21:08:57 +0300 ===
- Goodbye!
Exiting

$ gem list | grep zei
zeitwerk (2.7.1)

@bachos
Copy link

bachos commented Oct 22, 2024

Did you click http://127.0.0.1:3000?

The exception is thrown when you click to the above URL.

@fxn
Copy link
Author

fxn commented Oct 22, 2024

Seems related.

The test suite of Zeitwerk passes with truffleruby-head, could it be something that has drifted?

I have also added a workflow to run the test suite against TruffleRuby HEAD daily. I have a similar one for CRuby HEAD.

@fxn
Copy link
Author

fxn commented Oct 22, 2024

If you want a faster way to reproduce, this should suffice:

% ruby -raction_cable -e ActionCable::Server

should trigger the error. The key point is that ActionCable is an explicit namespace. If const_added is not doing its thing, child constants do not get autoloaded.

@eregon
Copy link
Member

eregon commented Oct 23, 2024

@bachos

  • Puma version: 6.4.3 (truffleruby 24.2.0-dev-5aa58980 - ruby 3.2.4) ("The Eagle of Durango")

That's 5aa5898 it's before the fix 495a0e5 so you need a newer version of truffleruby-dev than what you are using.

@andrykonchin
Copy link
Member

andrykonchin commented Oct 23, 2024

Did you click http://127.0.0.1:3000/?

The exception is thrown when you click to the above URL.

Right, thank you for clarification.

If you want a faster way to reproduce, this should suffice:

% ruby -raction_cable -e ActionCable::Server

Thank you!

I've checked again (on 44ded82) and don't reproduce the issue:

$ bin/rails s
=> Booting Puma
=> Rails 8.0.0.rc1 application starting in development
=> Run `bin/rails server --help` for more startup options
Puma starting in single mode...
* Puma version: 6.4.3 (truffleruby 24.2.0-dev-44ded821 - ruby 3.2.4) ("The Eagle of Durango")
*  Min threads: 3
*  Max threads: 3
*  Environment: development
*          PID: 28074
* Listening on http://127.0.0.1:3000
* Listening on http://[::1]:3000
Use Ctrl-C to stop
Started GET "/" for 127.0.0.1 at 2024-10-23 12:44:19 +0300
   (2.4ms)  CREATE TABLE "schema_migrations" ("version" varchar NOT NULL PRIMARY KEY) /*application='KyivHawk'*/
   (2.0ms)  CREATE TABLE "ar_internal_metadata" ("key" varchar NOT NULL PRIMARY KEY, "value" varchar, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL) /*application='KyivHawk'*/
  ActiveRecord::SchemaMigration Load (2.0ms)  SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC /*application='KyivHawk'*/
Processing by Rails::WelcomeController#index as HTML
  Rendering /Users/andrykonchin/projects/truffleruby-ws/truffleruby/mxbuild/truffleruby-jvm/lib/gems/gems/railties-8.0.0.rc1/lib/rails/templates/rails/welcome/index.html.erb
  Rendered /Users/andrykonchin/projects/truffleruby-ws/truffleruby/mxbuild/truffleruby-jvm/lib/gems/gems/railties-8.0.0.rc1/lib/rails/templates/rails/welcome/index.html.erb (Duration: 12.3ms | GC: 0.0ms)
Completed 200 OK in 825ms (Views: 31.6ms | ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 12.0ms)


^C- Gracefully stopping, waiting for requests to finish
=== puma shutdown: 2024-10-23 12:44:27 +0300 ===
- Goodbye!
Exiting
$ ruby -vraction_cable -e ActionCable::Server
truffleruby 24.2.0-dev-44ded821, like ruby 3.2.4, Interpreted JVM [x86_64-darwin23]
-e:1: warning: possibly useless use of :: in void context
$ gem list | grep zeit
zeitwerk (2.7.1)

@bachos Is the issue reproducible in your environment on the TruffleRuby master?

@bachos
Copy link

bachos commented Oct 23, 2024

I got 5aa58980 from rbenv ruby-build plugin (rbenv install truffleruby+graalvm-dev that is), would you mind updating that version to the latest ?

@bachos
Copy link

bachos commented Oct 23, 2024

Looks like truffleruby-jvm-24.2.0-ea.18-linux-amd64.tar.gz was made available but it is based 0e05bfe. 😿

@eregon
Copy link
Member

eregon commented Oct 23, 2024

Could you try rbenv install truffleruby-dev? That's recent enough.

truffleruby+graalvm-dev is updated weekly (from https://github.com/graalvm/graal-languages-ea-builds/releases)

@bachos
Copy link

bachos commented Oct 23, 2024

Could you try rbenv install truffleruby-dev?

It is working, thanks a lot.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment