Skip to content

Avoid loading unused ActiveSupport::Configurable during reflection - #2748

Open
thomasklemm wants to merge 2 commits into
Shopify:mainfrom
thomasklemm:fix/skip-unused-active-support-configurable
Open

thomasklemm wants to merge 2 commits into
Shopify:mainfrom
thomasklemm:fix/skip-unused-active-support-configurable

Conversation

@thomasklemm

Copy link
Copy Markdown

Motivation

On Rails 8.1, generating gem RBIs can emit ActiveSupport::Configurable is deprecated without replacement, and will be removed in Rails 8.2 even when the application never uses that API. With deprecations configured to raise, generation fails instead.

Rails deliberately removed Configurable from its eager autoloads in rails/rails#55943: its plain autoload must remain available, but loading the file emits the deprecation. Tapioca's autoload tracker currently forces it anyway. This reproduces on current main and 0.20.0; it is a different mechanism from the deprecated constant proxies addressed in #2701.

Minimal reproduction with Tapioca and Active Support 8.1.4 in the bundle:

require "tapioca/internal"
require "active_support"
ActiveSupport.deprecator.behavior = :raise
Tapioca::Runtime::Trackers::Autoload.eager_load_all!

Implementation

Leave the Rails 8.1+ Configurable autoload pending when reflecting on its fully qualified name or descendants. Do not remove the constant, silence deprecations, or skip already-loaded Configurable APIs. Rails 8.0 keeps its existing behavior.

The guard lives immediately before const_get in Runtime::Reflection.constantize, rather than only in the autoload tracker. I tested a tracker-only skip first: eager loading then succeeded, but real tapioca gem activesupport still failed in Gem::Pipeline#on_symbol. The gem compiler separately resolves statically discovered symbols and subconstants through the same reflection helper, so protecting the common lookup avoids another forced load later in generation.

No configuration or new public API is added. Other autoloads still load normally. Explicit application usage still emits the Rails deprecation and generates Configurable RBIs; namespaced lookups for unrelated constants remain unaffected.

Tests

  • Added a real-gem CLI regression test: generate Active Support RBIs with deprecations set to raise, verify the Configurable autoload is unchanged, and check another autoloaded API is generated. It failed with ActiveSupport::DeprecationException before the fix and passes after it.
  • Added a positive control: explicit Configurable usage still warns and its RBI is generated.
  • Gem CLI specs (bin/test spec/tapioca/runtime spec/tapioca/cli/gem_spec.rb): 79 tests, 571 assertions, no failures/errors, one pre-existing skip.
  • bin/test spec/tapioca/runtime/*_spec.rb: 31 tests, 71 assertions, no failures/errors/skips. Runtime specs were run explicitly because the Rails runner's directory expansion only matches _test.rb, not _spec.rb.
  • bin/test spec/tapioca/dsl/compilers/active_support_concern_spec.rb: 12 tests, 42 assertions, no failures/errors/skips.
  • bin/style lib/tapioca/runtime/reflection.rb spec/tapioca/cli/gem_spec.rb: no offenses.
  • bin/typecheck: no errors. Ruby syntax checks and git diff --check also pass.
  • Separate disposable, initialized Rails 8.1.4 application: bundle exec tapioca gems --all --no-doc --no-loc --workers 1 succeeds with deprecations set to raise, generates 73 RBI files, and leaves Configurable pending while loading BacktraceCleaner.
  • Additional process-isolated boundary checks pass with Active Support 8.1.4 and 8.0.5.1, including root-qualified/nested names, an unrelated shadowing namespace, and explicit usage after eager loading.

Local verification used Ruby 4.0.7 and the repository lockfile (Rails 8.1.4); the full hosted Ruby/Rails matrix is left to CI. A maintainer will need to add the bugfix release label.

Leave the deprecated Rails 8.1 API pending instead of triggering its
load-time deprecation while eager loading or compiling gem symbols.
Keep explicit usage warnings and already-loaded APIs intact.
@thomasklemm
thomasklemm requested a review from a team as a code owner October 20, 2026 11:42
@thomasklemm
thomasklemm force-pushed the fix/skip-unused-active-support-configurable branch from b308489 to 272facd Compare October 20, 2026 12:59

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant