From 67c3c5a4b2a0344157f717fdf0c7660bc5fa1428 Mon Sep 17 00:00:00 2001 From: Ramsay Stirling II Date: Sat, 7 Jul 2018 01:14:34 +0100 Subject: [PATCH] Ensure keyword arguments for Concurrent::*Struct behave similarly to Std-lib Struct --- lib/concurrent/synchronization/abstract_struct.rb | 10 ++++++++-- spec/concurrent/struct_shared.rb | 9 +++++++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/lib/concurrent/synchronization/abstract_struct.rb b/lib/concurrent/synchronization/abstract_struct.rb index 74164aa77..b54abe11d 100644 --- a/lib/concurrent/synchronization/abstract_struct.rb +++ b/lib/concurrent/synchronization/abstract_struct.rb @@ -142,8 +142,14 @@ def self.define_struct_class(parent, base, name, members, kw_args, &block) self.const_set(:MEMBERS, members.collect{|member| member.to_s.to_sym}.freeze) self.const_set(:KEYWORD_INIT, !!kw_args[:keyword_init]) def ns_initialize(*values, **kw_values) - raise ArgumentError.new('struct size differs') if values.length > length || kw_values.length > length - @values = keyword_init? ? members.map{ |val| kw_values.fetch(val, nil) } : values.fill(nil, values.length..length-1) + @values = if keyword_init? + key_diff = kw_values.keys - members + raise ArgumentError.new("unknown keywords: #{key_diff.join(',')}") unless key_diff.empty? + members.map {|val| kw_values.fetch(val, nil)} + else + raise ArgumentError.new('struct size differs') if values.length > length + values.fill(nil, values.length..length-1) + end end end unless name.nil? diff --git a/spec/concurrent/struct_shared.rb b/spec/concurrent/struct_shared.rb index b88b8ceec..77f8fe1ee 100644 --- a/spec/concurrent/struct_shared.rb +++ b/spec/concurrent/struct_shared.rb @@ -101,8 +101,13 @@ def baz(foo, bar) foo + bar; end it 'raises an exception when extra members are given' do classes.each do |clazz| - extra_values = values << 'forty two' - expect{ clazz.new(*extra_values) }.to raise_error(ArgumentError) + if clazz::KEYWORD_INIT + extra_values = kw_values.merge({FortyTwo: 'forty two'}) + expect{ clazz.new(**extra_values) }.to raise_error(ArgumentError) + else + extra_values = values << 'forty two' + expect{ clazz.new(*extra_values) }.to raise_error(ArgumentError) + end end end end