Skip to content

Commit

Permalink
Merge pull request #8168 from enebo/type_error
Browse files Browse the repository at this point in the history
First stab at Err#typeError in api
  • Loading branch information
enebo committed Apr 25, 2024
2 parents 92b0a3c + 4e44945 commit 4cdf181
Show file tree
Hide file tree
Showing 121 changed files with 1,615 additions and 1,743 deletions.
20 changes: 13 additions & 7 deletions core/src/main/java/org/jruby/BasicObjectStub.java
Expand Up @@ -40,6 +40,7 @@
import org.jruby.runtime.builtin.RubyJavaObject;
import org.jruby.runtime.builtin.Variable;

import static org.jruby.api.Error.typeError;
import static org.jruby.runtime.invokedynamic.MethodNames.INSPECT;
import static org.jruby.runtime.Helpers.invokedynamic;
import static org.jruby.util.RubyStringBuilder.str;
Expand Down Expand Up @@ -149,9 +150,8 @@ public static Class getJavaClass(IRubyObject self) {

public static String asJavaString(IRubyObject self) {
IRubyObject asString = checkStringType(self);
if(!asString.isNil()) return asString.asJavaString();
Ruby runtime = getRuntime(self);
throw runtime.newTypeError(str(runtime, "", inspect(self), " is not a string"));
if(asString.isNil()) throw typeError(getRuntime(self).getCurrentContext(), "", inspect(self), " is not a string");
return asString.asJavaString();
}

public static RubyString asString(IRubyObject self) {
Expand Down Expand Up @@ -182,8 +182,11 @@ public static RubyInteger convertToInteger(IRubyObject self, int convertMethodIn
}

public static RubyInteger convertToInteger(IRubyObject self, String convertMethod) {
IRubyObject val = TypeConverter.convertToType(self, getRuntime(self).getInteger(), convertMethod, true);
if (!(val instanceof RubyInteger)) throw getRuntime(self).newTypeError(getMetaClass(self).getName() + '#' + convertMethod + " should return Integer");
Ruby runtime = getRuntime(self);
IRubyObject val = TypeConverter.convertToType(self, runtime.getInteger(), convertMethod, true);
if (!(val instanceof RubyInteger)) {
throw typeError(runtime.getCurrentContext(), "", self, '#' + convertMethod + " should return Integer");
}
return (RubyInteger) val;
}

Expand Down Expand Up @@ -212,8 +215,11 @@ public static IRubyObject checkArrayType(IRubyObject self) {
}

public static Object toJava(IRubyObject self, Class cls) {
if (cls.isAssignableFrom(self.getClass())) return self;
throw getRuntime(self).newTypeError("could not convert " + self.getClass() + " to " + cls);
if (!cls.isAssignableFrom(self.getClass())) {
throw typeError(self.getRuntime().getCurrentContext(), "could not convert ", self, " to " + cls);
}

return self;
}

public static IRubyObject dup(IRubyObject self) {
Expand Down
6 changes: 4 additions & 2 deletions core/src/main/java/org/jruby/MetaClass.java
Expand Up @@ -36,6 +36,8 @@
import org.jruby.util.log.Logger;
import org.jruby.util.log.LoggerFactory;

import static org.jruby.api.Error.typeError;

public final class MetaClass extends RubyClass {

@Deprecated
Expand Down Expand Up @@ -70,8 +72,8 @@ private static void logSingleton(Ruby runtime, RubyClass superClass, RubyBasicOb
}

@Override
public final IRubyObject allocate(){
throw runtime.newTypeError("can't create instance of virtual class");
public final IRubyObject allocate() {
throw typeError(getRuntime().getCurrentContext(), "can't create instance of virtual class");
}

@Override
Expand Down
17 changes: 12 additions & 5 deletions core/src/main/java/org/jruby/Ruby.java
Expand Up @@ -208,6 +208,7 @@
import static java.lang.invoke.MethodType.methodType;
import static org.jruby.RubyBoolean.FALSE_BYTES;
import static org.jruby.RubyBoolean.TRUE_BYTES;
import static org.jruby.api.Error.*;
import static org.jruby.internal.runtime.GlobalVariable.Scope.GLOBAL;
import static org.jruby.parser.ParserType.*;
import static org.jruby.util.RubyStringBuilder.str;
Expand Down Expand Up @@ -1454,7 +1455,7 @@ public RubyClass defineClassUnder(String id, RubyClass superClass, ObjectAllocat
IRubyObject classObj = parent.getConstantAt(id);

if (classObj != null) {
if (!(classObj instanceof RubyClass)) throw newTypeError(str(this, ids(this, id), " is not a class"));
if (!(classObj instanceof RubyClass)) throw typeError(getCurrentContext(), str(this, ids(this, id), " is not a class"));
RubyClass klazz = (RubyClass)classObj;
if (klazz.getSuperClass().getRealClass() != superClass) {
throw newNameError(str(this, ids(this, id), " is already defined"), newSymbol(id));
Expand Down Expand Up @@ -1513,7 +1514,7 @@ public RubyModule defineModuleUnder(String name, RubyModule parent) {
RubyString typeName = parentIsObject ?
types(this, moduleObj.getMetaClass()) : types(this, parent, moduleObj.getMetaClass());

throw newTypeError(str(this, typeName, " is not a module"));
throw typeError(getCurrentContext(), str(this, typeName, " is not a module"));
}

return RubyModule.newModule(this, name, parent, !parentIsObject);
Expand All @@ -1531,7 +1532,7 @@ public RubyModule getOrCreateModule(String id) {
if (module == null) {
module = defineModule(id);
} else if (!module.isModule()) {
throw newTypeError(str(this, ids(this, id), " is not a Module"));
throw typeError(getCurrentContext(), str(this, ids(this, id), " is not a Module"));
}

return (RubyModule) module;
Expand Down Expand Up @@ -3899,6 +3900,7 @@ public RaiseException newErrnoEADDRFromBindException(BindException be, String co
}
}

@Deprecated
public RaiseException newTypeError(String message) {
return newRaiseException(getTypeError(), message);
}
Expand Down Expand Up @@ -4200,14 +4202,19 @@ public RaiseException newIOErrorFromException(final IOException ex) {
return Helpers.newIOErrorFromException(this, ex);
}

@Deprecated
public RaiseException newTypeError(IRubyObject receivedObject, RubyClass expectedType) {
return newTypeError(receivedObject, expectedType.getName());
ThreadContext context = getCurrentContext();
return createTypeError(context, createTypeErrorMessage(context, receivedObject, expectedType));
}

@Deprecated
public RaiseException newTypeError(IRubyObject receivedObject, RubyModule expectedType) {
return newTypeError(receivedObject, expectedType.getName());
ThreadContext context = getCurrentContext();
return createTypeError(context, createTypeErrorMessage(context, receivedObject, expectedType));
}

@Deprecated
public RaiseException newTypeError(IRubyObject receivedObject, String expectedType) {
return newRaiseException(getTypeError(),
str(this, "wrong argument type ",
Expand Down
17 changes: 9 additions & 8 deletions core/src/main/java/org/jruby/RubyArray.java
Expand Up @@ -56,6 +56,7 @@
import org.jcodings.specific.USASCIIEncoding;
import org.jruby.anno.JRubyClass;
import org.jruby.anno.JRubyMethod;
import org.jruby.api.Error;
import org.jruby.ast.util.ArgsUtil;
import org.jruby.common.IRubyWarnings.ID;
import org.jruby.exceptions.RaiseException;
Expand Down Expand Up @@ -93,6 +94,8 @@
import static org.jruby.RubyEnumerator.enumeratorizeWithSize;
import static org.jruby.RubyEnumerator.enumWithSize;
import static org.jruby.RubyNumeric.checkInt;
import static org.jruby.api.Error.typeError;
import static org.jruby.api.Error.typeError;
import static org.jruby.runtime.Helpers.addBufferLength;
import static org.jruby.runtime.Helpers.arrayOf;
import static org.jruby.runtime.Helpers.calculateBufferLength;
Expand Down Expand Up @@ -588,7 +591,7 @@ private RubyArray makeSharedFirst(ThreadContext context, IRubyObject num, boolea
protected final void modifyCheck() {
if ((flags & TMPLOCK_OR_FROZEN_ARR_F) != 0) {
if ((flags & FROZEN_F) != 0) throw getRuntime().newFrozenError(this);
if ((flags & TMPLOCK_ARR_F) != 0) throw getRuntime().newTypeError("can't modify array during iteration");
if ((flags & TMPLOCK_ARR_F) != 0) throw typeError(getRuntime().getCurrentContext(), "can't modify array during iteration");
}
}

Expand Down Expand Up @@ -2182,9 +2185,7 @@ public IRubyObject to_h(ThreadContext context, Block block) {
IRubyObject elt = block.isGiven() ? block.yield(context, e) : e;
IRubyObject key_value_pair = elt.checkArrayType();

if (key_value_pair == context.nil) {
throw runtime.newTypeError("wrong element type " + elt.getMetaClass().getRealClass() + " at " + i + " (expected array)");
}
if (key_value_pair == context.nil) throw typeError(context, "wrong element type ", elt, " at " + i + " (expected array)");

RubyArray ary = (RubyArray)key_value_pair;
if (ary.getLength() != 2) {
Expand Down Expand Up @@ -2545,7 +2546,7 @@ private int bsearch_index_internal(ThreadContext context, Block block) {
case -1: smaller = false;
}
} else {
throw runtime.newTypeError(str(runtime, "wrong argument type ", types(runtime, v.getType()), " (must be numeric, true, false or nil"));
throw typeError(context, "wrong argument type ", v, " (must be numeric, true, false or nil");
}
if (smaller) {
high = mid;
Expand Down Expand Up @@ -3079,7 +3080,7 @@ public IRubyObject zip(ThreadContext context, IRubyObject[] args, Block block) {
RubySymbol each = runtime.newSymbol("each");
for (int i = 0; i < args.length; i++) {
IRubyObject arg = args[i];
if (!arg.respondsTo("each")) throw runtime.newTypeError(arg, "must respond to :each");
if (!arg.respondsTo("each")) throw typeError(context, arg, "must respond to :each");
newArgs[i] = to_enum.call(context, arg, arg, each);
}
}
Expand Down Expand Up @@ -5111,7 +5112,7 @@ public IRubyObject sumCommon(final ThreadContext context, IRubyObject init, fina
} else if (result instanceof RubyRational) {
result = ((RubyRational) result).op_plus(context, value);
} else {
throw runtime.newTypeError("BUG: unexpected type in rational part of Array#sum");
throw typeError(context, "BUG: unexpected type in rational part of Array#sum");
}
} else if (value instanceof RubyFloat) {
result = RubyFloat.newFloat(runtime, ((RubyRational) result).getDoubleValue(context));
Expand Down Expand Up @@ -5334,7 +5335,7 @@ public RubyString pack(ThreadContext context, IRubyObject obj, IRubyObject maybe
buffer = ArgsUtil.extractKeywordArg(context, (RubyHash) opts, "buffer");
if (buffer == context.nil) buffer = null;
if (buffer != null && !(buffer instanceof RubyString)) {
throw runtime.newTypeError(str(runtime, "buffer must be String, not ", types(runtime, buffer.getType())));
throw typeError(context, "buffer must be String, not ", buffer, "");
}
}

Expand Down
48 changes: 19 additions & 29 deletions core/src/main/java/org/jruby/RubyBasicObject.java
Expand Up @@ -64,6 +64,8 @@
import org.jruby.runtime.Visibility;

import static org.jruby.anno.FrameField.*;
import static org.jruby.api.Convert.castToModule;
import static org.jruby.api.Error.typeError;
import static org.jruby.ir.runtime.IRRuntimeHelpers.dupIfKeywordRestAtCallsite;
import static org.jruby.runtime.Helpers.invokeChecked;
import static org.jruby.runtime.ThreadContext.*;
Expand Down Expand Up @@ -599,8 +601,8 @@ public Class<?> getJavaClass() {
@Override
public String asJavaString() {
IRubyObject str = checkStringType();
if (!str.isNil()) return ((RubyString) str).asJavaString();
throw getRuntime().newTypeError(str(getRuntime(), inspect(), " is not a string"));
if (str.isNil()) throw typeError(getRuntime().getCurrentContext(), this, "String");
return str.asJavaString();
}

/** rb_obj_as_string
Expand Down Expand Up @@ -669,9 +671,7 @@ public RubyInteger convertToInteger() {

IRubyObject result = TypeConverter.convertToType(context, this, runtime.getInteger(), sites.to_int_checked, true);

if (!(result instanceof RubyInteger)) {
throw runtime.newTypeError(str(runtime, types(runtime, getMetaClass()), "#to_int should return Integer"));
}
if (!(result instanceof RubyInteger)) throw typeError(context, "", this, "#to_int should return Integer");

return (RubyInteger) result;
}
Expand All @@ -696,7 +696,8 @@ public RubyInteger convertToInteger(String convertMethod) {
}

if (!(result instanceof RubyInteger)) {
throw runtime.newTypeError(str(runtime, types(runtime, getMetaClass()), "#", ids(runtime, convertMethod), " should return Integer"));
throw typeError(runtime.getCurrentContext(), str(runtime, types(runtime, getMetaClass()),
"#", ids(runtime, convertMethod), " should return Integer"));
}

return (RubyInteger) result;
Expand Down Expand Up @@ -801,11 +802,11 @@ else if (JavaUtil.isDuckTypeConvertable(getClass(), target)) {
return JavaUtil.convertProcToInterface(getRuntime().getCurrentContext(), this, target);
}
}
else if (target.isAssignableFrom(getClass())) {
return (T) this;
else if (!target.isAssignableFrom(getClass())) {
throw typeError(getRuntime().getCurrentContext(), "cannot convert instance of ", this, " to " + target);
}

throw getRuntime().newTypeError("cannot convert instance of " + getClass() + " to " + target);
return (T) this;
}

private Object unwrap_java_object() {
Expand Down Expand Up @@ -866,7 +867,7 @@ protected static void objInitCopy(IRubyObject obj, IRubyObject orig) {
// Not implemented
// checkTrusted();
if (obj.getClass() != orig.getClass() || obj.getMetaClass().getRealClass() != orig.getMetaClass().getRealClass()) {
throw obj.getRuntime().newTypeError("initialize_copy should take same class object");
throw typeError(obj.getRuntime().getCurrentContext(), "initialize_copy should take same class object");
}
}

Expand Down Expand Up @@ -2008,7 +2009,7 @@ public IRubyObject initialize_copy(IRubyObject original) {
checkFrozen();

if (getMetaClass().getRealClass() != original.getMetaClass().getRealClass()) {
throw getRuntime().newTypeError("initialize_copy should take same class object");
throw typeError(getRuntime().getCurrentContext(), "initialize_copy should take same class object");
}

return this;
Expand Down Expand Up @@ -2173,13 +2174,10 @@ public RubyBoolean frozen_p(ThreadContext context) {
* class. See also <code>Object#kind_of?</code>.
*/
public RubyBoolean instance_of_p(ThreadContext context, IRubyObject type) {
if (type() == type) {
return context.tru;
} else if (!(type instanceof RubyModule)) {
throw context.runtime.newTypeError("class or module required");
} else {
return context.fals;
}
if (type() == type) return context.tru;
if (!(type instanceof RubyModule)) throw typeError(context, "class or module required");

return context.fals;
}


Expand Down Expand Up @@ -2210,13 +2208,7 @@ public RubyBoolean instance_of_p(ThreadContext context, IRubyObject type) {
* b.kind_of? M #=&gt; true
*/
public RubyBoolean kind_of_p(ThreadContext context, IRubyObject type) {
// TODO: Generalize this type-checking code into IRubyObject helper.
if (!(type instanceof RubyModule)) {
// TODO: newTypeError does not offer enough for ruby error string...
throw context.runtime.newTypeError("class or module required");
}

return RubyBoolean.newBoolean(context, ((RubyModule) type).isInstance(this));
return RubyBoolean.newBoolean(context, castToModule(context, type, "class or module required").isInstance(this));
}

/** rb_obj_methods
Expand Down Expand Up @@ -2598,15 +2590,13 @@ public IRubyObject instance_exec(ThreadContext context, IRubyObject[] args, Bloc
* k.hello #=&gt; "Hello from Mod.\n"
*/
public IRubyObject extend(IRubyObject[] args) {
Ruby runtime = metaClass.runtime;
var context = getRuntime().getCurrentContext();

// Make sure all arguments are modules before calling the callbacks
for (int i = 0; i < args.length; i++) {
if (!args[i].isModule()) throw runtime.newTypeError(args[i], runtime.getModule());
if (!args[i].isModule()) throw typeError(context, args[i], "Module");
}

ThreadContext context = runtime.getCurrentContext();

// MRI extends in order from last to first
for (int i = args.length - 1; i >= 0; i--) {
args[i].callMethod(context, "extend_object", this);
Expand Down
3 changes: 2 additions & 1 deletion core/src/main/java/org/jruby/RubyBignum.java
Expand Up @@ -51,6 +51,7 @@
import org.jruby.runtime.marshal.UnmarshalStream;

import static org.jruby.RubyFixnum.zero;
import static org.jruby.api.Error.typeError;

/**
*
Expand Down Expand Up @@ -150,7 +151,7 @@ public BigInteger getBigIntegerValue() {

@Override
public RubyClass getSingletonClass() {
throw getRuntime().newTypeError("can't define singleton");
throw typeError(getRuntime().getCurrentContext(), "can't define singleton");
}

/** Getter for property value.
Expand Down

0 comments on commit 4cdf181

Please sign in to comment.