diff --git a/Library/Homebrew/PATH.rb b/Library/Homebrew/PATH.rb
index a69709e9c97055831eba8341dd7ba847ce0f5d18..6e48ef8553ea94b2d3b7504f2700f5946ef80cda 100644
--- a/Library/Homebrew/PATH.rb
+++ b/Library/Homebrew/PATH.rb
@@ -10,7 +10,7 @@ class PATH
   include Enumerable
   extend Forwardable
 
-  def_delegator :@paths, :each
+  delegate each: :@paths
 
   # FIXME: Enable cop again when https://github.com/sorbet/sorbet/issues/3532 is fixed.
   # rubocop:disable Style/MutableConstant
diff --git a/Library/Homebrew/formula.rb b/Library/Homebrew/formula.rb
index b7db3129475c368ce8f261c873c55ba1029c2a7a..62c72ec1e423f57394e33fe8f4f1af27301ff567 100644
--- a/Library/Homebrew/formula.rb
+++ b/Library/Homebrew/formula.rb
@@ -1,4 +1,4 @@
-# typed: false
+# typed: true
 # frozen_string_literal: true
 
 require "cache_store"
@@ -124,6 +124,7 @@ class Formula
 
   # The currently active {SoftwareSpec}.
   # @see #determine_active_spec
+  sig { returns(SoftwareSpec) }
   attr_reader :active_spec
 
   protected :active_spec
@@ -939,6 +940,7 @@ class Formula
   end
 
   # The generated launchd {.plist} file path.
+  sig { returns(Pathname) }
   def plist_path
     prefix/"#{plist_name}.plist"
   end
@@ -961,38 +963,47 @@ class Formula
     HOMEBREW_PREFIX/"opt"/name
   end
 
+  sig { returns(Pathname) }
   def opt_bin
     opt_prefix/"bin"
   end
 
+  sig { returns(Pathname) }
   def opt_include
     opt_prefix/"include"
   end
 
+  sig { returns(Pathname) }
   def opt_lib
     opt_prefix/"lib"
   end
 
+  sig { returns(Pathname) }
   def opt_libexec
     opt_prefix/"libexec"
   end
 
+  sig { returns(Pathname) }
   def opt_sbin
     opt_prefix/"sbin"
   end
 
+  sig { returns(Pathname) }
   def opt_share
     opt_prefix/"share"
   end
 
+  sig { returns(Pathname) }
   def opt_pkgshare
     opt_prefix/"share"/name
   end
 
+  sig { returns(Pathname) }
   def opt_elisp
     opt_prefix/"share/emacs/site-lisp"/name
   end
 
+  sig { returns(Pathname) }
   def opt_frameworks
     opt_prefix/"Frameworks"
   end
@@ -1012,40 +1023,45 @@ class Formula
   delegate pour_bottle_check_unsatisfied_reason: :"self.class"
 
   # Can be overridden to run commands on both source and bottle installation.
+  sig { overridable.void }
   def post_install; end
 
   # @private
+  sig { void }
   def run_post_install
     @prefix_returns_versioned_prefix = true
     build = self.build
-    self.build = Tab.for_formula(self)
 
-    new_env = {
-      TMPDIR:        HOMEBREW_TEMP,
-      TEMP:          HOMEBREW_TEMP,
-      TMP:           HOMEBREW_TEMP,
-      _JAVA_OPTIONS: "-Djava.io.tmpdir=#{HOMEBREW_TEMP}",
-      HOMEBREW_PATH: nil,
-      PATH:          ENV["HOMEBREW_PATH"],
-    }
+    begin
+      self.build = Tab.for_formula(self)
 
-    with_env(new_env) do
-      ENV.clear_sensitive_environment!
+      new_env = {
+        TMPDIR:        HOMEBREW_TEMP,
+        TEMP:          HOMEBREW_TEMP,
+        TMP:           HOMEBREW_TEMP,
+        _JAVA_OPTIONS: "-Djava.io.tmpdir=#{HOMEBREW_TEMP}",
+        HOMEBREW_PATH: nil,
+        PATH:          ENV["HOMEBREW_PATH"],
+      }
 
-      etc_var_dirs = [bottle_prefix/"etc", bottle_prefix/"var"]
-      Find.find(*etc_var_dirs.select(&:directory?)) do |path|
-        path = Pathname.new(path)
-        path.extend(InstallRenamed)
-        path.cp_path_sub(bottle_prefix, HOMEBREW_PREFIX)
-      end
+      with_env(new_env) do
+        ENV.clear_sensitive_environment!
 
-      with_logging("post_install") do
-        post_install
+        etc_var_dirs = [bottle_prefix/"etc", bottle_prefix/"var"]
+        T.unsafe(Find).find(*etc_var_dirs.select(&:directory?)) do |path|
+          path = Pathname.new(path)
+          path.extend(InstallRenamed)
+          path.cp_path_sub(bottle_prefix, HOMEBREW_PREFIX)
+        end
+
+        with_logging("post_install") do
+          post_install
+        end
       end
+    ensure
+      self.build = build
+      @prefix_returns_versioned_prefix = false
     end
-  ensure
-    self.build = build
-    @prefix_returns_versioned_prefix = false
   end
 
   # Warn the user about any Homebrew-specific issues or quirks for this package.
@@ -1067,6 +1083,7 @@ class Formula
   #   s += "Some issue only on older systems" if MacOS.version < :el_capitan
   #   s
   # end</pre>
+  sig { overridable.returns(T.nilable(String)) }
   def caveats
     nil
   end
@@ -1089,6 +1106,8 @@ class Formula
   # keep .la files with:
   #   skip_clean :la
   # @private
+  sig { params(path: Pathname).returns(T::Boolean) }
+
   def skip_clean?(path)
     return true if path.extname == ".la" && self.class.skip_clean_paths.include?(:la)
 
@@ -1241,7 +1260,7 @@ class Formula
     Formula.cache[:outdated_kegs] ||= {}
     Formula.cache[:outdated_kegs][cache_key] ||= begin
       all_kegs = []
-      current_version = false
+      current_version = T.let(false, T::Boolean)
 
       installed_kegs.each do |keg|
         all_kegs << keg
@@ -1427,13 +1446,15 @@ class Formula
   # Standard parameters for cabal-v2 builds.
   sig { returns(T::Array[String]) }
   def std_cabal_v2_args
+    env = T.cast(ENV, T.any(Stdenv, Superenv))
+
     # cabal-install's dependency-resolution backtracking strategy can
     # easily need more than the default 2,000 maximum number of
     # "backjumps," since Hackage is a fast-moving, rolling-release
     # target. The highest known needed value by a formula was 43,478
     # for git-annex, so 100,000 should be enough to avoid most
     # gratuitous backjumps build failures.
-    ["--jobs=#{ENV.make_jobs}", "--max-backjumps=100000", "--install-method=copy", "--installdir=#{bin}"]
+    ["--jobs=#{env.make_jobs}", "--max-backjumps=100000", "--install-method=copy", "--installdir=#{bin}"]
   end
 
   # Standard parameters for meson builds.
@@ -1960,6 +1981,7 @@ class Formula
   #
   # # If there is a "make install" available, please use it!
   # system "make", "install"</pre>
+  sig { params(cmd: T.any(String, Pathname), args: T.any(String, Pathname)).void }
   def system(cmd, *args)
     verbose_using_dots = Homebrew::EnvConfig.verbose_using_dots?
 
@@ -2026,10 +2048,12 @@ class Formula
           rd.close
         end
       else
-        pid = fork { exec_cmd(cmd, args, log, logfn) }
+        pid = fork do
+          exec_cmd(cmd, args, log, logfn)
+        end
       end
 
-      Process.wait(pid)
+      Process.wait(T.must(pid))
 
       $stdout.flush
 
@@ -2114,11 +2138,15 @@ class Formula
   end
 
   # Runs `xcodebuild` without Homebrew's compiler environment variables set.
+  sig { params(args: T.any(String, Pathname)).void }
   def xcodebuild(*args)
     removed = ENV.remove_cc_etc
-    system "xcodebuild", *args
-  ensure
-    ENV.update(removed)
+
+    begin
+      T.unsafe(self).system("xcodebuild", *args)
+    ensure
+      ENV.update(removed)
+    end
   end
 
   def fetch_patches
@@ -2148,7 +2176,8 @@ class Formula
     if cmd == "python"
       setup_py_in_args = %w[setup.py build.py].include?(args.first)
       setuptools_shim_in_args = args.any? { |a| a.to_s.start_with? "import setuptools" }
