dsl command generates stubs in sorbet/rbi/dsl/ which are incompatible with Sorbet packages mode (--sorbet-packages)
Nobody has claimed this yet.
- Dominant language
- Ruby
- Stars
- 873
- Forks
- 164
- Avg merge
- 4d 27m
- Merged PRs (30d)
- 9
Description
Summary
When using Sorbet's experimental packages mode (--sorbet-packages), tapioca's dsl command generates DSL stubs into sorbet/rbi/dsl/. If the class being stubbed belongs to an enrolled package, Sorbet raises error 5084 ("Superclasses may only be set on constants in the package that owns them") because the stub file lives in the root package but modifies constants owned by a different enrolled package.
Background
Sorbet packages mode enforces that only the package that owns a constant can set its superclass or add mixins to it. Ownership is determined by which __package.rb's directory hierarchy the file lives under.
When a pack (e.g., packs/payments/billing/) is enrolled into packages mode via a __package.rb, its constants — including Billing::Invoice — become owned by the Billing package. Tapioca's DSL stubs for those constants live in sorbet/rbi/dsl/billing/invoice.rbi, which belongs to a root catch-all package, not to Billing.
Reproduction
Given a pack enrolled in packages mode:
packs/payments/billing/
├── __package.rb # class Billing < PackageSpec
└── app/models/
└── billing/
└── invoice.rb # class Billing::Invoice < ApplicationRecord
And tapioca's generated DSL stub:
sorbet/rbi/dsl/billing/invoice.rbi
# sorbet/rbi/dsl/billing/invoice.rbi
# typed: true
class Billing::Invoice
include GeneratedAssociationMethods # 5084 here
extend GeneratedAssociationMethods::ClassMethods # 5084 here
end
class Billing::Invoice::DraftState < Billing::Invoice # 5084 here
end
Running bin/srb tc with --sorbet-packages produces:
sorbet/rbi/dsl/billing/invoice.rbi:4: Superclasses may only be set on constants in the package that owns them https://srb.help/5084
sorbet/rbi/dsl/billing/invoice.rbi:5: `include` may only be used on constants in the package that owns them https://srb.help/5084
sorbet/rbi/dsl/billing/invoice.rbi:8: Superclasses may only be set on constants in the package that owns them https://srb.help/5084
This happens because sorbet/rbi/dsl/ belongs to the root package, while Billing::Invoice is owned by the Billing package. Sorbet's resolver enforces that only the owning package's files may set superclasses or add mixins to its constants.
Expected Behavior
Tapioca should support generating DSL stubs co-located with the pack they belong to, so that files modifying Billing::* constants live within the Billing package path:
packs/payments/billing/sorbet/rbi/dsl/billing/invoice.rbi
Proposed Solution
Add a configuration option to tapioca dsl to generate per-pack DSL stubs inside the pack directory rather than the global sorbet/rbi/dsl/ location. One approach:
-
Pack-aware routing: Detect
__package.rbfiles and, for each generated stub, check whether the constant's source file lives under a pack root. If so, write the stub to<pack_root>/sorbet/rbi/dsl/instead of the global directory. -
tapioca.ymlconfig key: An opt-in flag to enable this behaviour without breaking existing setups:
dsl:
packaged_output: true # route stubs into <pack_root>/sorbet/rbi/dsl/ when a __package.rb is present
Workaround
Globally suppress error 5084 (--suppress-error-code=5084), which defeats the purpose of packages mode enforcement, or manually move generated stubs into the relevant pack directory after each tapioca dsl run.
Environment
tapiocaversion: 0.17.10sorbet/sorbet-runtimeversion: 0.6.13055
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the tapioca dsl command's output routing and the described __package.rb hierarchy; compare the global sorbet/rbi/dsl/ path with the expected per-pack path. Done means an opt-in configuration can place stubs for constants owned by an enrolled pack inside that pack, while preserving existing output behavior and avoiding Sorbet error 5084.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- ruby
- Domain
- cli, tooling
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100