From f4e2c637d8816f938a4e7d78023272939ad99396 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Fri, 11 Sep 2026 14:48:35 -0400 Subject: [PATCH] Bind ActiveSupport::Concern block DSLs to T.untyped MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `included`, `prepended`, and `class_methods` class_eval their block on the including class (or the generated ClassMethods module), so `self` inside the block is never the concern module itself. Without a binding Sorbet types `self` as `T.class_of(TheConcern)` and reports 7003 for every DSL call in an `included do … end` body. `T.untyped` is the honest binding — a concern cannot know its includer — and matches the existing `Testing::Declarative#test` and `SetupAndTeardown#setup`/`#teardown` annotations in this file. --- rbi/annotations/activesupport.rbi | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/rbi/annotations/activesupport.rbi b/rbi/annotations/activesupport.rbi index 0043b104..1ea55f33 100644 --- a/rbi/annotations/activesupport.rbi +++ b/rbi/annotations/activesupport.rbi @@ -5,6 +5,19 @@ module ActiveSupport::Testing::Declarative def test(name, &block); end end +module ActiveSupport::Concern + sig { params(base: T.untyped, block: T.nilable(T.proc.bind(T.untyped).void)).void } + def included(base = nil, &block); end + + # @version >= 6.1.0 + sig { params(base: T.untyped, block: T.nilable(T.proc.bind(T.untyped).void)).void } + def prepended(base = nil, &block); end + + # @version >= 4.2.0 + sig { params(class_methods_module_definition: T.nilable(T.proc.bind(T.untyped).void)).void } + def class_methods(&class_methods_module_definition); end +end + class ActiveSupport::EnvironmentInquirer sig { returns(T::Boolean) } def development?; end