Before asking your question, please make sure these are true:
[x] I have read the Troubleshooting guide.
[x] I have tried searching the docs for an answer.
[x] I have tried to reproduce the behavior I'm seeing on sorbet.run:
[x] I have read (or at least skimmed) How to ask good questions by Julia Evans
Great, thanks! Now by all means, ask away:
srb init fails for me with the following errors...
/var/folders/zm/tns9x8rj0vjcbtnf1xmhlbyh0000gn/T/d20190621-72368-1sf5wos/reflection.rbi:232081: Circular dependency: `EventMachine::WebMockHttpClient` is a parent of itself https://srb.help/5011
232081 |class EventMachine::WebMockHttpClient < EventMachine::HttpClient
^^^^^^^^^^^^^^^^^^^^^^^^
/var/folders/zm/tns9x8rj0vjcbtnf1xmhlbyh0000gn/T/d20190621-72368-1sf5wos/reflection.rbi:232081: Class definition
232081 |class EventMachine::WebMockHttpClient < EventMachine::HttpClient
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/var/folders/zm/tns9x8rj0vjcbtnf1xmhlbyh0000gn/T/d20190621-72368-1sf5wos/reflection.rbi:232128: Circular dependency: `EventMachine::WebMockHttpConnection` is a parent of itself https://srb.help/5011
232128 |class EventMachine::WebMockHttpConnection < EventMachine::HttpConnection
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/var/folders/zm/tns9x8rj0vjcbtnf1xmhlbyh0000gn/T/d20190621-72368-1sf5wos/reflection.rbi:232128: Class definition
232128 |class EventMachine::WebMockHttpConnection < EventMachine::HttpConnection
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/var/folders/zm/tns9x8rj0vjcbtnf1xmhlbyh0000gn/T/d20190621-72368-1sf5wos/reflection.rbi:364771: Class parents redefined for class `Net::InternetMessageIO` https://srb.help/5012
364771 |class Net::InternetMessageIO < Net::BufferedIO
^^^^^^^^^^^^^^^
/var/folders/zm/tns9x8rj0vjcbtnf1xmhlbyh0000gn/T/d20190621-72368-1sf5wos/reflection.rbi:365772: Circular dependency: `Net::WebMockNetBufferedIO` is a parent of itself https://srb.help/5011
365772 |class Net::WebMockNetBufferedIO < Net::BufferedIO
^^^^^^^^^^^^^^^
/var/folders/zm/tns9x8rj0vjcbtnf1xmhlbyh0000gn/T/d20190621-72368-1sf5wos/reflection.rbi:365772: Class definition
365772 |class Net::WebMockNetBufferedIO < Net::BufferedIO
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
These are not definitions within my codebase, but (I assume) things that are done in gems that my application depends on. Is there a workaround for this that doesn't involve removing the dependency?
It doesn't seem like adding # typed: ignore to the top of the relevant file in vendor/ stops sorbet from running the file.
Currently, the available fixes as far as I can tell are:
Gemfile, bundle install, and then run init again. Then you can add the gem again afterward, but you'll have to remove the gem every time you want to update your gems' type definitions.I'm not sure if Sorbet should respect # typed: ignore in a gem's files and I'm just doing something wrong? Or if a preferable workaround would be to add some sort of constant/special comment that tells Sorbet not to try to run the given file when init-ing.
Should Sorbet have a way for users to blacklist a gem? Or even a specific file within a gem?
This is somewhat related to #925 as well (or potentially the solution could solve both issues)
Here's an attempt at a reproducible example:
mkdir test;
cd test;
bundle init;
bundle add rails;
rails new test-app;
srb init; # Answer 'Y'; Passes
bundle add dotenv-rails;
srb init; # Answer 'Y'; Fails
The error it gives after adding dotenv-rails dependency is:
Generating: sorbet/config
Generating: sorbet/rbi/sorbet-typed/
Generating: sorbet/rbi/gems/
Traceback (most recent call last):
16: from /Users/dave/.rvm/gems/ruby-2.6.3/gems/sorbet-0.4.4413/bin/srb-rbi:234:in `<main>'
15: from /Users/dave/.rvm/gems/ruby-2.6.3/gems/sorbet-0.4.4413/bin/srb-rbi:196:in `main'
14: from /Users/dave/.rvm/gems/ruby-2.6.3/gems/sorbet-0.4.4413/bin/srb-rbi:118:in `init'
13: from /Users/dave/.rvm/gems/ruby-2.6.3/gems/sorbet-0.4.4413/bin/srb-rbi:229:in `block in make_step'
12: from /Users/dave/.rvm/gems/ruby-2.6.3/gems/sorbet-0.4.4413/lib/gem-generator-tracepoint.rb:38:in `main'
11: from /Users/dave/.rvm/gems/ruby-2.6.3/gems/sorbet-0.4.4413/lib/gem-generator-tracepoint/tracer.rb:70:in `trace'
10: from /Users/dave/.rvm/gems/ruby-2.6.3/gems/sorbet-0.4.4413/lib/gem-generator-tracepoint.rb:39:in `block in main'
9: from /Users/dave/.rvm/gems/ruby-2.6.3/gems/sorbet-0.4.4413/lib/require_everything.rb:19:in `require_everything'
8: from /Users/dave/.rvm/gems/ruby-2.6.3/gems/sorbet-0.4.4413/lib/require_everything.rb:39:in `load_bundler'
7: from /Users/dave/.rvm/gems/ruby-2.6.3/gems/sorbet-0.4.4413/lib/gem_loader.rb:579:in `require_all_gems'
6: from /Users/dave/.rvm/gems/ruby-2.6.3/gems/sorbet-0.4.4413/lib/gem_loader.rb:579:in `each'
5: from /Users/dave/.rvm/gems/ruby-2.6.3/gems/sorbet-0.4.4413/lib/gem_loader.rb:581:in `block in require_all_gems'
4: from /Users/dave/.rvm/gems/ruby-2.6.3/gems/sorbet-0.4.4413/lib/gem_loader.rb:562:in `require_gem'
3: from /Users/dave/.rvm/gems/ruby-2.6.3/gems/sorbet-0.4.4413/lib/gem_loader.rb:562:in `require'
2: from /Users/dave/.rvm/gems/ruby-2.6.3/gems/dotenv-rails-2.7.4/lib/dotenv-rails.rb:1:in `<top (required)>'
1: from /Users/dave/.rvm/gems/ruby-2.6.3/gems/dotenv-rails-2.7.4/lib/dotenv-rails.rb:1:in `require'
/Users/dave/.rvm/gems/ruby-2.6.3/gems/dotenv-rails-2.7.4/lib/dotenv/rails.rb:19:in `<top (required)>': uninitialized constant ActiveSupport (NameError)
Though when running it in my real project, I get a failure at a different point (rails.rb:39:in 'load': undefined local variable or method 'dotenv_files' for #<Dotenv::Railtie:0x00007f907ad7b2b8> (NameError))
Adding # typed: ignore to the top of the file makes no difference — the same error is returned.
For completeness, my Gemfile is:
# frozen_string_literal: true
source "https://rubygems.org"
git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
# gem "rails"
gem "dotenv-rails", "~> 2.7"
And after modifying the dotenv-rails gem, the file looks like this:
# typed: ignore
require "dotenv"
# Fix for rspec rake tasks loading in development
#
# Dotenv loads environment variables when the Rails application is initialized.
# When running `rake`, the Rails application is initialized in development.
# Rails includes some hacks to set `RAILS_ENV=test` when running `rake test`,
# but rspec does not include the same hacks.
#
# See https://github.com/bkeepers/dotenv/issues/219
if defined?(Rake.application)
if Rake.application.top_level_tasks.grep(/^(parallel:spec|spec(:|$))/).any?
Rails.env = ENV["RAILS_ENV"] ||= "test"
end
end
# …
# REST OF FILE
# …
FYI, we thought we'd try sorbet on a brand new project with not much code using goliath gem. Out of the gate srb init failed and the output did not give any clear indications as to the reasons (not a good developer experience). After digging into some logs and determined it was because sorbet was reporting Circular dependencies on multiple classes in the async-rack gem, which is a dependency of goliath.
For example:
# lib/async_rack/chunked.rb
module AsyncRack
class Chunked < AsyncCallback(:Chunked)
AsyncCallback is a factory class method.
# lib/async_rack/async_callback.rb
module AsyncRack
##
# @see AsyncRack::AsyncCallback
def self.AsyncCallback(name, namespace = Rack)
@wrapped ||= Hash.new { |h,k| h[k] = {} }
@wrapped[namespace][name.to_sym] ||= namespace.const_get(name).tap do |klass|
klass.extend AsyncCallback::InheritanceHook
klass.alias_subclass name, namespace
end
end
#...
We can't see a circular dependency here. This is a common pattern throughout this gem and srb init reported multiple circular dependency offenses.
Sorbet feels like I'm stuck in a dependency nightmare (again, not a good developer experience). We won't be monkey patch either gems in order to use sorbet. We quite the experiment.
Seems like a lot of good work has gone into sorbet so we wanted to share share our developer experience if it will help to improve things. We might try sorbet again sometime in the future.
A possible solution for gems requiring other gems which are not part of the bundle, would be to add require: false for this gems to your Gemfile and require these gems manually where you need to.
Sorbet seems to respect this option and will not require all files from that gem anymore:
https://github.com/sorbet/sorbet/blob/master/gems/sorbet/lib/gem_loader.rb#L569
Im circling back on this and giving sorbet another try. With require: false declared for the offending Gems, Im still seeing the same errors trying to run srb init. I was able to work around this be commenting out the offending gems in my Gemfile. This seems like alot to go through just to get rbi definitions updated (or initialized). Sorbet has been out for a while now. Does anyone know how the Teams at stripe or shopify handle this?
Having this issue as well with tilt. However, I was previously able to run srb init when I first installed sorbet. Not sure why it is failing now.
I'm having the same issue in an existing large codebase. Modifying existing gems isn't an option for us, nor can we easily remove the gems this fails on.
Is it possible to skip the generation of some or all of the RBI files? Ideally, we could exclude certain gems from automatic RBI generation and then their references in the code remain unknown/ignored until we explicitly define interfaces for them.
Having issue with sitemap_generator. sitemap_generator-6.0.1/lib/sitemap_generator/adapters/s3_adapter.rb:2:in
I had a problem with one of my dependencies, but fixed it by ignoring the path with --ignore path and adding that (with a newline in between) to sorbet/config. srb init doesn't work when you only have sorbet/config instead of an empty directory it seems, so I first ran it and aborted it early to get a proper directory structure. Perhaps this can be closed now?
@L-as could you please paste your example? I couldn't quite understand what you did there to ignore a gem.
Most helpful comment
Having issue withFog::Storage is not defined. (RuntimeError)`
sitemap_generator.sitemap_generator-6.0.1/lib/sitemap_generator/adapters/s3_adapter.rb:2:in