Feature #19344
openRegexp.new: stricter handling of second argument
Description
Since Ruby 3.2 (#18788), the second argument to Regexp.new
can be:
- Integer: then it is treated as a combination of
Regexp::<constant>
flags - String: then it is treated as a combination of string flags
-
nil
orfalse
: then it is ignored - any other truthy value: then it is treated as an "ignore case" option.
The fourth one is confusing, especially since the introduction of the flexibility of flags: one might erroneously assume or forget the protocol, and the naive check will strengthen the assumption:
# maybe it accepts the array of string options?..
Regexp.new('foo', %w[i]) #=> /foo/i -- oh, seems it does
# would the symbol work?..
Regexp.new('foo', :i) #=> /foo/i -- awesome, it works!
I propose to change (4) to only handle literal true
value, and raise TypeError
on any unsupported type.
On compatibility: I believe that whenever the usage of boolean to distinguish "ignore case/respect case" is deliberate (like in rubygems), the code already passes true/false, not any random value. Otherwise, the change in Ruby 3.2 might also have broken it (what if it previously passed strings, meaning them to be "truthy values"?)
PS: BTW, the documentation for (4) was completely lost in Ruby 3.2, due to this PR. cc @jeremyevans0 (Jeremy Evans), @burdettelamar (Burdette Lamar)
Updated by nobu (Nobuyoshi Nakada) almost 2 years ago
It is already warned with $VERBOSE
, and this make to raise ArgumentError
.
diff --git a/re.c b/re.c
index 7a743185589..f03c2b48a1e 100644
--- a/re.c
+++ b/re.c
@@ -3866,7 +3866,7 @@ reg_extract_args(int argc, VALUE *argv, struct reg_init_args *args)
int f;
if (FIXNUM_P(opts)) flags = FIX2INT(opts);
else if ((f = str_to_option(opts)) >= 0) flags = f;
- else if (!NIL_P(opts) && rb_bool_expected(opts, "ignorecase", FALSE))
+ else if (!NIL_P(opts) && rb_bool_expected(opts, "ignorecase", TRUE))
flags = ONIG_OPTION_IGNORECASE;
}
if (!NIL_OR_UNDEF_P(n_flag)) {