[ruby/psych] Refine Ruby 3.5 Set support.
authorJean Boussier <[email protected]>
Sat, 3 May 2025 10:57:39 +0000 (3 12:57 +0200)
committerHiroshi SHIBATA <[email protected]>
Thu, 8 May 2025 09:03:04 +0000 (8 18:03 +0900)
Use feature testing to detect native Set,
and don't rely on `Set#to_h` which wasn't intended
as a public method.

https://github.com/ruby/psych/commit/d58cff11af

ext/psych/lib/psych.rb
ext/psych/lib/psych/core_ext.rb

index a95393c..d7567d8 100644 (file)
@@ -23,7 +23,6 @@ require_relative 'psych/parser'
 require_relative 'psych/omap'
 require_relative 'psych/set'
 require_relative 'psych/coder'
-require_relative 'psych/core_ext'
 require_relative 'psych/stream'
 require_relative 'psych/json/tree_builder'
 require_relative 'psych/json/stream'
@@ -761,3 +760,5 @@ module Psych
   self.domain_types = {}
   # :startdoc:
 end
+
+require_relative 'psych/core_ext'
index 950b20f..fc259fd 100644 (file)
@@ -18,12 +18,19 @@ if defined?(::IRB)
   require_relative 'y'
 end
 
-
-# TODO: how best to check for builtin Set?
-if defined?(::Set) && Object.const_source_location(:Set) == ["ruby", 0]
+# Up to Ruby 3.4, Set was a regular object and was dumped as such
+# by Pysch.
+# Starting from Ruby 3.5 it's a core class written in C, so we have to implement
+# #encode_with / #init_with to preserve backward compatibility.
+if defined?(::Set) && Set.new.instance_variables.empty?
   class Set
     def encode_with(coder)
-      coder["hash"] = to_h
+      hash = {}
+      each do |m|
+        hash[m] = true
+      end
+      coder["hash"] = hash
+      coder
     end
 
     def init_with(coder)