You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
For classes that redefine their singleton class #inspect method (e.g. ActiveRecord::Base, ActiveRecord::SchemaMigration, and ActiveRecord::InternalMetadata all override with connection information), Tapioca cannot constantize the string into a module, leading to a TypeError down the chain when attempting to handle mixins for those constants.
This pops up in cases where gems monkey-patch those classes. When you run tapioca gem <affected_gem>, you end up with the following style of stacktrace.
Stacktrace of error
/Users/herold/.gem/ruby/3.1.2/gems/tapioca-0.9.2/lib/tapioca/runtime/reflection.rb:61:in `bind_call': bind argument must be an instance of Module (TypeError)
from /Users/herold/.gem/ruby/3.1.2/gems/tapioca-0.9.2/lib/tapioca/runtime/reflection.rb:61:in `ancestors_of'
from /Users/herold/.gem/ruby/3.1.2/gems/tapioca-0.9.2/lib/tapioca/gem/listeners/mixins.rb:115:in `interesting_ancestors_of'
from /Users/herold/.gem/ruby/3.1.2/gems/tapioca-0.9.2/lib/tapioca/gem/listeners/mixins.rb:19:in `on_scope'
from /Users/herold/.gem/ruby/3.1.2/gems/tapioca-0.9.2/lib/tapioca/gem/listeners/base.rb:26:in `dispatch'
from /Users/herold/.gem/ruby/3.1.2/gems/tapioca-0.9.2/lib/tapioca/gem/pipeline.rb:188:in `block in on_node'
from /Users/herold/.gem/ruby/3.1.2/gems/tapioca-0.9.2/lib/tapioca/gem/pipeline.rb:188:in `each'
from /Users/herold/.gem/ruby/3.1.2/gems/tapioca-0.9.2/lib/tapioca/gem/pipeline.rb:188:in `on_node'
from /Users/herold/.gem/ruby/3.1.2/gems/tapioca-0.9.2/lib/tapioca/gem/pipeline.rb:153:in `dispatch'
from /Users/herold/.gem/ruby/3.1.2/gems/tapioca-0.9.2/lib/tapioca/gem/pipeline.rb:49:in `compile'
from /Users/herold/.gem/ruby/3.1.2/gems/sorbet-runtime-0.5.10263/lib/types/private/methods/_methods.rb:272:in `bind_call'
from /Users/herold/.gem/ruby/3.1.2/gems/sorbet-runtime-0.5.10263/lib/types/private/methods/_methods.rb:272:in `block in _on_method_added'
from /Users/herold/.gem/ruby/3.1.2/gems/tapioca-0.9.2/lib/tapioca/commands/gem.rb:188:in `compile_gem_rbi'
from /Users/herold/.gem/ruby/3.1.2/gems/sorbet-runtime-0.5.10263/lib/types/private/methods/_methods.rb:272:in `bind_call'
from /Users/herold/.gem/ruby/3.1.2/gems/sorbet-runtime-0.5.10263/lib/types/private/methods/_methods.rb:272:in `block in _on_method_added'
from /Users/herold/.gem/ruby/3.1.2/gems/tapioca-0.9.2/lib/tapioca/commands/gem.rb:79:in `block (2 levels) in execute'
from /Users/herold/.gem/ruby/3.1.2/gems/thor-1.2.1/lib/thor/shell/basic.rb:44:in `indent'
from /Users/herold/.gem/ruby/3.1.2/gems/tapioca-0.9.2/lib/tapioca/commands/gem.rb:78:in `block in execute'
from /Users/herold/.gem/ruby/3.1.2/gems/parallel-1.22.1/lib/parallel.rb:587:in `call_with_index'
from /Users/herold/.gem/ruby/3.1.2/gems/parallel-1.22.1/lib/parallel.rb:354:in `block in work_direct'
from /Users/herold/.gem/ruby/3.1.2/gems/parallel-1.22.1/lib/parallel.rb:597:in `with_instrumentation'
from /Users/herold/.gem/ruby/3.1.2/gems/parallel-1.22.1/lib/parallel.rb:353:in `work_direct'
from /Users/herold/.gem/ruby/3.1.2/gems/parallel-1.22.1/lib/parallel.rb:288:in `map'
from /Users/herold/.gem/ruby/3.1.2/gems/tapioca-0.9.2/lib/tapioca/executor.rb:31:in `run_in_parallel'
from /Users/herold/.gem/ruby/3.1.2/gems/sorbet-runtime-0.5.10263/lib/types/private/methods/_methods.rb:272:in `bind_call'
from /Users/herold/.gem/ruby/3.1.2/gems/sorbet-runtime-0.5.10263/lib/types/private/methods/_methods.rb:272:in `block in _on_method_added'
from /Users/herold/.gem/ruby/3.1.2/gems/tapioca-0.9.2/lib/tapioca/commands/gem.rb:77:in `execute'
from /Users/herold/.gem/ruby/3.1.2/gems/sorbet-runtime-0.5.10263/lib/types/private/methods/_methods.rb:272:in `bind_call'
from /Users/herold/.gem/ruby/3.1.2/gems/sorbet-runtime-0.5.10263/lib/types/private/methods/_methods.rb:272:in `block in _on_method_added'
from /Users/herold/.gem/ruby/3.1.2/gems/tapioca-0.9.2/lib/tapioca/cli.rb:265:in `block in gem'
from /Users/herold/.gem/ruby/3.1.2/gems/tapioca-0.9.2/lib/tapioca.rb:18:in `block in silence_warnings'
from /opt/rubies/3.1.2/lib/ruby/3.1.0/rubygems/user_interaction.rb:46:in `use_ui'
from /Users/herold/.gem/ruby/3.1.2/gems/tapioca-0.9.2/lib/tapioca.rb:17:in `silence_warnings'
from /Users/herold/.gem/ruby/3.1.2/gems/sorbet-runtime-0.5.10263/lib/types/private/methods/_methods.rb:272:in `bind_call'
from /Users/herold/.gem/ruby/3.1.2/gems/sorbet-runtime-0.5.10263/lib/types/private/methods/_methods.rb:272:in `block in _on_method_added'
from /Users/herold/.gem/ruby/3.1.2/gems/tapioca-0.9.2/lib/tapioca/cli.rb:225:in `gem'
from /Users/herold/.gem/ruby/3.1.2/gems/thor-1.2.1/lib/thor/command.rb:27:in `run'
from /Users/herold/.gem/ruby/3.1.2/gems/thor-1.2.1/lib/thor/invocation.rb:127:in `invoke_command'
from /Users/herold/.gem/ruby/3.1.2/gems/thor-1.2.1/lib/thor.rb:392:in `dispatch'
from /Users/herold/.gem/ruby/3.1.2/gems/thor-1.2.1/lib/thor/base.rb:485:in `start'
from /Users/herold/.gem/ruby/3.1.2/gems/tapioca-0.9.2/exe/tapioca:23:in `<top (required)>'
from bin/tapioca:29:in `load'
from bin/tapioca:29:in `<main>'
In this example, Tapioca::Runtime::Trackers::Mixin ends up with a constants_with_mixin hash with ActiveRecord::SchemaMigration (call 'ActiveRecord::SchemaMigration.connection' to establish a connection) as the key. This, in turn, gets fed through constantize and can't be converted into the correct class, thus ending up with a nil as the constant in the Tapioca::Gem::Event::ForeignConstantFound event.
I attempted a naive patch to remove /\s+.*/ from the name, but that ended up creating syntax errors in the generated RBI file since the original name gets output to the file. Maybe if we sanitize it higher in the stack?
I have a minimal reproduction project available that uses an internal Shopify gem to reproduce the bug if you'd like me to upload that.
I attempted to write a test reproducing the issue. The stacktrace I get is slightly different but I think it stems from the same problem. Does this test accurately capture your issue?
It might stem from the same problem, but the error is presenting differently so I'm not sure! Since this doesn't crash, it feels like it might be different.
I pushed this repo as a minimal reproduction for you. I couldn't figure out how to write a test that showed the behavior so I did this to play around!
For classes that redefine their singleton class
#inspect
method (e.g.ActiveRecord::Base
,ActiveRecord::SchemaMigration
, andActiveRecord::InternalMetadata
all override with connection information), Tapioca cannot constantize the string into a module, leading to aTypeError
down the chain when attempting to handle mixins for those constants.This pops up in cases where gems monkey-patch those classes. When you run
tapioca gem <affected_gem>
, you end up with the following style of stacktrace.Stacktrace of error
In this example,
Tapioca::Runtime::Trackers::Mixin
ends up with aconstants_with_mixin
hash withActiveRecord::SchemaMigration (call 'ActiveRecord::SchemaMigration.connection' to establish a connection)
as the key. This, in turn, gets fed throughconstantize
and can't be converted into the correct class, thus ending up with anil
as the constant in theTapioca::Gem::Event::ForeignConstantFound
event.I attempted a naive patch to remove
/\s+.*/
from the name, but that ended up creating syntax errors in the generated RBI file since the original name gets output to the file. Maybe if we sanitize it higher in the stack?I have a minimal reproduction project available that uses an internal Shopify gem to reproduce the bug if you'd like me to upload that.
cc @vahe
The text was updated successfully, but these errors were encountered: