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: 8737eb54b0ff
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: f4f1e596854a
Choose a head ref
  • 5 commits
  • 4 files changed
  • 1 contributor

Commits on Sep 11, 2014

  1. Clean up javadocs.

    headius committed Sep 11, 2014
    Copy the full SHA
    5dc303f View commit details
  2. Match MRI error text.

    headius committed Sep 11, 2014
    Copy the full SHA
    03c93e7 View commit details
  3. Add to_a and to_ary cases.

    headius committed Sep 11, 2014
    Copy the full SHA
    b0cd4d3 View commit details
  4. Clean up imports.

    headius committed Sep 11, 2014
    Copy the full SHA
    a75da25 View commit details
  5. Fix new coercion logic.

    MRI's tests for respond_to? also included a test for NOEX_BASIC,
    which appears to be a flag only added to respond_to?,
    respond_to_missing?, and method_missing. We do not have this flag,
    so instead we just check that respond_to? is not the builtin
    version.
    headius committed Sep 11, 2014
    Copy the full SHA
    f4f1e59 View commit details
8 changes: 5 additions & 3 deletions core/src/main/java/org/jruby/RubyClass.java
Original file line number Diff line number Diff line change
@@ -659,7 +659,9 @@ private static boolean checkFuncallRespondTo(ThreadContext context, RubyClass kl
RubyClass defined_class;
DynamicMethod me = klass.searchMethod("respond_to?");

if (me != null && !me.isUndefined()) {
// NOTE: isBuiltin here would be NOEX_BASIC in MRI, a flag only added to respond_to?, method_missing, and
// respond_to_missing? Same effect, I believe.
if (me != null && !me.isUndefined() && !me.isBuiltin()) {
Arity arity = me.getArity();

if (arity.getValue() > 2)
@@ -675,8 +677,8 @@ private static boolean checkFuncallRespondTo(ThreadContext context, RubyClass kl

// MRI: check_funcall_callable
public static boolean checkFuncallCallable(ThreadContext context, DynamicMethod method) {
// FIXME: MRI actually checks protectedness here too
return !method.getVisibility().isPrivate();
// FIXME: MRI actually checks protectedness here too and has more complex private logic
return method != null && !method.isUndefined() && !method.getVisibility().isPrivate();
}

private static IRubyObject checkFuncallMissing(ThreadContext context, RubyClass klass, IRubyObject self, String method, IRubyObject... args) {
52 changes: 24 additions & 28 deletions core/src/main/java/org/jruby/util/TypeConverter.java
Original file line number Diff line number Diff line change
@@ -26,8 +26,6 @@
***** END LICENSE BLOCK *****/
package org.jruby.util;

import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import org.jruby.Ruby;
import org.jruby.RubyArray;
import org.jruby.RubyBignum;
@@ -43,34 +41,32 @@
import org.jruby.exceptions.RaiseException;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.encoding.EncodingService;

public class TypeConverter {
/**
* Converts this object to type 'targetType' using 'convertMethod' method (MRI: convert_type).
* Converts this object to type 'target' using 'convertMethod' method (MRI: convert_type).
*
* @param obj the object to convert
* @param targetType is the type we are trying to convert to
* @param target is the type we are trying to convert to
* @param convertMethodIndex the fast index to use for calling the method
* @param convertMethod is the method to be called to try and convert to targeType
* @param raiseOnError will throw an Error if conversion does not work
* @param raise will throw an Error if conversion does not work
* @return the converted value
*/
@Deprecated
public static final IRubyObject convertToType(IRubyObject obj, RubyClass target, int convertMethodIndex, String convertMethod, boolean raise) {
if (!obj.respondsTo(convertMethod)) return handleUncoercibleObject(raise, obj, target);

return obj.callMethod(obj.getRuntime().getCurrentContext(), convertMethod);
}

/**
* Converts this object to type 'targetType' using 'convertMethod' method (MRI: convert_type).
* Converts this object to type 'target' using 'convertMethod' method (MRI: convert_type).
*
* @param obj the object to convert
* @param targetType is the type we are trying to convert to
* @param convertMethodIndex the fast index to use for calling the method
* @param target is the type we are trying to convert to
* @param convertMethod is the method to be called to try and convert to targeType
* @param raiseOnError will throw an Error if conversion does not work
* @param raise will throw an Error if conversion does not work
* @return the converted value
*/
public static final IRubyObject convertToType(IRubyObject obj, RubyClass target, String convertMethod, boolean raise) {
@@ -80,13 +76,12 @@ public static final IRubyObject convertToType(IRubyObject obj, RubyClass target,
}

/**
* Converts this object to type 'targetType' using 'convertMethod' method (MRI: convert_type 1.9).
* Converts this object to type 'target' using 'convertMethod' method (MRI: convert_type 1.9).
*
* @param obj the object to convert
* @param targetType is the type we are trying to convert to
* @param convertMethodIndex the fast index to use for calling the method
* @param target is the type we are trying to convert to
* @param convertMethod is the method to be called to try and convert to targeType
* @param raiseOnError will throw an Error if conversion does not work
* @param raise will throw an Error if conversion does not work
* @return the converted value
*/
public static final IRubyObject convertToType19(IRubyObject obj, RubyClass target, String convertMethod, boolean raise) {
@@ -96,10 +91,10 @@ public static final IRubyObject convertToType19(IRubyObject obj, RubyClass targe
}

/**
* Converts this object to type 'targetType' using 'convertMethod' method and raises TypeError exception on failure (MRI: rb_convert_type).
* Converts this object to type 'target' using 'convertMethod' method and raises TypeError exception on failure (MRI: rb_convert_type).
*
* @param obj the object to convert
* @param targetType is the type we are trying to convert to
* @param target is the type we are trying to convert to
* @param convertMethodIndex the fast index to use for calling the method
* @param convertMethod is the method to be called to try and convert to targeType
* @return the converted value
@@ -113,10 +108,10 @@ public static final IRubyObject convertToType(IRubyObject obj, RubyClass target,
}

/**
* Converts this object to type 'targetType' using 'convertMethod' method and raises TypeError exception on failure (MRI: rb_convert_type).
* Converts this object to type 'target' using 'convertMethod' method and raises TypeError exception on failure (MRI: rb_convert_type).
*
* @param obj the object to convert
* @param targetType is the type we are trying to convert to
* @param target is the type we are trying to convert to
* @param convertMethod is the method to be called to try and convert to targeType
* @return the converted value
*/
@@ -128,10 +123,10 @@ public static final IRubyObject convertToType(IRubyObject obj, RubyClass target,
}

/**
* Converts this object to type 'targetType' using 'convertMethod' method and raises TypeError exception on failure (MRI: rb_convert_type in 1.9).
* Converts this object to type 'target' using 'convertMethod' method and raises TypeError exception on failure (MRI: rb_convert_type in 1.9).
*
* @param obj the object to convert
* @param targetType is the type we are trying to convert to
* @param target is the type we are trying to convert to
* @param convertMethod is the method to be called to try and convert to targeType
* @return the converted value
*/
@@ -195,7 +190,7 @@ public static String convertToIdentifier(IRubyObject obj) {
* additional TypeError during conversion (MRI: rb_check_convert_type).
*
* @param obj the object to convert
* @param targetType is the type we are trying to convert to
* @param target is the type we are trying to convert to
* @param convertMethodIndex the fast index to use for calling the method
* @param convertMethod is the method to be called to try and convert to targeType
* @return the converted value
@@ -214,8 +209,7 @@ public static final IRubyObject convertToTypeWithCheck(IRubyObject obj, RubyClas
* additional TypeError during conversion (MRI: rb_check_convert_type).
*
* @param obj the object to convert
* @param targetType is the type we are trying to convert to
* @param convertMethodIndex the fast index to use for calling the method
* @param target is the type we are trying to convert to
* @param convertMethod is the method to be called to try and convert to targeType
* @return the converted value
*/
@@ -232,16 +226,18 @@ public static final IRubyObject convertToTypeWithCheck(IRubyObject obj, RubyClas
* additional TypeError during conversion (MRI: rb_check_convert_type).
*
* @param obj the object to convert
* @param targetType is the type we are trying to convert to
* @param convertMethodIndex the fast index to use for calling the method
* @param target is the type we are trying to convert to
* @param convertMethod is the method to be called to try and convert to targeType
* @return the converted value
*/
public static final IRubyObject convertToTypeWithCheck19(IRubyObject obj, RubyClass target, String convertMethod) {
if (target.isInstance(obj)) return obj;
IRubyObject val = TypeConverter.convertToType19(obj, target, convertMethod, false);
if (val.isNil()) return val;
if (!target.isInstance(val)) throw obj.getRuntime().newTypeError(obj.getMetaClass() + "#" + convertMethod + " should return " + target.getName());
if (!target.isInstance(val)) {
String cname = obj.getMetaClass().getName();
throw obj.getRuntime().newTypeError("can't convert " + cname + " to " + target.getName() + " (" + cname + "#" + convertMethod + " gives " + val.getMetaClass().getName() + ")");
}
return val;
}

@@ -250,7 +246,7 @@ public static final IRubyObject convertToTypeWithCheck19(IRubyObject obj, RubyCl
* additional TypeError during conversion (MRI: rb_check_convert_type).
*
* @param obj the object to convert
* @param targetType is the type we are trying to convert to
* @param target is the type we are trying to convert to
* @param convertMethod is the method to be called to try and convert to targeType
* @return the converted value
*/
20 changes: 19 additions & 1 deletion spec/regression/GH-1962_Kernel_Array_coercion_spec.rb
Original file line number Diff line number Diff line change
@@ -1,12 +1,30 @@
if RUBY_VERSION >= "1.9"
describe "GH-1962: Kernel::Array" do
it "coerces Array-like objects that only define method_missing" do
it "coerces Array-like objects that define method_missing" do
o = Object.new
def o.method_missing(name, *args)
[]
end

expect(Array(o)).to eq([])
end

it "coerces Array-like objects that define to_ary" do
o = Object.new
def o.to_ary
[]
end

expect(Array(o)).to eq([])
end

it "coerces Array-like objects that define to_a" do
o = Object.new
def o.to_a
[]
end

expect(Array(o)).to eq([])
end
end
end
20 changes: 19 additions & 1 deletion spec/regression/GH-1963_Array_product_coercion_spec.rb
Original file line number Diff line number Diff line change
@@ -1,12 +1,30 @@
if RUBY_VERSION >= "1.9"
describe "GH-1963: Array#product" do
it "coerces Array-like objects that only define method_missing" do
it "coerces Array-like objects that define method_missing" do
o = Object.new
def o.method_missing(name, *args)
[2]
end

expect([1].product(o)).to eq([[1,2]])
end

it "coerces Array-like objects that define to_ary" do
o = Object.new
def o.to_ary
[2]
end

expect([1].product(o)).to eq([[1,2]])
end

it "does not coerce Array-like objects that define to_a" do
o = Object.new
def o.to_a
[2]
end

expect {[1].product(o)}.to raise_exception(TypeError)
end
end
end