-      ENV.refurbish_args if setup_py_in_args || setuptools_shim_in_args
+      env = T.cast(ENV, T.any(Stdenv, Superenv))
+      env.refurbish_args if setup_py_in_args || setuptools_shim_in_args
     end
 
     $stdout.reopen(out)
@@ -2156,7 +2185,7 @@ class Formula
     out.close
     args.map!(&:to_s)
     begin
-      exec(cmd, *args)
+      T.unsafe(Kernel).exec(cmd, *args)
     rescue
       nil
     end
@@ -2420,7 +2449,7 @@ class Formula
     # Get the `BUILD_FLAGS` from the formula's namespace set in `Formulary::load_formula`.
     # @private
     def build_flags
-      namespace = to_s.split("::")[0..-2].join("::")
+      namespace = T.must(to_s.split("::")[0..-2]).join("::")
       return [] if namespace.empty?
 
       mod = const_get(namespace)
diff --git a/Library/Homebrew/resource.rb b/Library/Homebrew/resource.rb
index c2a2b749a851690f5e9e0ec0f5ac77886af13b6f..d17bc7be56362bcc7ad8372c9e569b9fbfe07cdb 100644
--- a/Library/Homebrew/resource.rb
+++ b/Library/Homebrew/resource.rb
@@ -12,6 +12,8 @@ require "mktemp"
 #
 # @api private
 class Resource
+  extend T::Sig
+
   include Context
   include FileUtils
 
@@ -221,8 +223,8 @@ class Resource
 
   # A resource containing a Go package.
   class Go < Resource
-    def stage(target)
-      super(target/name)
+    def stage(target, &block)
+      super(target/name, &block)
     end
   end
 
diff --git a/Library/Homebrew/software_spec.rb b/Library/Homebrew/software_spec.rb
index f5f817ba05c8ddb9734f4fa9b10534c84cafa5fe..513efdbafe12a3e8d5bc7de82a9b7699bcb9821f 100644
--- a/Library/Homebrew/software_spec.rb
+++ b/Library/Homebrew/software_spec.rb
@@ -29,7 +29,9 @@ class SoftwareSpec
 
   def_delegators :@resource, :stage, :fetch, :verify_download_integrity, :source_modified_time, :download_name,
                  :cached_download, :clear_cache, :checksum, :mirrors, :specs, :using, :version, :mirror,
-                 :downloader, *Checksum::TYPES
+                 :downloader
+
+  def_delegators :@resource, *Checksum::TYPES
 
   def initialize(flags: [])
     @resource = Resource.new
diff --git a/Library/Homebrew/sorbet/plugins/attr_rw.rb b/Library/Homebrew/sorbet/plugins/attr_rw.rb
new file mode 100644
index 0000000000000000000000000000000000000000..2363d3bffae4af277aa159576df64adfaf2ca177
--- /dev/null
+++ b/Library/Homebrew/sorbet/plugins/attr_rw.rb
@@ -0,0 +1,13 @@
+# typed: strict
+# frozen_string_literal: true
+
+source = ARGV[5]
+
+source.scan(/:([^\s,]+)/).flatten.each do |method|
+  puts <<~RUBY
+    # typed: strict
+
+    sig { params(arg: T.untyped).returns(T.untyped) }
+    def #{method}(arg = T.unsafe(nil)); end
+  RUBY
+end
diff --git a/Library/Homebrew/sorbet/plugins/def_delegator.rb b/Library/Homebrew/sorbet/plugins/def_delegator.rb
new file mode 100644
index 0000000000000000000000000000000000000000..7eea2d6bd00618929a5c7038a599ed71591961ea
--- /dev/null
+++ b/Library/Homebrew/sorbet/plugins/def_delegator.rb
@@ -0,0 +1,17 @@
+# typed: strict
+# frozen_string_literal: true
+
+source = ARGV[5]
+
+match = source.match(/\s*def_delegator\s+.*:(?<method>[^:]+)\s*\Z/m)
+
+raise if match.nil?
+
+method = match[:method]
+
+puts <<~RUBY
+  # typed: strict
+
+  sig {params(arg0: T.untyped, blk: T.untyped).returns(T.untyped)}
+  def #{method}(*arg0, &blk); end
+RUBY
diff --git a/Library/Homebrew/sorbet/plugins/def_delegators.rb b/Library/Homebrew/sorbet/plugins/def_delegators.rb
new file mode 100644
index 0000000000000000000000000000000000000000..ac09880d3c7350f6cb4239692ab7351910a71954
--- /dev/null
+++ b/Library/Homebrew/sorbet/plugins/def_delegators.rb
@@ -0,0 +1,17 @@
+# typed: strict
+# frozen_string_literal: true
+
+source = ARGV[5]
+
+symbols = source.scan(/:[^\s,]+/)
+
+_, *methods = symbols.map { |s| s.delete_prefix(":") }
+
+methods.each do |method|
+  puts <<~RUBY
+    # typed: strict
+
+    sig {params(arg0: T.untyped, blk: T.untyped).returns(T.untyped)}
+    def #{method}(*arg0, &blk); end
+  RUBY
+end
diff --git a/Library/Homebrew/sorbet/plugins/delegate.rb b/Library/Homebrew/sorbet/plugins/delegate.rb
index 2f308cc45d8128ad3f3eb347370e2020f4e9ac9d..8a249d188c3c5a0e6ad57baaf67bcf1a91d81ffb 100644
--- a/Library/Homebrew/sorbet/plugins/delegate.rb
+++ b/Library/Homebrew/sorbet/plugins/delegate.rb
@@ -15,7 +15,7 @@ methods.each do |method|
   puts <<~RUBY
     # typed: strict
 
