Skip to content

Commit

Permalink
Add Object#deep_dup to extend/
Browse files Browse the repository at this point in the history
  • Loading branch information
dduugg committed Jan 12, 2024
1 parent 1b84407 commit 6fdba65
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 24 deletions.
11 changes: 2 additions & 9 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,7 @@
!**/vendor/bundle/ruby/*/gems/rubocop-rails-*/config
!**/vendor/bundle/ruby/*/gems/rubocop-rspec-*/config
!**/vendor/bundle/ruby/*/gems/rubocop-sorbet-*/config

# Ignore activesupport, except the ones we need.
**/vendor/bundle/ruby/*/gems/activesupport-*/lib/**/*
!**/vendor/bundle/ruby/*/gems/activesupport-*/lib/active_support/
!**/vendor/bundle/ruby/*/gems/activesupport-*/lib/active_support/core_ext/
!**/vendor/bundle/ruby/*/gems/activesupport-*/lib/active_support/core_ext/*/
!**/vendor/bundle/ruby/*/gems/activesupport-*/lib/active_support/core_ext/object/deep_dup.rb
!**/vendor/bundle/ruby/*/gems/activesupport-*/lib/active_support/core_ext/object/duplicable.rb
!**/vendor/bundle/ruby/*/gems/sorbet-runtime-*/

# Ignore partially included gems where we don't need all files
**/vendor/gems/mechanize-*/.*
Expand All @@ -82,6 +75,7 @@
**/vendor/gems/mechanize-*/test/

# Ignore dependencies we don't wish to vendor
**/vendor/bundle/ruby/*/gems/activesupport-*/
**/vendor/bundle/ruby/*/gems/ast-*/
**/vendor/bundle/ruby/*/gems/bootsnap-*/
**/vendor/bundle/ruby/*/gems/bundler-*/
Expand Down Expand Up @@ -144,7 +138,6 @@
**/vendor/bundle/ruby/*/gems/simplecov_json_formatter-*/
**/vendor/bundle/ruby/*/gems/simpleidn-*/
**/vendor/bundle/ruby/*/gems/sorbet-*/
!**/vendor/bundle/ruby/*/gems/sorbet-runtime-*/
**/vendor/bundle/ruby/*/gems/spoom-*/
**/vendor/bundle/ruby/*/gems/stackprof-*/
**/vendor/bundle/ruby/*/gems/strscan-*/
Expand Down
2 changes: 1 addition & 1 deletion Library/Homebrew/cask/artifact/abstract_artifact.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# frozen_string_literal: true

require "attrable"
require "active_support/core_ext/object/deep_dup"
require "extend/object/deep_dup"

module Cask
module Artifact
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# typed: strict
# frozen_string_literal: true

require "active_support/core_ext/object/duplicable"
require "extend/object/duplicable"

class Object
# Returns a deep copy of object if it's duplicable. If it's
Expand All @@ -12,9 +13,8 @@ class Object
#
# object.instance_variable_defined?(:@a) # => false
# dup.instance_variable_defined?(:@a) # => true
def deep_dup
duplicable? ? dup : self
end
sig { returns(T.self_type) }
def deep_dup = duplicable? ? dup : self
end

class Array
Expand All @@ -26,9 +26,8 @@ class Array
#
# array[1][2] # => nil
# dup[1][2] # => 4
def deep_dup
map(&:deep_dup)
end
sig { returns(T.self_type) }
def deep_dup = T.unsafe(self).map(&:deep_dup)
end

class Hash
Expand All @@ -40,16 +39,35 @@ class Hash
#
# hash[:a][:c] # => nil
# dup[:a][:c] # => "c"
sig { returns(T.self_type) }
def deep_dup
hash = dup
each_pair do |key, value|
if (::String === key && key.frozen?) || ::Symbol === key
hash[key] = value.deep_dup
case key
when ::String, ::Symbol
hash[key] = T.unsafe(value).deep_dup
else
hash.delete(key)
hash[key.deep_dup] = value.deep_dup
hash[T.unsafe(key).deep_dup] = T.unsafe(value).deep_dup
end
end
hash
end
end

class Module
# Returns a copy of module or class if it's anonymous. If it's
# named, returns +self+.
#
# Object.deep_dup == Object # => true
# klass = Class.new
# klass.deep_dup == klass # => false
sig { returns(T.self_type) }
def deep_dup
if name.nil?
super
else
self
end
end
end
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# typed: strict
# frozen_string_literal: true

#--
Expand All @@ -23,6 +24,7 @@ class Object
#
# False for method objects;
# true otherwise.
sig { returns(T::Boolean) }
def duplicable?
true
end
Expand All @@ -31,8 +33,9 @@ def duplicable?
class Method
# Methods are not duplicable:
#
# method(:puts).duplicable? # => false
# method(:puts).dup # => TypeError: allocator undefined for Method
# method(:puts).duplicable? # => false
# method(:puts).dup # => TypeError: allocator undefined for Method
sig { returns(FalseClass) }
def duplicable?
false
end
Expand All @@ -41,8 +44,21 @@ def duplicable?
class UnboundMethod
# Unbound methods are not duplicable:
#
# method(:puts).unbind.duplicable? # => false
# method(:puts).unbind.dup # => TypeError: allocator undefined for UnboundMethod
# method(:puts).unbind.duplicable? # => false
# method(:puts).unbind.dup # => TypeError: allocator undefined for UnboundMethod
sig { returns(FalseClass) }
def duplicable?
false
end
end

require "singleton"

module Singleton
# Singleton instances are not duplicable:
#
# Class.new.include(Singleton).instance.dup # TypeError (can't dup instance of singleton
sig { returns(FalseClass) }
def duplicable?
false
end
Expand Down

0 comments on commit 6fdba65

Please sign in to comment.