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

sync: LoadError: cannot load such file -- RMagick #237

Closed
jaredbeck opened this issue Feb 24, 2021 · 5 comments · Fixed by #252
Closed

sync: LoadError: cannot load such file -- RMagick #237

jaredbeck opened this issue Feb 24, 2021 · 5 comments · Fixed by #252
Assignees
Labels
bug Something isn't working

Comments

@jaredbeck
Copy link

Trying to install tapioca for the first time, sync was unable to compile carrierwave.

My app does not use RMagick. RMagick is not a runtime dependency of CarrierWave.

bundle exec tapioca -v
Tapioca v0.4.14
bundle exec tapioca sync
...
  Compiling carrierwave, this may take a few seconds... bundler: failed to load command: tapioca (/Users/jared/.rbenv/versions/2.6.6/bin/tapioca)
LoadError: cannot load such file -- RMagick
..../ruby/gems/2.6.0/gems/activesupport-6.1.3/lib/active_support/dependencies.rb:332:in `require'
..../ruby/gems/2.6.0/gems/activesupport-6.1.3/lib/active_support/dependencies.rb:332:in `block in require'
..../ruby/gems/2.6.0/gems/activesupport-6.1.3/lib/active_support/dependencies.rb:299:in `load_dependency'
..../ruby/gems/2.6.0/gems/activesupport-6.1.3/lib/active_support/dependencies.rb:332:in `require'
..../ruby/gems/2.6.0/gems/carrierwave-2.1.1/lib/carrierwave/processing/rmagick.rb:65:in `rescue in block in <module:RMagick>'
..../ruby/gems/2.6.0/gems/carrierwave-2.1.1/lib/carrierwave/processing/rmagick.rb:62:in `block in <module:RMagick>'
..../ruby/gems/2.6.0/gems/activesupport-6.1.3/lib/active_support/concern.rb:136:in `class_eval'
..../ruby/gems/2.6.0/gems/activesupport-6.1.3/lib/active_support/concern.rb:136:in `append_features'
..../ruby/gems/2.6.0/gems/tapioca-0.4.14/lib/tapioca/compilers/symbol_table/symbol_generator.rb:349:in `include'
..../ruby/gems/2.6.0/gems/tapioca-0.4.14/lib/tapioca/compilers/symbol_table/symbol_generator.rb:349:in `block (2 levels) in compile_mixes_in_class_methods'
..../ruby/gems/2.6.0/gems/tapioca-0.4.14/lib/tapioca/compilers/symbol_table/symbol_generator.rb:359:in `compile_mixes_in_class_methods'
..../ruby/gems/2.6.0/gems/tapioca-0.4.14/lib/tapioca/compilers/symbol_table/symbol_generator.rb:184:in `block in compile_body'
..../ruby/gems/2.6.0/gems/tapioca-0.4.14/lib/tapioca/compilers/symbol_table/symbol_generator.rb:634:in `with_indentation'
..../ruby/gems/2.6.0/gems/tapioca-0.4.14/lib/tapioca/compilers/symbol_table/symbol_generator.rb:176:in `compile_body'
..../ruby/gems/2.6.0/gems/tapioca-0.4.14/lib/tapioca/compilers/symbol_table/symbol_generator.rb:162:in `compile_module'
..../ruby/gems/2.6.0/gems/tapioca-0.4.14/lib/tapioca/compilers/symbol_table/symbol_generator.rb:114:in `compile_constant'
..../ruby/gems/2.6.0/gems/tapioca-0.4.14/lib/tapioca/compilers/symbol_table/symbol_generator.rb:100:in `compile'
..../ruby/gems/2.6.0/gems/tapioca-0.4.14/lib/tapioca/compilers/symbol_table/symbol_generator.rb:231:in `block in compile_subconstants'
..../ruby/gems/2.6.0/gems/tapioca-0.4.14/lib/tapioca/compilers/symbol_table/symbol_generator.rb:222:in `map'
..../ruby/gems/2.6.0/gems/tapioca-0.4.14/lib/tapioca/compilers/symbol_table/symbol_generator.rb:222:in `compile_subconstants'
..../ruby/gems/2.6.0/gems/tapioca-0.4.14/lib/tapioca/compilers/symbol_table/symbol_generator.rb:170:in `compile_module'
..../ruby/gems/2.6.0/gems/tapioca-0.4.14/lib/tapioca/compilers/symbol_table/symbol_generator.rb:114:in `compile_constant'
..../ruby/gems/2.6.0/gems/tapioca-0.4.14/lib/tapioca/compilers/symbol_table/symbol_generator.rb:100:in `compile'
..../ruby/gems/2.6.0/gems/tapioca-0.4.14/lib/tapioca/compilers/symbol_table/symbol_generator.rb:74:in `generate_from_symbol'
..../ruby/gems/2.6.0/gems/tapioca-0.4.14/lib/tapioca/compilers/symbol_table/symbol_generator.rb:32:in `block in generate'
..../ruby/gems/2.6.0/gems/tapioca-0.4.14/lib/tapioca/compilers/symbol_table/symbol_generator.rb:32:in `map'
..../ruby/gems/2.6.0/gems/tapioca-0.4.14/lib/tapioca/compilers/symbol_table/symbol_generator.rb:32:in `generate'
..../ruby/gems/2.6.0/gems/tapioca-0.4.14/lib/tapioca/compilers/symbol_table_compiler.rb:19:in `compile'
..../ruby/gems/2.6.0/gems/tapioca-0.4.14/lib/tapioca/generator.rb:434:in `compile_gem_rbi'
..../ruby/gems/2.6.0/gems/tapioca-0.4.14/lib/tapioca/generator.rb:380:in `block (2 levels) in perform_additions'
..../ruby/gems/2.6.0/gems/tapioca-0.4.14/lib/tapioca/generator.rb:371:in `each'
..../ruby/gems/2.6.0/gems/tapioca-0.4.14/lib/tapioca/generator.rb:371:in `block in perform_additions'
..../ruby/gems/2.6.0/gems/thor-1.1.0/lib/thor/shell/basic.rb:44:in `indent'
..../ruby/gems/2.6.0/gems/tapioca-0.4.14/lib/tapioca/generator.rb:365:in `perform_additions'
..../ruby/gems/2.6.0/gems/sorbet-runtime-0.5.6231/lib/types/private/methods/_methods.rb:233:in `call'
..../ruby/gems/2.6.0/gems/sorbet-runtime-0.5.6231/lib/types/private/methods/_methods.rb:233:in `block in _on_method_added'
..../ruby/gems/2.6.0/gems/tapioca-0.4.14/lib/tapioca/generator.rb:150:in `sync_rbis_with_gemfile'
..../ruby/gems/2.6.0/gems/sorbet-runtime-0.5.6231/lib/types/private/methods/_methods.rb:233:in `call'
..../ruby/gems/2.6.0/gems/sorbet-runtime-0.5.6231/lib/types/private/methods/_methods.rb:233:in `block in _on_method_added'
..../ruby/gems/2.6.0/gems/tapioca-0.4.14/lib/tapioca/cli.rb:93:in `block in sync'
..../ruby/gems/2.6.0/gems/tapioca-0.4.14/lib/tapioca.rb:11:in `block in silence_warnings'
..../ruby/2.6.0/rubygems/user_interaction.rb:47:in `use_ui'
..../ruby/gems/2.6.0/gems/tapioca-0.4.14/lib/tapioca.rb:10:in `silence_warnings'
..../ruby/gems/2.6.0/gems/tapioca-0.4.14/lib/tapioca/cli.rb:92:in `sync'
..../ruby/gems/2.6.0/gems/thor-1.1.0/lib/thor/command.rb:27:in `run'
..../ruby/gems/2.6.0/gems/thor-1.1.0/lib/thor/invocation.rb:127:in `invoke_command'
..../ruby/gems/2.6.0/gems/thor-1.1.0/lib/thor.rb:392:in `dispatch'
..../ruby/gems/2.6.0/gems/thor-1.1.0/lib/thor/base.rb:485:in `start'
..../ruby/gems/2.6.0/gems/tapioca-0.4.14/exe/tapioca:6:in `<top (required)>'
..../bin/tapioca:23:in `load'
..../bin/tapioca:23:in `<top (required)>'
@paracycle paracycle self-assigned this Feb 24, 2021
@paracycle
Copy link
Member

Ouch, thanks for this report and sorry that your first time experience failed in this way.

I know why this is failing, but not sure about the fix. There is a place in Tapioca where we try to discover the mixed-in class methods modules of a module by including all modules into a temporary class and checking the diff between the ancestors.

The failure is happening there for the CarrierWave::RMagick module, since CarrierWave::RMagick tries to require RMagick gem when included.

I guess we could skip that operation if the module is a concern, since we know the exact class that concerns mixin anyway.

I'll try to get this fixed this week.

@paracycle paracycle added the bug Something isn't working label Feb 24, 2021
@jaredbeck
Copy link
Author

Hey, no worries 😄 It's free software!

There is a place in Tapioca where we try to discover the mixed-in class methods .. of a module by including all modules into a temporary class and checking the diff between the ancestors.

🤯 Dynamic analysis of ruby is .. wow. ❤️ This is not an easy problem

I guess we could skip that operation if the module is a concern, since we know the exact class that concerns mixin anyway.

Like a blocklist? Or maybe rescue the LoadError and print a warning?

@paracycle
Copy link
Member

Sorry, I am super late in responding to this but I aim to merge a fix for this and release a version today or tomorrow.

🤯 Dynamic analysis of ruby is .. wow. ❤️ This is not an easy problem

😅 Yeah, it's been a ride. (Shameless plug: I did talk about some of our experiences doing that in my RubyKaigi 2020 talk in case you are interested)

Like a blocklist? Or maybe rescue the LoadError and print a warning?

I think we have special handling for ActiveSupport::Concern modules and I think we can special case those to return early which will fix this. But, in general, I think we would have to rescue LoadErrors to make it safe for all weird operations.

paracycle added a commit that referenced this issue Mar 9, 2021
We try to do something sneaky to detect modules that are mixed into a
class through inclusion of another module, where we try to infer that
information from the change in the ancestor list of a test class after
including the said module to that class.

However, that operation is risky since a `self.included` method on the
target module could potentially run any Ruby code and it turns out some
code in the wild even try to require optional gems when the concern is
being included.

Since this detection is best effort, it should be fine to catch
all kinds of `Exception`s and bail out of the operation without
side-effects.

Fixes: #237
@paracycle
Copy link
Member

This was released as part of v0.4.16, thanks for reporting the error.

@jaredbeck
Copy link
Author

I did talk about some of our experiences doing that in my RubyKaigi 2020 talk in case you are interested

Nice talk! The "Pitfalls" were scary. It's amazing some of the things people do with ruby. sigh I hope that, as type-checking becomes more popular, such antics will become less popular.

This was referenced Mar 10, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment