Fix logic for responds_to?
of generic module instances
#10760
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Fixes #8334 (more specifically snippet 4 there). This resembles #10519 but the mechanisms are vastly different.
There are essentially two kinds of logic used in
responds_to?(:foo)
filters:T
or its parents define any method calledfoo
, the filtered type isT
.T
, through either including or inheritingT
, that respond tofoo
.Virtual classes and modules are supposed to use the latter, but generic module instances use the former for some reason. This PR makes them behave like non-generic modules:
One consequence is that even if the generic module itself defines that method,
responds_to?
will filter the variable to all including types of the module:This behaviour is currently consistent with non-generic modules. There might be a follow-up PR to make modules exhibit both non-virtual logic and fall back to virtual logic, which can eliminate very large unions and/or
NoReturn
in some places. (In fact I said the exact same thing on #10519.)Type filtering and codegen are both backed by
Crystal::Type#filter_by_responds_to
so this PR fixes both at once.