Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 8ac17f336a96
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 07500f83e81d
Choose a head ref
  • 8 commits
  • 9 files changed
  • 1 contributor

Commits on Jun 26, 2017

  1. Copy the full SHA
    0b08a85 View commit details
  2. Copy the full SHA
    9d439e9 View commit details
  3. Copy the full SHA
    f7b57b8 View commit details
  4. Copy the full SHA
    1601fde View commit details
  5. Copy the full SHA
    5fac625 View commit details
  6. Copy the full SHA
    17149a8 View commit details
  7. Copy the full SHA
    55c9dd9 View commit details
  8. Copy the full SHA
    07500f8 View commit details
9 changes: 7 additions & 2 deletions core/src/main/java/org/jruby/AbstractRubyMethod.java
Original file line number Diff line number Diff line change
@@ -83,7 +83,12 @@ public final IRubyObject op_eql19(ThreadContext context, IRubyObject other) {

@JRubyMethod(name = "eql?", required = 1)
public IRubyObject op_eql(ThreadContext context, IRubyObject other) {
return op_equal(context, other);
return context.runtime.newBoolean( equals(other) );
}

@Override
public boolean equals(Object other) {
return this == other;
}

public abstract AbstractRubyMethod rbClone();
@@ -111,7 +116,7 @@ public IRubyObject source_location(ThreadContext context) {
return runtime.newArray(runtime.newString(filename), runtime.newFixnum(getLine()));
}

return context.runtime.getNil();
return context.nil;
}

