Skip to content

Commit f9395b1

Browse files
committed
[GR-18163] Fix import_methods supports module methods with super
PullRequest: truffleruby/3746
2 parents 4229c48 + 0434b56 commit f9395b1

File tree

3 files changed

+51
-24
lines changed

3 files changed

+51
-24
lines changed

spec/ruby/core/refinement/import_methods_spec.rb

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,6 @@ def indent(level)
125125
suppress_warning { import_methods RefinementSpec::ModuleWithAncestors }
126126
end
127127

128-
129128
using self
130129
-> {
131130
"foo".indent(3)
@@ -134,26 +133,26 @@ def indent(level)
134133
end
135134

136135
it "doesn't import any methods if one of the arguments is not a module" do
137-
str_utils = Module.new do
138-
def indent(level)
139-
" " * level + self
140-
end
141-
end
142-
143-
string_refined = Module.new do
144-
refine String do
145-
-> {
146-
import_methods str_utils, Integer
147-
}.should raise_error(TypeError)
148-
end
136+
str_utils = Module.new do
137+
def indent(level)
138+
" " * level + self
149139
end
140+
end
150141

151-
Module.new do
152-
using string_refined
142+
string_refined = Module.new do
143+
refine String do
153144
-> {
154-
"foo".indent(3)
155-
}.should raise_error(NoMethodError)
145+
import_methods str_utils, Integer
146+
}.should raise_error(TypeError)
156147
end
148+
end
149+
150+
Module.new do
151+
using string_refined
152+
-> {
153+
"foo".indent(3)
154+
}.should raise_error(NoMethodError)
155+
end
157156
end
158157

159158
it "imports methods from multiple modules so that methods see other's module's methods" do
@@ -219,6 +218,31 @@ def self.indent(level)
219218
end
220219
end
221220

221+
it "imports module methods with super" do
222+
class_to_refine = Class.new do
223+
def foo(number)
224+
2 * number
225+
end
226+
end
227+
228+
extension = Module.new do
229+
def foo(number)
230+
super * 2
231+
end
232+
end
233+
234+
refinement = Module.new do
235+
refine class_to_refine do
236+
import_methods extension
237+
end
238+
end
239+
240+
Module.new do
241+
using refinement
242+
class_to_refine.new.foo(2).should == 8
243+
end
244+
end
245+
222246
context "when methods are not defined in Ruby code" do
223247
it "raises ArgumentError" do
224248
Module.new do

src/main/java/org/truffleruby/core/module/ModuleNodes.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2489,7 +2489,7 @@ private String createErrorMessage(InternalMethod method, RubyModule module) {
24892489
private void importMethodsFromModuleToRefinement(RubyModule module, RubyModule refinement) {
24902490
var declarationContext = createDeclarationContextWithRefinement(refinement);
24912491
for (InternalMethod methodToCopy : module.fields.getMethods()) {
2492-
var clonedMethod = cloneMethod(methodToCopy, declarationContext);
2492+
var clonedMethod = cloneMethod(methodToCopy, declarationContext, refinement);
24932493
refinement.fields.addMethod(getContext(), this, clonedMethod);
24942494
}
24952495
}
@@ -2514,9 +2514,11 @@ private DeclarationContext createDeclarationContextWithRefinement(RubyModule ref
25142514
refinements);
25152515
}
25162516

2517-
private InternalMethod cloneMethod(InternalMethod method, DeclarationContext declarationContext) {
2517+
private InternalMethod cloneMethod(InternalMethod method, DeclarationContext declarationContext,
2518+
RubyModule refinement) {
25182519
var clonedCallTarget = cloneCallTarget(method);
2519-
return method.withCallTargetAndDeclarationContext(clonedCallTarget, declarationContext);
2520+
return method.withCallTargetAndDeclarationContextAndDeclarationModule(clonedCallTarget, declarationContext,
2521+
refinement);
25202522
}
25212523

25222524
private RootCallTarget cloneCallTarget(InternalMethod method) {

src/main/java/org/truffleruby/language/methods/InternalMethod.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -384,17 +384,18 @@ public InternalMethod withDeclarationContext(DeclarationContext newDeclarationCo
384384
}
385385
}
386386

387-
public InternalMethod withCallTargetAndDeclarationContext(RootCallTarget rootCallTarget,
388-
DeclarationContext newDeclarationContext) {
389-
if (rootCallTarget == this.callTarget && newDeclarationContext == declarationContext) {
387+
public InternalMethod withCallTargetAndDeclarationContextAndDeclarationModule(RootCallTarget rootCallTarget,
388+
DeclarationContext newDeclarationContext, RubyModule newDeclaringModule) {
389+
if (rootCallTarget == this.callTarget && newDeclarationContext == declarationContext &&
390+
newDeclaringModule == this.declaringModule) {
390391
return this;
391392
} else {
392393
return new InternalMethod(
393394
sharedMethodInfo,
394395
lexicalScope,
395396
newDeclarationContext,
396397
name,
397-
declaringModule,
398+
newDeclaringModule,
398399
owner,
399400
visibility,
400401
undefined,

0 commit comments

Comments
 (0)