Detect incompatible use of `Struct.new` in Ruby 3.1 / 3.2
Problem
Since Ruby 3.2 (https://www.ruby-lang.org/en/news/2022/12/25/ruby-3-2-0-released/) Struct
supports kwargs by default so keyword_init: true
is no longer required.
We are running Ruby 3.2 in MRs and Ruby 3.1 on master
so occasionally master is broken due to this incompatibility.
For example:
# Note no `keyword_init: true`.
Foo = Struct.new(:foo)
# Works in Ruby 3.2
Foo.new(foo: 42)
=> #<struct Foo foo=42>
# Fails in Ruby 3.1
Foo.new(foo: 42)
(irb):3: warning: Passing only keyword arguments to Struct#initialize will behave differently from Ruby 3.2. Please use a Hash literal like .new({k: v}) instead of .new(k: v).
=> #<struct Foo foo={:foo=>42}>
We need to add keyword_init: true
as in Struct.new(:foo, keyword_init: true)
.
See:
- gitlab-org/quality/engineering-productivity/master-broken-incidents#7259 (closed)
- gitlab-org/quality/engineering-productivity/master-broken-incidents#7667 (closed)
Proposed
Detect if Struct.new
is used without keyword_init: true
but a hash is passed to Struct
's instance.
Alternatively, wait until Ruby 3.1 is phased out.