Skip to content

Commit 0e6eea3

Browse files
committed
Don't crash on dict unpacking of non-dicts
1 parent 0521623 commit 0e6eea3

File tree

2 files changed

+21
-3
lines changed

2 files changed

+21
-3
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/ErrorMessages.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,7 @@ public abstract class ErrorMessages {
469469
public static final String OBJ_HAS_NO_LEN = "object of type '%p' has no len()";
470470
public static final String OBJ_ISNT_CALLABLE = "'%p' object is not callable";
471471
public static final String OBJ_ISNT_ITERATOR = "'%p' object is not an iterator";
472+
public static final String OBJ_ISNT_MAPPING = "'%p' object is not a mapping";
472473
public static final String OBJ_ISNT_REVERSIBLE = "'%p' object is not reversible";
473474
public static final String OBJ_NOT_ITERABLE = "'%p' object is not iterable";
474475
public static final String OBJ_NOT_SUBSCRIPTABLE = "'%p' object is not subscriptable";

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/generator/DictConcatNode.java

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,13 @@
4040
*/
4141
package com.oracle.graal.python.nodes.generator;
4242

43+
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.TypeError;
44+
4345
import com.oracle.graal.python.builtins.objects.common.HashingStorage;
4446
import com.oracle.graal.python.builtins.objects.common.HashingStorageLibrary;
4547
import com.oracle.graal.python.builtins.objects.dict.PDict;
48+
import com.oracle.graal.python.nodes.ErrorMessages;
49+
import com.oracle.graal.python.nodes.PRaiseNode;
4650
import com.oracle.graal.python.nodes.expression.ExpressionNode;
4751
import com.oracle.truffle.api.CompilerDirectives;
4852
import com.oracle.truffle.api.dsl.Cached;
@@ -56,6 +60,8 @@ public abstract class DictConcatNode extends ExpressionNode {
5660

5761
@Children final ExpressionNode[] mappables;
5862

63+
@Child private PRaiseNode raiseNode;
64+
5965
protected DictConcatNode(ExpressionNode... mappablesNodes) {
6066
this.mappables = mappablesNodes;
6167
}
@@ -66,6 +72,7 @@ public Object concat(VirtualFrame frame,
6672
@Cached ConditionProfile hasFrame,
6773
@CachedLibrary(limit = "2") HashingStorageLibrary firstlib,
6874
@CachedLibrary(limit = "1") HashingStorageLibrary otherlib) {
75+
// TODO support mappings in general
6976
PDict first = null;
7077
PDict other;
7178
for (ExpressionNode n : mappables) {
@@ -90,12 +97,22 @@ private static void addAllToDict(VirtualFrame frame, PDict dict, PDict other, Co
9097
dict.setDictStorage(dictStorage);
9198
}
9299

93-
private static PDict expectDict(Object first) {
100+
private PDict expectDict(Object first) {
94101
if (!(first instanceof PDict)) {
95-
CompilerDirectives.transferToInterpreter();
96-
throw new RuntimeException("non-dictionary in dictionary appending");
102+
throw getRaiseNode().raise(TypeError, ErrorMessages.OBJ_ISNT_MAPPING, first);
97103
}
98104
return (PDict) first;
99105
}
100106

107+
protected final PRaiseNode getRaiseNode() {
108+
if (raiseNode == null) {
109+
CompilerDirectives.transferToInterpreterAndInvalidate();
110+
if (isAdoptable()) {
111+
raiseNode = insert(PRaiseNode.create());
112+
} else {
113+
raiseNode = PRaiseNode.getUncached();
114+
}
115+
}
116+
return raiseNode;
117+
}
101118
}

0 commit comments

Comments
 (0)