diff --git a/.gitattributes b/.gitattributes index a243b74346b0..1fd2a3a8a59e 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2,6 +2,8 @@ /CHANGELOG.md merge=union +/spec/truffleruby.next-specs merge=union + # Rules for GitHub's Linguist language-classification system. We're abusing the # 'vendored' attribute to exclude files as a lot of this isn't really vendored, # and a whole lot of actually vendored code isn't listed! What we want to do is diff --git a/CHANGELOG.md b/CHANGELOG.md index 385d0452783f..5055ef85d40e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ Compatibility: * Add optional `timeout` argument to `Thread::Queue#pop` (#3039, @itarato). * Add optional `timeout` argument to `Thread::SizedsQueue#pop` (#3039, @itarato). * Handle `long long` and aliases in `Fiddle` (#3128, @eregon). +* Add `Module#refinements` (#3039, @itarato). Performance: diff --git a/spec/tags/truffle/methods_tags.txt b/spec/tags/truffle/methods_tags.txt index 533595a0a69d..dac19aba2b88 100644 --- a/spec/tags/truffle/methods_tags.txt +++ b/spec/tags/truffle/methods_tags.txt @@ -114,3 +114,4 @@ fails:Public methods on UnboundMethod should include private? fails:Public methods on UnboundMethod should include protected? fails:Public methods on UnboundMethod should include public? fails:Public methods on String should not include bytesplice +fails:Public methods on Module should not include refinements diff --git a/spec/truffleruby.next-specs b/spec/truffleruby.next-specs index 2b7ef4fbe7a3..de60b64e2670 100644 --- a/spec/truffleruby.next-specs +++ b/spec/truffleruby.next-specs @@ -29,3 +29,5 @@ spec/ruby/core/queue/shift_spec.rb spec/ruby/core/sizedqueue/deq_spec.rb spec/ruby/core/sizedqueue/pop_spec.rb spec/ruby/core/sizedqueue/shift_spec.rb + +spec/ruby/core/module/refinements_spec.rb diff --git a/src/main/java/org/truffleruby/core/module/ModuleNodes.java b/src/main/java/org/truffleruby/core/module/ModuleNodes.java index ccad0292813b..a05b0b676a1f 100644 --- a/src/main/java/org/truffleruby/core/module/ModuleNodes.java +++ b/src/main/java/org/truffleruby/core/module/ModuleNodes.java @@ -10,6 +10,7 @@ package org.truffleruby.core.module; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashSet; @@ -37,7 +38,6 @@ import org.truffleruby.builtins.CoreMethodArrayArgumentsNode; import org.truffleruby.builtins.CoreMethodNode; import org.truffleruby.annotations.CoreModule; -import org.truffleruby.builtins.NonStandard; import org.truffleruby.annotations.Primitive; import org.truffleruby.builtins.PrimitiveArrayArgumentsNode; import org.truffleruby.builtins.PrimitiveNode; @@ -2324,7 +2324,6 @@ protected RubyArray usedModules() { } - @NonStandard @CoreMethod(names = "used_refinements", onSingleton = true) public abstract static class UsedRefinementsNode extends CoreMethodArrayArgumentsNode { @@ -2335,15 +2334,24 @@ protected RubyArray usedRefinements() { final DeclarationContext declarationContext = RubyArguments.getDeclarationContext(frame); final Set refinements = new HashSet<>(); for (RubyModule[] refinementModules : declarationContext.getRefinements().values()) { - for (RubyModule refinementModule : refinementModules) { - refinements.add(refinementModule); - } + Collections.addAll(refinements, refinementModules); } return createArray(refinements.toArray()); } } + @CoreMethod(names = "refinements") + public abstract static class RefinementsNode extends CoreMethodArrayArgumentsNode { + + @TruffleBoundary + @Specialization + protected RubyArray refinements(RubyModule self) { + return createArray(self.fields.getRefinements().values().toArray()); + } + + } + @GenerateUncached @ImportStatic(ArrayGuards.class) public abstract static class SetMethodVisibilityNode extends RubyBaseNode { diff --git a/test/mri/excludes/TestRefinement.rb b/test/mri/excludes/TestRefinement.rb index e3ab5bb756e4..3d9fa3731d4a 100644 --- a/test/mri/excludes/TestRefinement.rb +++ b/test/mri/excludes/TestRefinement.rb @@ -10,3 +10,4 @@ exclude :test_unbound_refine_method, "needs investigation" exclude :test_ancestors, "[ruby-core:86949] [Bug #14744]." exclude :test_import_methods, "NoMethodError: undefined method `bar' for #" +exclude :test_refinements, "TruffleRuby does not guarantee refinement list ordering" diff --git a/test/mri/tests/ruby/test_refinement.rb b/test/mri/tests/ruby/test_refinement.rb index 9a153a0c25b4..a5cc872a459e 100644 --- a/test/mri/tests/ruby/test_refinement.rb +++ b/test/mri/tests/ruby/test_refinement.rb @@ -1835,6 +1835,21 @@ def test_used_modules assert_equal [ref::RefB, ref::RefA], ref::Combined::USED_MODS end + def test_refinements + int_refinement = nil + str_refinement = nil + m = Module.new { + refine Integer do + int_refinement = self + end + + refine String do + str_refinement = self + end + } + assert_equal([int_refinement, str_refinement], m.refinements) + end + def test_warn_setconst_in_refinmenet bug10103 = '[ruby-core:64143] [Bug #10103]' warnings = [