-    sig {params(arg0: T.untyped).returns(T.untyped)}
-    def #{method}(*arg0); end
+    sig {params(arg0: T.untyped, blk: T.untyped).returns(T.untyped)}
+    def #{method}(*arg0, &blk); end
   RUBY
 end
diff --git a/Library/Homebrew/sorbet/rbi/upstream.rbi b/Library/Homebrew/sorbet/rbi/upstream.rbi
index d3295ae20c7eefa6c141d9ec52c16dd9ac3b1d0f..4a77637e5af87806d24391028fd2c126b55bf02e 100644
--- a/Library/Homebrew/sorbet/rbi/upstream.rbi
+++ b/Library/Homebrew/sorbet/rbi/upstream.rbi
@@ -9,3 +9,48 @@ class Pathname
   sig { params(with_directory: T::Boolean).returns(T::Array[Pathname]) }
   def children(with_directory = true); end
 end
+
+module FileUtils
+  # https://github.com/sorbet/sorbet/pull/3730
+  module_function
+
+  sig do
+    params(
+      src: T.untyped,
+      dest: T.untyped,
+      preserve: T.nilable(T::Boolean),
+      noop: T.nilable(T::Boolean),
+      verbose: T.nilable(T::Boolean)
+    ).returns(T.untyped)
+  end
+  def cp(src, dest, preserve: nil, noop: nil, verbose: nil); end
+
+  sig do
+    params(
+      list: T.any(String, Pathname),
+      mode: T.nilable(Integer),
+      noop: T.nilable(T::Boolean),
+      verbose: T.nilable(T::Boolean)
+    ).returns(T::Array[String])
+  end
+  def mkdir_p(list, mode: nil, noop: nil, verbose: nil); end
+end
+
+class Module
+  # https://github.com/sorbet/sorbet/pull/3732
+  sig do
+    params(
+        arg0: T.any(Symbol, String),
+        arg1: T.any(Proc, Method, UnboundMethod)
+    )
+    .returns(Symbol)
+  end
+  sig do
+    params(
+        arg0: T.any(Symbol, String),
+        blk: T.proc.bind(T.untyped).returns(T.untyped),
+    )
+    .returns(Symbol)
+  end
+  def define_method(arg0, arg1=T.unsafe(nil), &blk); end
+end
diff --git a/Library/Homebrew/sorbet/triggers.yml b/Library/Homebrew/sorbet/triggers.yml
index 747e297c2ef4c0ed11ec58ae6e153124c7bf8150..ccf1647ba40e9b85b6170a502d12ad742c3075ba 100644
--- a/Library/Homebrew/sorbet/triggers.yml
+++ b/Library/Homebrew/sorbet/triggers.yml
@@ -4,4 +4,7 @@ ruby_extra_args:
 triggers:
   using: sorbet/plugins/using.rb
   attr_predicate: sorbet/plugins/attr_predicate.rb
+  attr_rw: sorbet/plugins/attr_rw.rb
+  def_delegator: sorbet/plugins/def_delegator.rb
+  def_delegators: sorbet/plugins/def_delegators.rb
   delegate: sorbet/plugins/delegate.rb