Skip to content

Commit 06081a7

Browse files
committed
Convert UnknownKeyException to KeyError, similar to Hash#fetch(missing_key)
* So we can know if the operation succeeded or not, and we map interop semantics more closely.
1 parent a8bb871 commit 06081a7

File tree

3 files changed

+34
-22
lines changed

3 files changed

+34
-22
lines changed

src/main/java/org/truffleruby/core/exception/CoreExceptions.java

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import java.util.EnumSet;
1616

1717
import com.oracle.truffle.api.interop.InvalidBufferOffsetException;
18+
import com.oracle.truffle.api.interop.UnknownKeyException;
1819
import org.jcodings.Encoding;
1920
import org.jcodings.specific.UTF8Encoding;
2021
import org.truffleruby.RubyContext;
@@ -404,11 +405,6 @@ public RubyException mathDomainError(String method, Node currentNode) {
404405

405406
// IndexError
406407

407-
@TruffleBoundary
408-
public RubyException indexErrorOutOfString(int index, Node currentNode) {
409-
return indexError(StringUtils.format("index %d out of string", index), currentNode);
410-
}
411-
412408
@TruffleBoundary
413409
public RubyException indexError(String message, Node currentNode) {
414410
RubyClass exceptionClass = context.getCoreLibrary().indexErrorClass;
@@ -417,6 +413,11 @@ public RubyException indexError(String message, Node currentNode) {
417413
return ExceptionOperations.createRubyException(context, exceptionClass, errorMessage, currentNode, null);
418414
}
419415

416+
@TruffleBoundary
417+
public RubyException indexErrorOutOfString(int index, Node currentNode) {
418+
return indexError(StringUtils.format("index %d out of string", index), currentNode);
419+
}
420+
420421
@TruffleBoundary
421422
public RubyException indexTooSmallError(String type, int index, int length, Node currentNode) {
422423
return indexError(
@@ -445,6 +446,21 @@ public RubyException indexErrorInvalidBufferOffsetException(InvalidBufferOffsetE
445446
return indexError("invalid buffer offset " + exception.getByteOffset(), currentNode);
446447
}
447448

449+
// KeyError
450+
451+
@TruffleBoundary
452+
public RubyException keyError(String message, Node currentNode) {
453+
RubyClass exceptionClass = context.getCoreLibrary().keyErrorClass;
454+
RubyString errorMessage = StringOperations
455+
.createString(context, language, StringOperations.encodeRope(message, UTF8Encoding.INSTANCE));
456+
return ExceptionOperations.createRubyException(context, exceptionClass, errorMessage, currentNode, null);
457+
}
458+
459+
@TruffleBoundary
460+
public RubyException keyError(UnknownKeyException exception, Node currentNode) {
461+
return keyError(exception.getMessage(), currentNode);
462+
}
463+
448464
// StopIteration
449465

450466
@TruffleBoundary

src/main/java/org/truffleruby/interop/InteropNodes.java

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@
2121
import com.oracle.truffle.api.frame.VirtualFrame;
2222
import com.oracle.truffle.api.interop.ExceptionType;
2323
import com.oracle.truffle.api.interop.NodeLibrary;
24-
import com.oracle.truffle.api.interop.UnknownKeyException;
25-
import com.oracle.truffle.api.interop.UnsupportedTypeException;
2624
import org.jcodings.specific.UTF8Encoding;
2725
import org.truffleruby.RubyContext;
2826
import org.truffleruby.RubyLanguage;
@@ -2000,8 +1998,7 @@ protected Object getMetaQualifiedName(Object metaObject,
20001998
}
20011999
// endregion
20022000

2003-
// region Hash
2004-
2001+
// region Hash entries
20052002
@CoreMethod(names = "has_hash_entries?", onSingleton = true, required = 1)
20062003
public abstract static class HasHashEntriesNode extends InteropCoreMethodArrayArgumentsNode {
20072004
@Specialization(limit = "getCacheLimit()")
@@ -2132,10 +2129,8 @@ protected Object readHashValue(Object receiver, Object key,
21322129
@Cached TranslateInteropExceptionNode translateInteropException) {
21332130
try {
21342131
return interop.readHashValue(receiver, key);
2135-
} catch (UnsupportedMessageException e) {
2132+
} catch (InteropException e) {
21362133
throw translateInteropException.execute(e);
2137-
} catch (UnknownKeyException e) {
2138-
return nil;
21392134
}
21402135
}
21412136
}
@@ -2163,10 +2158,8 @@ protected Object removeHashEntry(Object receiver, Object key,
21632158
try {
21642159
interop.removeHashEntry(receiver, key);
21652160
return nil;
2166-
} catch (UnsupportedMessageException e) {
2161+
} catch (InteropException e) {
21672162
throw translateInteropException.execute(e);
2168-
} catch (UnknownKeyException e) {
2169-
return nil;
21702163
}
21712164
}
21722165
}
@@ -2179,17 +2172,12 @@ protected Object writeHashEntry(Object receiver, Object key, Object value,
21792172
@Cached TranslateInteropExceptionNode translateInteropException) {
21802173
try {
21812174
interop.writeHashEntry(receiver, key, value);
2182-
return nil;
2183-
} catch (UnsupportedMessageException e) {
2184-
throw translateInteropException.execute(e);
2185-
} catch (UnknownKeyException e) {
2186-
return nil;
2187-
} catch (UnsupportedTypeException e) {
2175+
return value;
2176+
} catch (InteropException e) {
21882177
throw translateInteropException.execute(e);
21892178
}
21902179
}
21912180
}
2192-
21932181
// endregion
21942182

21952183
// region Identity

src/main/java/org/truffleruby/interop/TranslateInteropExceptionNode.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
import com.oracle.truffle.api.interop.InvalidBufferOffsetException;
1313
import com.oracle.truffle.api.interop.StopIterationException;
14+
import com.oracle.truffle.api.interop.UnknownKeyException;
1415
import org.truffleruby.RubyContext;
1516
import org.truffleruby.RubyLanguage;
1617
import org.truffleruby.language.RubyBaseNode;
@@ -77,6 +78,13 @@ protected RuntimeException handle(
7778
exception);
7879
}
7980

81+
@Specialization
82+
protected RuntimeException handle(
83+
UnknownKeyException exception, boolean inInvokeMember, Object receiver, Object[] args,
84+
@CachedContext(RubyLanguage.class) RubyContext context) {
85+
return new RaiseException(context, context.getCoreExceptions().keyError(exception, this), exception);
86+
}
87+
8088
@Specialization
8189
protected RuntimeException handle(
8290
UnknownIdentifierException exception, boolean inInvokeMember, Object receiver, Object[] args,

0 commit comments

Comments
 (0)