3
3
4
4
ruby_version_is "2.7" do
5
5
describe "Module#ruby2_keywords" do
6
- it "marks the final hash argument as keyword hash" do
7
- obj = Object . new
8
-
9
- obj . singleton_class . class_exec do
10
- def foo ( *a ) a . last end
11
- ruby2_keywords :foo
6
+ class << self
7
+ ruby2_keywords def mark ( *args )
8
+ args
12
9
end
10
+ end
13
11
14
- last = obj . foo ( 1 , 2 , a : "a" )
12
+ it "marks the final hash argument as keyword hash" do
13
+ last = mark ( 1 , 2 , a : "a" ) . last
15
14
Hash . ruby2_keywords_hash? ( last ) . should == true
16
15
end
17
16
@@ -21,74 +20,121 @@ def foo(*a) a.last end
21
20
def regular ( *args )
22
21
args . last
23
22
end
24
-
25
- ruby2_keywords def foo ( *args )
26
- args . last
27
- end
28
23
end
29
24
30
25
h = { a : 1 }
31
26
ruby_version_is "3.0" do
32
27
obj . regular ( **h ) . should . equal? ( h )
33
28
end
34
29
35
- last = obj . foo ( **h )
30
+ last = mark ( **h ) . last
36
31
Hash . ruby2_keywords_hash? ( last ) . should == true
37
32
Hash . ruby2_keywords_hash? ( h ) . should == false
38
33
39
- last2 = obj . foo ( **last ) # last is already marked
34
+ last2 = mark ( **last ) . last # last is already marked
40
35
Hash . ruby2_keywords_hash? ( last2 ) . should == true
41
36
Hash . ruby2_keywords_hash? ( last ) . should == true
42
37
last2 . should_not . equal? ( last )
43
38
Hash . ruby2_keywords_hash? ( h ) . should == false
44
39
end
45
40
46
- it "makes a copy and unmark at the call site when calling with marked *args " do
41
+ it "makes a copy and unmark the Hash when calling a method taking (arg) " do
47
42
obj = Object . new
48
43
obj . singleton_class . class_exec do
49
- ruby2_keywords def foo ( *args )
50
- args
51
- end
52
-
53
44
def single ( arg )
54
45
arg
55
46
end
47
+ end
56
48
57
- def splat ( *args )
58
- args . last
59
- end
49
+ h = { a : 1 }
50
+ args = mark ( **h )
51
+ marked = args . last
52
+ Hash . ruby2_keywords_hash? ( marked ) . should == true
53
+
54
+ after_usage = obj . single ( *args )
55
+ after_usage . should == h
56
+ after_usage . should_not . equal? ( h )
57
+ after_usage . should_not . equal? ( marked )
58
+ Hash . ruby2_keywords_hash? ( after_usage ) . should == false
59
+ Hash . ruby2_keywords_hash? ( marked ) . should == true
60
+ end
60
61
62
+ it "makes a copy and unmark the Hash when calling a method taking (**kw)" do
63
+ obj = Object . new
64
+ obj . singleton_class . class_exec do
61
65
def kwargs ( **kw )
62
66
kw
63
67
end
64
68
end
65
69
66
70
h = { a : 1 }
67
- args = obj . foo ( **h )
71
+ args = mark ( **h )
68
72
marked = args . last
69
73
Hash . ruby2_keywords_hash? ( marked ) . should == true
70
74
71
- after_usage = obj . single ( *args )
75
+ after_usage = obj . kwargs ( *args )
72
76
after_usage . should == h
73
77
after_usage . should_not . equal? ( h )
74
78
after_usage . should_not . equal? ( marked )
75
79
Hash . ruby2_keywords_hash? ( after_usage ) . should == false
76
80
Hash . ruby2_keywords_hash? ( marked ) . should == true
81
+ end
82
+
83
+ # https://bugs.ruby-lang.org/issues/18625
84
+ it "does NOT copy the Hash when calling a method taking (*args)" do
85
+ obj = Object . new
86
+ obj . singleton_class . class_exec do
87
+ def splat ( *args )
88
+ args . last
89
+ end
90
+
91
+ def splat1 ( arg , *args )
92
+ args . last
93
+ end
94
+
95
+ def proc_call ( *args )
96
+ -> *args { args . last } . call ( *args )
97
+ end
98
+ end
99
+
100
+ h = { a : 1 }
101
+ args = mark ( **h )
102
+ marked = args . last
103
+ Hash . ruby2_keywords_hash? ( marked ) . should == true
77
104
78
105
after_usage = obj . splat ( *args )
79
106
after_usage . should == h
80
107
after_usage . should_not . equal? ( h )
81
- after_usage . should_not . equal? ( marked )
82
- ruby_bug "#18625" , "" ..."3.3" do # might be fixed in 3.2
83
- Hash . ruby2_keywords_hash? ( after_usage ) . should == false
84
- end
108
+ after_usage . should . equal? ( marked ) # https://bugs.ruby-lang.org/issues/18625
109
+ Hash . ruby2_keywords_hash? ( after_usage ) . should == true # https://bugs.ruby-lang.org/issues/18625
85
110
Hash . ruby2_keywords_hash? ( marked ) . should == true
86
111
87
- after_usage = obj . kwargs ( *args )
112
+ args = mark ( 1 , **h )
113
+ marked = args . last
114
+ after_usage = obj . splat1 ( *args )
88
115
after_usage . should == h
89
116
after_usage . should_not . equal? ( h )
90
- after_usage . should_not . equal? ( marked )
91
- Hash . ruby2_keywords_hash? ( after_usage ) . should == false
117
+ after_usage . should . equal? ( marked ) # https://bugs.ruby-lang.org/issues/18625
118
+ Hash . ruby2_keywords_hash? ( after_usage ) . should == true # https://bugs.ruby-lang.org/issues/18625
119
+ Hash . ruby2_keywords_hash? ( marked ) . should == true
120
+
121
+ args = mark ( **h )
122
+ marked = args . last
123
+ after_usage = obj . proc_call ( *args )
124
+ after_usage . should == h
125
+ after_usage . should_not . equal? ( h )
126
+ after_usage . should . equal? ( marked ) # https://bugs.ruby-lang.org/issues/18625
127
+ Hash . ruby2_keywords_hash? ( after_usage ) . should == true # https://bugs.ruby-lang.org/issues/18625
128
+ Hash . ruby2_keywords_hash? ( marked ) . should == true
129
+
130
+ args = mark ( **h )
131
+ marked = args . last
132
+ after_usage = obj . send ( :splat , *args )
133
+ after_usage . should == h
134
+ after_usage . should_not . equal? ( h )
135
+ send_copies = RUBY_ENGINE == "ruby" # inconsistent with Proc#call above for CRuby
136
+ after_usage . equal? ( marked ) . should == !send_copies
137
+ Hash . ruby2_keywords_hash? ( after_usage ) . should == !send_copies
92
138
Hash . ruby2_keywords_hash? ( marked ) . should == true
93
139
end
94
140
0 commit comments