Skip to content

Commit 54df760

Browse files
committed
Update method owner when it is being aliased
1 parent 3e3172d commit 54df760

File tree

7 files changed

+63
-4
lines changed

7 files changed

+63
-4
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Bug fixes:
88
* Fix `rb_id2name` to ensure the native string will have the same lifetime as the id (#2630, @aardvark179).
99
* Fix `MatchData#[]` exception when passing a length argument larger than the number of match values (#2636, @nirvdrum).
1010
* Fix `MatchData#[]` exception when supplying a large negative index along with a length argument (@nirvdrum).
11+
* Fix aliased methods to return the correct owner when method is from a superclass (@bjfish).
1112

1213
Compatibility:
1314

spec/ruby/language/alias_spec.rb

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,19 @@ def test_with_check(*args)
243243
e.class.should == NameError
244244
}
245245
end
246+
247+
it "defines the method on the aliased class when the original method is from a parent class" do
248+
parent = Class.new do
249+
def parent_method
250+
end
251+
end
252+
child = Class.new(parent) do
253+
alias parent_method_alias parent_method
254+
end
255+
256+
child.instance_method(:parent_method_alias).owner.should == child
257+
child.instance_methods(false).should include(:parent_method_alias)
258+
end
246259
end
247260

248261
describe "The alias keyword" do

src/main/java/org/truffleruby/core/method/MethodNodes.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ public abstract static class OwnerNode extends CoreMethodArrayArgumentsNode {
172172

173173
@Specialization
174174
protected RubyModule owner(RubyMethod method) {
175-
return method.method.getDeclaringModule();
175+
return method.method.getOwner();
176176
}
177177

178178
}

src/main/java/org/truffleruby/core/method/UnboundMethodNodes.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ public abstract static class OwnerNode extends CoreMethodArrayArgumentsNode {
155155

156156
@Specialization
157157
protected RubyModule owner(RubyUnboundMethod unboundMethod) {
158-
return unboundMethod.method.getDeclaringModule();
158+
return unboundMethod.method.getOwner();
159159
}
160160

161161
}

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,8 @@ public void initCopy(RubyModule from) {
213213
if (methodEntry.getMethod() != null) {
214214
MethodEntry newMethodEntry = new MethodEntry(methodEntry
215215
.getMethod()
216-
.withDeclaringModule(rubyModule));
216+
.withDeclaringModule(rubyModule)
217+
.withOwner(rubyModule));
217218
this.methods.put(methodEntry.getMethod().getName(), newMethodEntry);
218219
}
219220
}
@@ -513,6 +514,8 @@ public void addMethod(RubyContext context, Node currentNode, InternalMethod meth
513514

514515
checkFrozen(context, currentNode);
515516

517+
method = method.withOwner(rubyModule);
518+
516519
if (SharedObjects.isShared(rubyModule)) {
517520
Set<Object> adjacent = ObjectGraph.newObjectSet();
518521
ObjectGraph.addProperty(adjacent, method);

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,8 @@ public void addMethodIgnoreNameVisibility(RubyContext context, InternalMethod me
9696
singletonClass.fields.addMethod(
9797
context,
9898
currentNode,
99-
method.withDeclaringModule(singletonClass).withVisibility(Visibility.PUBLIC));
99+
method.withDeclaringModule(singletonClass).withOwner(singletonClass)
100+
.withVisibility(Visibility.PUBLIC));
100101
} else {
101102
fields.addMethod(context, currentNode, method.withVisibility(visibility));
102103
}

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

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,10 @@ public class InternalMethod implements ObjectGraphNode {
4040
private final DeclarationContext activeRefinements;
4141
private final String name;
4242

43+
/** The module on which the method was initially declared in the source code (e.g., with def) */
4344
private final RubyModule declaringModule;
45+
/** The module owning this InternalMethod (i.e., the method is part of that module's instance methods) */
46+
private final RubyModule owner;
4447
private final Visibility visibility;
4548
private final boolean undefined;
4649
private final boolean unimplemented; // similar to MRI's rb_f_notimplement
@@ -124,6 +127,7 @@ public InternalMethod(
124127
declarationContext,
125128
name,
126129
declaringModule,
130+
declaringModule,
127131
visibility,
128132
undefined,
129133
false,
@@ -142,6 +146,7 @@ private InternalMethod(
142146
DeclarationContext declarationContext,
143147
String name,
144148
RubyModule declaringModule,
149+
RubyModule owner,
145150
Visibility visibility,
146151
boolean undefined,
147152
boolean unimplemented,
@@ -160,6 +165,7 @@ private InternalMethod(
160165
this.lexicalScope = lexicalScope;
161166
this.declarationContext = declarationContext;
162167
this.declaringModule = declaringModule;
168+
this.owner = owner;
163169
this.name = name;
164170
this.visibility = visibility;
165171
this.undefined = undefined;
@@ -181,6 +187,10 @@ public RubyModule getDeclaringModule() {
181187
return declaringModule;
182188
}
183189

190+
public RubyModule getOwner() {
191+
return owner;
192+
}
193+
184194
public String getName() {
185195
return name;
186196
}
@@ -235,6 +245,31 @@ public InternalMethod withDeclaringModule(RubyModule newDeclaringModule) {
235245
declarationContext,
236246
name,
237247
newDeclaringModule,
248+
owner,
249+
visibility,
250+
undefined,
251+
unimplemented,
252+
builtIn,
253+
alwaysInlinedNodeFactory,
254+
activeRefinements,
255+
proc,
256+
callTarget,
257+
callTargetSupplier,
258+
capturedBlock);
259+
}
260+
}
261+
262+
public InternalMethod withOwner(RubyModule newOwner) {
263+
if (newOwner == owner) {
264+
return this;
265+
} else {
266+
return new InternalMethod(
267+
sharedMethodInfo,
268+
lexicalScope,
269+
declarationContext,
270+
name,
271+
declaringModule,
272+
newOwner,
238273
visibility,
239274
undefined,
240275
unimplemented,
@@ -258,6 +293,7 @@ public InternalMethod withName(String newName) {
258293
declarationContext,
259294
newName,
260295
declaringModule,
296+
owner,
261297
visibility,
262298
undefined,
263299
unimplemented,
@@ -281,6 +317,7 @@ public InternalMethod withVisibility(Visibility newVisibility) {
281317
declarationContext,
282318
name,
283319
declaringModule,
320+
owner,
284321
newVisibility,
285322
undefined,
286323
unimplemented,
@@ -304,6 +341,7 @@ public InternalMethod withActiveRefinements(DeclarationContext context) {
304341
declarationContext,
305342
name,
306343
declaringModule,
344+
owner,
307345
visibility,
308346
undefined,
309347
unimplemented,
@@ -327,6 +365,7 @@ public InternalMethod withDeclarationContext(DeclarationContext newDeclarationCo
327365
newDeclarationContext,
328366
name,
329367
declaringModule,
368+
owner,
330369
visibility,
331370
undefined,
332371
unimplemented,
@@ -347,6 +386,7 @@ public InternalMethod undefined() {
347386
declarationContext,
348387
name,
349388
declaringModule,
389+
owner,
350390
visibility,
351391
true,
352392
unimplemented,
@@ -366,6 +406,7 @@ public InternalMethod unimplemented() {
366406
declarationContext,
367407
name,
368408
declaringModule,
409+
owner,
369410
visibility,
370411
undefined,
371412
true,

0 commit comments

Comments
 (0)