Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid adding constants to Enumerable #44611

Merged
merged 1 commit into from Mar 4, 2022

Conversation

casperisfine
Copy link
Contributor

Ref: aws/aws-sdk-ruby#2670

Some gems like aws-sdk-core use Object#extend(Enumerable). It's not a very good pattern, but it's somehwat handled ok by Ruby.

However if Enumerable has constants, then any time the module is extended, the global constant cache is flushed and this has a very negative impact on performance for the virtual machine, and even worse for JITs.

I tried to preserve backward compatibility as much as possible, so Enumerable::SoleItemExpectedError can still be referenced.

@casperisfine casperisfine force-pushed the no-enumerable-constants branch 6 times, most recently from 11e67fe to 73b0adb Compare March 4, 2022 12:27
Ref: aws/aws-sdk-ruby#2670

Some gems like aws-sdk-core use `Object#extend(Enumerable)`.
It's not a very good pattern, but it's somehwat handled ok by Ruby.

However if Enumerable has constants, then any time the module is
extended, the global constant cache is flushed and this has a very
negative impact on performance for the virtual machine, and even
worse for JITs.
@byroot
Copy link
Member

byroot commented Mar 4, 2022

Discussed this with @matthewd, he agreed that it's a bit ugly, but unfortunately necessary, so I'll merge.

@byroot byroot merged commit b783e8a into rails:main Mar 4, 2022
@casperisfine casperisfine deleted the no-enumerable-constants branch March 4, 2022 12:48
@etiennebarrie
Copy link
Contributor

One thing that's not compatible is Enumerable.constants which used to return [:SoleItemExpectedError] and now doesn't anymore. I don't think that's a huge deal though.

I think that hack shouldn't stick around though, should we deprecate that constant and have it somewhere else, maybe simply ActiveSupport::SoleItemExpectedError?

@byroot
Copy link
Member

byroot commented Mar 4, 2022

should we deprecate that constant and have it somewhere else, maybe simply ActiveSupport::SoleItemExpectedError?

Yeah, I though about this and I'd be in favour of it.

@matthewd what do you think?

@byroot
Copy link
Member

byroot commented Mar 4, 2022

Another idea was to raise something like IndexError, but not sure if it would be backward compatible enough.

@matthewd
Copy link
Member

matthewd commented Mar 4, 2022

I like that its current location is more communicative about where it came from (essentially contextualizing the words ("sole") in the actual constant name, helping to point to what's complaining). But it's also pretty easy to mount an argument that we shouldn't be littering constants outside our namespace without a very good reason, and this is not that.

... and thinking further, realistically, it's a "your code has a bug" exception, so not one I'd expect people to have much need of rescuing [and thus referencing]. Yeah, maybe let's just drop it in ActiveSupport. Slightly unfortunate to pollute that top-level namespace, but there's no existing deeper namespace that makes sense... and given the low likelihood of direct references, it's not catastrophic if we decide to move it again later. 🤷🏻‍♂️

(From a quick survey, we do litter Module::DelegationError, while the other core_ext-defined errors end up in separately-necessary namespaced support classes.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants