[#108552] [Ruby master Bug#18782] Race conditions in autoload when loading the same feature with multiple threads. — "ioquatix (Samuel Williams)" <noreply@...>
Issue #18782 has been reported by ioquatix (Samuel Williams).
11 messages
2022/05/14
[ruby-core:108656] [Ruby master Feature#18788] Support passing Regexp options as String to Regexp.new
From:
janosch-x <noreply@...>
Date:
2022-05-23 10:17:54 UTC
List:
ruby-core #108656
Issue #18788 has been updated by janosch-x (Janosch M端ller).
@nobu
Thank you for the explanation regarding symbols!
> we'll need migration period to warn anything other than inter and valid string
I think the optional third argument should be also deprecated as described in #18797. Otherwise we might still want to allow `nil` as "stopgap" value for the second argument.
> Regexp.new(code, eval("//#{options}").options)
This feels too unsafe for some of the cases mentioned above.
> Regexp.new("(?#{options}:#{code})")
This is clever and will work for most of the use cases mentioned above. Just a few minor downsides:
1. The group options syntax isn't so well-known and universally understood.
2. A few use cases might need to preserve notation (e.g. codemod).
3. The result may become verbose in case of recursion or nesting of Regexps.
----------------------------------------
Feature #18788: Support passing Regexp options as String to Regexp.new
https://bugs.ruby-lang.org/issues/18788#change-97699
* Author: janosch-x (Janosch M端ller)
* Status: Open
* Priority: Normal
----------------------------------------
## Current situation
`Regexp.new` takes an integer as second argument which needs to be ORed together from multiple constants:
```
Regexp.new('foo', Regexp::IGNORECASE | Regexp::MULTILINE | Regexp::EXTENDED) # => /foo/imx
```
Any other non-nil value is treated as `i` flag:
```
Regexp.new('foo', Object.new) # => /foo/i
```
## Suggestion
`Regexp.new` should support passing the regexp flags not only as an Integer, but also as a String or Symbol, like so:
```
Regexp.new('foo', 'i') # => /foo/i
Regexp.new('foo', :i) # => /foo/i
Regexp.new('foo', 'imx') # => /foo/imx
Regexp.new('foo', :imx) # => /foo/imx
# edge cases
Regexp.new('foo', 'iii') # => /foo/i
Regexp.new('foo', :iii) # => /foo/i
Regexp.new('foo', '') # => /foo/
Regexp.new('foo', :'') # => /foo/
# unsupported flags could be ignored -
# or raise an ArgumentError to reveal changed behavior?
Regexp.new('foo', 'jmq') # => /foo/m
Regexp.new('foo', :jmq) # => /foo/m
Regexp.new('foo', '-m') # => /foo/m
Regexp.new('foo', :'-m') # => /foo/m
```
## Reasons
1. The constants are a bit cumbersome to use, particularly when building the regexp from variable data:
```
def make_regexp(regexp_body, opt_string)
opt_int = 0
opt_int |= Regexp::IGNORECASE if opt_string.include?('i')
opt_int |= Regexp::MULTILINE if opt_string.include?('m')
opt_int |= Regexp::EXTENDED if opt_string.include?('x')
Regexp.new(regexp_body, opt_int)
end
```
2. Passing a String or Symbol is already silently accepted, and people might get the wrong impression that it works:
```
Regexp.new('foo', 'i') # => /foo/i
Regexp.new('foo', :i) # => /foo/i
```
... but it doesn't really work:
```
Regexp.new('foo', 'x') # => /foo/i
Regexp.new('foo', :x) # => /foo/i
```
## Backwards compatibility
This change would not be fully backwards compatible.
Code that relies on the second argument being either a String/Symbol or nil to decide whether the Regexp should be case insensitive would break (unless the String or Symbol contains "i").
I can't come up with a scenario where one would write such code, though - except maybe code golfing?
--
https://bugs.ruby-lang.org/
Unsubscribe: <mailto:[email protected]?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>