Skip to content

Commit ff89f89

Browse files
committed
Only clear $~ once when #match "fails"
``` $ ips --ruby ruby-dev --ruby ruby-master -e '"".match?(/a/)' -e '"".match(/a/)' ruby 4.1.0dev (2026-07-28T19:56:48Z master 120c8fa) +PRISM [arm64-darwin25] "".match?(/a/): 40.578M i/s (± 1.4%) "".match(/a/): 23.439M i/s (± 1.7%) ruby 4.1.0dev (2026-07-28T19:56:48Z master 120c8fa) +PRISM [arm64-darwin25] "".match?(/a/): 40.357M i/s (± 1.7%) "".match(/a/): 20.285M i/s (± 1.5%) Summary "".match?(/a/) (ruby ruby-dev) ran 1.01 ± 0.02 times faster than "".match?(/a/) (ruby ruby-master) 1.73 ± 0.04 times faster than "".match(/a/) (ruby ruby-dev) 2.00 ± 0.04 times faster than "".match(/a/) (ruby ruby-master) ``` Previously, `reg_match_pos` cleared `$~` in every case where it returned a negative offset except one: when a negative `pos` argument underflows the start of the string. `rb_reg_match_m` had to account for this by clearing `$~` for _any_ negative return, so every failed `Regexp#match` (and `String#match`) which doesn't underflow ended up calling `rb_backref_set` twice. This commit moves the clear into the branch that was missing it, so `reg_match_pos` maintains `$~` on all of its negative returns and its callers no longer have to.
1 parent 120c8fa commit ff89f89

1 file changed

Lines changed: 1 addition & 1 deletion

File tree

re.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3830,6 +3830,7 @@ reg_match_pos(VALUE re, VALUE *strp, long pos, VALUE* set_match)
38303830
VALUE l = rb_str_length(str);
38313831
pos += NUM2INT(l);
38323832
if (pos < 0) {
3833+
rb_backref_set(Qnil);
38333834
return pos;
38343835
}
38353836
}
@@ -4024,7 +4025,6 @@ rb_reg_match_m(int argc, VALUE *argv, VALUE re)
40244025

40254026
pos = reg_match_pos(re, &str, pos, &result);
40264027
if (pos < 0) {
4027-
rb_backref_set(Qnil);
40284028
return Qnil;
40294029
}
40304030
rb_match_busy(result);

0 commit comments

Comments
 (0)