public String getFilename() {
87 changes: 59 additions & 28 deletions core/src/main/java/org/jruby/RubyBasicObject.java
Original file line number Diff line number Diff line change
@@ -1631,22 +1631,37 @@ public boolean isBuiltin(String methodName) {
}

@JRubyMethod(name = "singleton_method_added", module = true, visibility = PRIVATE)
public static IRubyObject singleton_method_added19(ThreadContext context, IRubyObject recv, IRubyObject symbolId, Block block) {
return context.runtime.getNil();
public static IRubyObject singleton_method_added(ThreadContext context, IRubyObject recv, IRubyObject symbolId, Block block) {
return context.nil;
}

@JRubyMethod(name = "singleton_method_removed", module = true, visibility = PRIVATE)
public static IRubyObject singleton_method_removed19(ThreadContext context, IRubyObject recv, IRubyObject symbolId, Block block) {
return context.runtime.getNil();
public static IRubyObject singleton_method_removed(ThreadContext context, IRubyObject recv, IRubyObject symbolId, Block block) {
return context.nil;
}

@JRubyMethod(name = "singleton_method_undefined", module = true, visibility = PRIVATE)
public static IRubyObject singleton_method_undefined(ThreadContext context, IRubyObject recv, IRubyObject symbolId, Block block) {
return context.nil;
}

@Deprecated
public static IRubyObject singleton_method_added19(ThreadContext context, IRubyObject recv, IRubyObject symbolId, Block block) {
return singleton_method_added(context, recv, symbolId, block);
}

@Deprecated
public static IRubyObject singleton_method_removed19(ThreadContext context, IRubyObject recv, IRubyObject symbolId, Block block) {
return singleton_method_removed(context, recv, symbolId, block);
}

@Deprecated
public static IRubyObject singleton_method_undefined19(ThreadContext context, IRubyObject recv, IRubyObject symbolId, Block block) {
return context.runtime.getNil();
return singleton_method_undefined(context, recv, symbolId, block);
}

@JRubyMethod(name = "method_missing", rest = true, module = true, visibility = PRIVATE)
public static IRubyObject method_missing19(ThreadContext context, IRubyObject recv, IRubyObject[] args, Block block) {
public static IRubyObject method_missing(ThreadContext context, IRubyObject recv, IRubyObject[] args, Block block) {
Visibility lastVis = context.getLastVisibility();
CallType lastCallType = context.getLastCallType();

@@ -1657,26 +1672,31 @@ public static IRubyObject method_missing19(ThreadContext context, IRubyObject re
return RubyKernel.methodMissingDirect(context, recv, (RubySymbol)args[0], lastVis, lastCallType, args);
}

@Deprecated
public static IRubyObject method_missing19(ThreadContext context, IRubyObject recv, IRubyObject[] args, Block block) {
return method_missing(context, recv, args, block);
}

@JRubyMethod(name = "__send__", omit = true)
public IRubyObject send19(ThreadContext context, IRubyObject arg0, Block block) {
public IRubyObject send(ThreadContext context, IRubyObject arg0, Block block) {
String name = RubySymbol.objectToSymbolString(arg0);

return getMetaClass().finvoke(context, this, name, block);
}
@JRubyMethod(name = "__send__", omit = true)
public IRubyObject send19(ThreadContext context, IRubyObject arg0, IRubyObject arg1, Block block) {
public IRubyObject send(ThreadContext context, IRubyObject arg0, IRubyObject arg1, Block block) {
String name = RubySymbol.objectToSymbolString(arg0);

return getMetaClass().finvoke(context, this, name, arg1, block);
}
@JRubyMethod(name = "__send__", omit = true)
public IRubyObject send19(ThreadContext context, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2, Block block) {
public IRubyObject send(ThreadContext context, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2, Block block) {
String name = RubySymbol.objectToSymbolString(arg0);

return getMetaClass().finvoke(context, this, name, arg1, arg2, block);
}
@JRubyMethod(name = "__send__", required = 1, rest = true, omit = true)
public IRubyObject send19(ThreadContext context, IRubyObject[] args, Block block) {
public IRubyObject send(ThreadContext context, IRubyObject[] args, Block block) {
String name = RubySymbol.objectToSymbolString(args[0]);

final int length = args.length - 1;
@@ -2298,13 +2318,15 @@ public RubyBoolean kind_of_p(ThreadContext context, IRubyObject type) {
* k.methods.length #=> 42
*/
public IRubyObject methods(ThreadContext context, IRubyObject[] args) {
return methods(context, args, false);
return methods(context, args, true);
}

@Deprecated
public IRubyObject methods19(ThreadContext context, IRubyObject[] args) {
return methods(context, args, true);
return methods(context, args);
}

public IRubyObject methods(ThreadContext context, IRubyObject[] args, boolean useSymbols) {
public final IRubyObject methods(ThreadContext context, IRubyObject[] args, boolean useSymbols) {
boolean all = args.length == 1 ? args[0].isTrue() : true;
Ruby runtime = getRuntime();
RubyArray methods = runtime.newArray();
@@ -2337,8 +2359,9 @@ public IRubyObject public_methods(ThreadContext context, IRubyObject[] args) {
return getMetaClass().instanceMethods(args, PUBLIC, true, false);
}

@Deprecated
public IRubyObject public_methods19(ThreadContext context, IRubyObject[] args) {
return getMetaClass().instanceMethods(args, PUBLIC, true, false);
return public_methods(context, args);
}

/** rb_obj_protected_methods
@@ -2357,8 +2380,9 @@ public IRubyObject protected_methods(ThreadContext context, IRubyObject[] args)
return getMetaClass().instanceMethods(args, PROTECTED, true, false);
}

@Deprecated
public IRubyObject protected_methods19(ThreadContext context, IRubyObject[] args) {
return getMetaClass().instanceMethods(args, PROTECTED, true, false);
return protected_methods(context, args);
}

/** rb_obj_private_methods
@@ -2377,8 +2401,9 @@ public IRubyObject private_methods(ThreadContext context, IRubyObject[] args) {
return getMetaClass().instanceMethods(args, PRIVATE, true, false);
}

@Deprecated
public IRubyObject private_methods19(ThreadContext context, IRubyObject[] args) {
return getMetaClass().instanceMethods(args, PRIVATE, true, false);
return private_methods(context, args);
}

/** rb_obj_singleton_methods
@@ -2481,12 +2506,13 @@ public RubyArray singleton_methods(ThreadContext context, IRubyObject[] args) {
* m.call #=> "Hello, @iv = Fred"
*/
public IRubyObject method(IRubyObject name) {
return getMetaClass().newMethod(this, name.asJavaString(), true, null);
final RubySymbol symbol = TypeConverter.checkID(name);
return getMetaClass().newMethod(this, symbol.asJavaString(), true, null, true);
}

@Deprecated
public IRubyObject method19(IRubyObject name) {
final RubySymbol symbol = TypeConverter.checkID(name);
return getMetaClass().newMethod(this, symbol.asJavaString(), true, null, true);
return method(name);
}

/** rb_any_to_s
@@ -2658,21 +2684,26 @@ public IRubyObject extend(IRubyObject[] args) {
*
* @return the result of invoking the method identified by aSymbol.
*/
@Deprecated
public IRubyObject send(ThreadContext context, Block block) {
throw context.runtime.newArgumentError(0, 1);
}
public IRubyObject send(ThreadContext context, IRubyObject arg0, Block block) {
return send19(context, arg0, block);
@Deprecated
public IRubyObject send19(ThreadContext context, IRubyObject arg0, Block block) {
return send(context, arg0, block);
}
public IRubyObject send(ThreadContext context, IRubyObject arg0, IRubyObject arg1, Block block) {
return send19(context, arg0, arg1, block);
@Deprecated
public IRubyObject send19(ThreadContext context, IRubyObject arg0, IRubyObject arg1, Block block) {
return send(context, arg0, arg1, block);
}
public IRubyObject send(ThreadContext context, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2, Block block) {
return send19(context, arg0, arg1, arg2, block);
@Deprecated
public IRubyObject send19(ThreadContext context, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2, Block block) {
return send(context, arg0, arg1, arg2, block);
}
public IRubyObject send(ThreadContext context, IRubyObject[] args, Block block) {
if (args.length == 0) return send(context, block);
return send19(context, args, block);
@Deprecated
public IRubyObject send19(ThreadContext context, IRubyObject[] args, Block block) {
if (args.length == 0) throw context.runtime.newArgumentError(0, 1);
return send(context, args, block);
}

/** rb_false
18 changes: 9 additions & 9 deletions core/src/main/java/org/jruby/RubyKernel.java
Original file line number Diff line number Diff line change
@@ -1940,7 +1940,7 @@ public static RubyBoolean kind_of_p(ThreadContext context, IRubyObject self, IRu

@JRubyMethod(name = "methods", optional = 1)
public static IRubyObject methods19(ThreadContext context, IRubyObject self, IRubyObject[] args) {
return ((RubyBasicObject)self).methods19(context, args);
return ((RubyBasicObject)self).methods(context, args);
}

@JRubyMethod(name = "object_id")
@@ -1950,17 +1950,17 @@ public static IRubyObject object_id(IRubyObject self) {

@JRubyMethod(name = "public_methods", optional = 1)
public static IRubyObject public_methods19(ThreadContext context, IRubyObject self, IRubyObject[] args) {
return ((RubyBasicObject)self).public_methods19(context, args);
return ((RubyBasicObject)self).public_methods(context, args);
}

@JRubyMethod(name = "protected_methods", optional = 1)
public static IRubyObject protected_methods19(ThreadContext context, IRubyObject self, IRubyObject[] args) {
return ((RubyBasicObject)self).protected_methods19(context, args);
return ((RubyBasicObject)self).protected_methods(context, args);
}

@JRubyMethod(name = "private_methods", optional = 1)
public static IRubyObject private_methods19(ThreadContext context, IRubyObject self, IRubyObject[] args) {
return ((RubyBasicObject)self).private_methods19(context, args);
return ((RubyBasicObject)self).private_methods(context, args);
}

@JRubyMethod(name = "singleton_methods", optional = 1)
@@ -1970,7 +1970,7 @@ public static RubyArray singleton_methods19(ThreadContext context, IRubyObject s

@JRubyMethod(name = "method", required = 1)
public static IRubyObject method19(IRubyObject self, IRubyObject symbol) {
return ((RubyBasicObject)self).method19(symbol);
return ((RubyBasicObject)self).method(symbol);
}

@JRubyMethod(name = "to_s")
@@ -1985,19 +1985,19 @@ public static IRubyObject extend(IRubyObject self, IRubyObject[] args) {

@JRubyMethod(name = {"send"}, omit = true)
public static IRubyObject send19(ThreadContext context, IRubyObject self, IRubyObject arg0, Block block) {
return ((RubyBasicObject)self).send19(context, arg0, block);
return ((RubyBasicObject)self).send(context, arg0, block);
}
@JRubyMethod(name = {"send"}, omit = true)
public static IRubyObject send19(ThreadContext context, IRubyObject self, IRubyObject arg0, IRubyObject arg1, Block block) {
return ((RubyBasicObject)self).send19(context, arg0, arg1, block);
return ((RubyBasicObject)self).send(context, arg0, arg1, block);
}
@JRubyMethod(name = {"send"}, omit = true)
public static IRubyObject send19(ThreadContext context, IRubyObject self, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2, Block block) {
return ((RubyBasicObject)self).send19(context, arg0, arg1, arg2, block);
return ((RubyBasicObject)self).send(context, arg0, arg1, arg2, block);
}
@JRubyMethod(name = {"send"}, required = 1, rest = true, omit = true)
public static IRubyObject send19(ThreadContext context, IRubyObject self, IRubyObject[] args, Block block) {
return ((RubyBasicObject)self).send19(context, args, block);
return ((RubyBasicObject)self).send(context, args, block);
}

@JRubyMethod(name = "nil?")
77 changes: 49 additions & 28 deletions core/src/main/java/org/jruby/RubyMethod.java
Original file line number Diff line number Diff line change
@@ -143,34 +143,51 @@ public RubyFixnum arity() {
return getRuntime().newFixnum(value);
}

@JRubyMethod(name = "eql?", required = 1)
public IRubyObject op_eql(ThreadContext context, IRubyObject other) {
return op_equal(context, other);
}

@Override
@JRubyMethod(name = "==", required = 1)
public RubyBoolean op_equal(ThreadContext context, IRubyObject other) {
return context.runtime.newBoolean( equals(other) );
}

@Override
public boolean equals(Object other) {
if (!(other instanceof RubyMethod)) {
return context.runtime.getFalse();
return false;
}
if (method instanceof ProcMethod) {
return context.runtime.newBoolean(((ProcMethod) method).isSame(((RubyMethod) other).getMethod()));
return ((ProcMethod) method).isSame(((RubyMethod) other).getMethod());
}
RubyMethod otherMethod = (RubyMethod)other;
return context.runtime.newBoolean(receiver == otherMethod.receiver &&
originModule == otherMethod.originModule &&
(isMethodMissingMatch(otherMethod.getMethod().getRealMethod()) || isSerialMatch(otherMethod.getMethod().getRealMethod()))
);
return receiver == otherMethod.receiver && originModule == otherMethod.originModule &&
( isSerialMatch(otherMethod.method) || isMethodMissingMatch(otherMethod.getMethod().getRealMethod()) );
}

private boolean isMethodMissingMatch(DynamicMethod other) {
return (method.getRealMethod() instanceof RubyModule.RespondToMissingMethod) &&
((RubyModule.RespondToMissingMethod)method.getRealMethod()).equals(other);
((RubyModule.RespondToMissingMethod) method.getRealMethod()).equals(other);
}

private boolean isSerialMatch(DynamicMethod otherMethod) {
return method.getRealMethod().getSerialNumber() == otherMethod.getRealMethod().getSerialNumber();
}

@JRubyMethod(name = "eql?", required = 1)
public IRubyObject op_eql(ThreadContext context, IRubyObject other) {
return op_equal(context, other);
@JRubyMethod
public RubyFixnum hash(ThreadContext context) {
return context.runtime.newFixnum(hashCodeImpl());
}

@Override
public int hashCode() {
return (int) hashCodeImpl();
}

private long hashCodeImpl() {
return receiver.hashCode() * method.getRealMethod().getSerialNumber();
}

@JRubyMethod(name = "clone")
@@ -217,36 +234,40 @@ public RubyUnboundMethod unbind() {
@JRubyMethod(name = {"inspect", "to_s"})
@Override
public IRubyObject inspect() {
StringBuilder buf = new StringBuilder("#<");
char delimeter = '#';

buf.append(getMetaClass().getRealClass().getName()).append(": ");
StringBuilder str = new StringBuilder(24).append("#<");
char sharp = '#';

str.append(getMetaClass().getRealClass().getName()).append(": ");

if (implementationModule.isSingleton()) {
IRubyObject attached = ((MetaClass) implementationModule).getAttached();
if (receiver == null) {
buf.append(implementationModule.inspect().toString());
str.append(implementationModule.inspect().toString());
} else if (receiver == attached) {
buf.append(attached.inspect().toString());
delimeter = '.';
str.append(attached.inspect().toString());
sharp = '.';
} else {
buf.append(receiver.inspect().toString());
buf.append('(').append(attached.inspect().toString()).append(')');
delimeter = '.';
str.append(receiver.inspect().toString());
str.append('(').append(attached.inspect().toString()).append(')');
sharp = '.';
}
} else {
buf.append(originModule.getName());

str.append(originModule.getName());
if (implementationModule != originModule) {
buf.append('(').append(implementationModule.getName()).append(')');
str.append('(').append(implementationModule.getName()).append(')');
}
}

str.append(sharp).append(methodName); // (real-name) if alias
final String realName= method.getRealMethod().getName();
if ( realName != null && ! methodName.equals(realName) ) {
str.append('(').append(realName).append(')');
}
str.append('>');

buf.append(delimeter).append(methodName).append('>');

RubyString str = RubyString.newString(getRuntime(), buf);
str.setTaint(isTaint());
return str;
RubyString res = RubyString.newString(getRuntime(), str);
res.setTaint(isTaint());
return res;
}

@JRubyMethod
56 changes: 37 additions & 19 deletions core/src/main/java/org/jruby/RubyUnboundMethod.java
Original file line number Diff line number Diff line change
@@ -82,19 +82,32 @@ public static RubyClass defineUnboundMethodClass(Ruby runtime) {
return newClass;
}

@JRubyMethod(name = "==", required = 1)
@Override
@JRubyMethod(name = "==", required = 1)
public RubyBoolean op_equal(ThreadContext context, IRubyObject other) {
if (!(other instanceof AbstractRubyMethod)) {
return context.runtime.getFalse();
}
return context.runtime.newBoolean( equals(other) );
}

@Override
public boolean equals(Object other) {
if (!(other instanceof AbstractRubyMethod)) return false;
if (method instanceof ProcMethod) {
return context.runtime.newBoolean(((ProcMethod) method).isSame(((AbstractRubyMethod) other).getMethod()));
return ((ProcMethod) method).isSame(((AbstractRubyMethod) other).getMethod());
}
AbstractRubyMethod otherMethod = (AbstractRubyMethod)other;
return context.runtime.newBoolean(
originModule == otherMethod.originModule &&
method.getRealMethod().getSerialNumber() == otherMethod.method.getRealMethod().getSerialNumber());
AbstractRubyMethod otherMethod = (AbstractRubyMethod) other;
return originModule == otherMethod.originModule &&
method.getRealMethod().getSerialNumber() == otherMethod.method.getRealMethod().getSerialNumber();
}

@JRubyMethod
public RubyFixnum hash(ThreadContext context) {
return context.runtime.newFixnum(hashCode());
}

@Override
public int hashCode() {
long serial = method.getRealMethod().getSerialNumber();
return 997 * ((int) (serial >> 32) ^ (int) serial & 0xFF);
}

@JRubyMethod
@@ -115,26 +128,31 @@ public RubyUnboundMethod rbClone() {
@JRubyMethod(name = {"inspect", "to_s"})
@Override
public IRubyObject inspect() {
StringBuilder buf = new StringBuilder("#<");
char delimeter = '#';
StringBuilder str = new StringBuilder(24).append("#<");
char sharp = '#';

buf.append(getMetaClass().getRealClass().getName()).append(": ");
str.append(getMetaClass().getRealClass().getName()).append(": ");

if (implementationModule.isSingleton()) {
buf.append(implementationModule.inspect().toString());
str.append(implementationModule.inspect().toString());
} else {
buf.append(originModule.getName());
str.append(originModule.getName());

if (implementationModule != originModule) {
buf.append('(').append(implementationModule.getName()).append(')');
str.append('(').append(implementationModule.getName()).append(')');
}
}

buf.append(delimeter).append(methodName).append('>');
str.append(sharp).append(methodName); // (real-name) if alias
final String realName= method.getRealMethod().getName();
if ( realName != null && ! methodName.equals(realName) ) {
str.append('(').append(realName).append(')');
}
str.append('>');

RubyString str = getRuntime().newString(buf.toString());
str.setTaint(isTaint());
return str;
RubyString res = RubyString.newString(getRuntime(), str);
res.setTaint(isTaint());
return res;
}

@JRubyMethod
Original file line number Diff line number Diff line change
@@ -123,4 +123,12 @@ public DynamicMethod getRealMethod() {
public long getSerialNumber() {
return oldMethod.getSerialNumber();
}

@Override
public RubyModule getDefinedClass() {
RubyModule definedClass = this.definedClass;
if (definedClass != null) return definedClass;
return oldMethod.getDefinedClass();
}

}
Original file line number Diff line number Diff line change
@@ -108,4 +108,12 @@ public DynamicMethod getRealMethod() {
public Arity getArity() {
return method.getArity();
}

@Override
public RubyModule getDefinedClass() {
RubyModule definedClass = this.definedClass;
if (definedClass != null) return definedClass;
return method.getDefinedClass();
}

}
57 changes: 56 additions & 1 deletion test/jruby/test_method.rb
Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@ def test_function_break
def obj.broken_method
break # TODO this is a SyntaxError on MRI 2.2.2
end
assert_raise(LocalJumpError){obj.broken_method}
assert_raise(LocalJumpError){ obj.broken_method }
end

module Methods
@@ -74,4 +74,59 @@ def test_callee # (passing) part from *mri/ruby/test_method.rb*
assert_nil(eval("class TestCallee; __callee__; end"))
end

def test_eq # (modified) part from *mri/ruby/test_method.rb*
o = Object.new
class << o
def foo; end
alias muu foo
def baz; end
alias bar baz
end
assert_not_equal(o.method(:foo), nil)
m = o.method(:foo)
def o.foo; end
assert_not_equal(o.method(:foo), m)
assert_equal(o.method(:foo), o.method(:foo))
assert_equal(o.method(:baz), o.method(:bar))
assert_not_equal(o.method(:foo), o.method(:baz))
assert_not_equal(o.method(:foo), o.method(:muu))

assert_equal(String.instance_method(:to_s), String.instance_method(:to_str))

assert_not_equal([0].method(:map), [].method(:map))
end

def test_hash
o = Object.new
def o.foo; end
class << o
alias bar foo
end

hash = o.method(:foo).hash
assert_kind_of(Integer, hash)
assert_equal(hash, o.method(:bar).hash)

hash = String.instance_method(:to_s).hash
assert_kind_of(Integer, hash)
assert_equal(hash, String.instance_method(:to_str).hash)

assert_not_equal([0].method(:map).hash, [].method(:map).hash)
end

def test_inspect
c = Class.new do
def foo; end; alias bar foo
end
m = c.new.method(:foo)
assert_equal("#<Method: #{c.inspect}#foo>", m.inspect)
m = c.instance_method(:foo)
assert_equal("#<UnboundMethod: #{c.inspect}#foo>", m.inspect)

m = c.new.method(:bar)
assert_equal("#<Method: #{c.inspect}#bar(foo)>", m.inspect)
m = c.instance_method(:bar)
assert_equal("#<UnboundMethod: #{c.inspect}#bar(foo)>", m.inspect)
end

end
5 changes: 2 additions & 3 deletions test/mri/excludes/TestMethod.rb
Original file line number Diff line number Diff line change
@@ -4,10 +4,9 @@
exclude :test_clone, "needs investigation"
exclude :test_define_method_visibility, "needs investigation"
exclude :test_define_method_with_symbol, "scope changes in define_method methods?"
exclude :test_eq, "needs investigation"
exclude :test_eq, "weird logic for != when patching an object retuned from o.method, likely irrelevant"
exclude :test_gced_bmethod, "often 'Timeout::Error: execution of assert_normal_exit expired' on CI"
exclude :test_hash, "needs investigation"
exclude :test_inspect, "needs investigation"
exclude :test_hash, "won't pass since Array#map is not a Array#collect alias as in MRI"
exclude :test_orphan_callee, "needs investigation"
exclude :test_singleton_method, "needs investigation"
exclude :test_splat_long_array, "passes locally but fails on travis OOME"