|
35 | 35 | import com.oracle.graal.python.builtins.objects.type.PythonAbstractClass;
|
36 | 36 | import com.oracle.graal.python.nodes.PGuards;
|
37 | 37 | import com.oracle.graal.python.nodes.PRaiseNode;
|
| 38 | +import com.oracle.graal.python.nodes.call.CallNode; |
38 | 39 | import com.oracle.graal.python.nodes.expression.ExpressionNode;
|
39 | 40 | import com.oracle.graal.python.nodes.util.ExceptionStateNodes.GetCaughtExceptionNode;
|
40 | 41 | import com.oracle.graal.python.runtime.exception.PException;
|
41 |
| -import com.oracle.graal.python.runtime.object.PythonObjectFactory; |
42 | 42 | import com.oracle.truffle.api.dsl.Cached;
|
43 | 43 | import com.oracle.truffle.api.dsl.ImportStatic;
|
44 | 44 | import com.oracle.truffle.api.dsl.NodeChild;
|
@@ -66,16 +66,25 @@ void setCause(@SuppressWarnings("unused") VirtualFrame frame, PBaseException exc
|
66 | 66 | // raise * from <class>
|
67 | 67 | @Specialization
|
68 | 68 | void setCause(@SuppressWarnings("unused") VirtualFrame frame, PBaseException exception, LazyPythonClass causeClass,
|
69 |
| - @Cached PythonObjectFactory factory, |
70 | 69 | @Cached BranchProfile baseCheckFailedProfile,
|
71 | 70 | @Cached ValidExceptionNode validException,
|
| 71 | + @Cached CallNode callConstructor, |
72 | 72 | @Cached PRaiseNode raise) {
|
73 | 73 | if (!validException.execute(frame, causeClass)) {
|
74 | 74 | baseCheckFailedProfile.enter();
|
75 | 75 | throw raise.raise(PythonBuiltinClassType.TypeError, "exception causes must derive from BaseException");
|
76 | 76 | }
|
77 |
| - PBaseException cause = factory.createBaseException(causeClass); |
78 |
| - exception.setCause(cause); |
| 77 | + Object cause = callConstructor.execute(causeClass); |
| 78 | + if (cause instanceof PBaseException) { |
| 79 | + exception.setCause((PBaseException) cause); |
| 80 | + } else { |
| 81 | + // msimacek: CPython currently (3.8.2) has a bug that it's not checking the type of |
| 82 | + // the value returned by the constructor, you can set a non-exception as a cause |
| 83 | + // this way and see the exception printer TypeError on it. I don't want to raise an |
| 84 | + // exception because CPython doesn't do it and I don't want to change the cause type |
| 85 | + // to Object either, because it's not meant to be that way. |
| 86 | + exception.setCause(null); |
| 87 | + } |
79 | 88 | }
|
80 | 89 |
|
81 | 90 | // raise * from None
|
@@ -146,22 +155,34 @@ private void checkBaseClass(VirtualFrame frame, PythonAbstractClass pythonClass,
|
146 | 155 | @Specialization(guards = "isNoValue(cause)")
|
147 | 156 | void doRaise(@SuppressWarnings("unused") VirtualFrame frame, PythonAbstractClass pythonClass, @SuppressWarnings("unused") PNone cause,
|
148 | 157 | @Cached ValidExceptionNode validException,
|
| 158 | + @Cached CallNode callConstructor, |
| 159 | + @Cached BranchProfile constructorTypeErrorProfile, |
149 | 160 | @Cached PRaiseNode raise) {
|
150 | 161 | checkBaseClass(frame, pythonClass, validException, raise);
|
151 |
| - throw raise.raise(pythonClass); |
| 162 | + Object newException = callConstructor.execute(frame, pythonClass); |
| 163 | + if (newException instanceof PBaseException) { |
| 164 | + throw raise.raise((PBaseException) newException); |
| 165 | + } else { |
| 166 | + constructorTypeErrorProfile.enter(); |
| 167 | + throw raise.raise(TypeError, "calling %s should have returned an instance of BaseException, not %p", pythonClass, newException); |
| 168 | + } |
152 | 169 | }
|
153 | 170 |
|
154 | 171 | // raise <class> from *
|
155 | 172 | @Specialization(guards = "!isNoValue(cause)")
|
156 | 173 | void doRaise(@SuppressWarnings("unused") VirtualFrame frame, PythonAbstractClass pythonClass, Object cause,
|
157 |
| - @Cached PythonObjectFactory factory, |
158 | 174 | @Cached ValidExceptionNode validException,
|
159 | 175 | @Cached PRaiseNode raise,
|
| 176 | + @Cached CallNode callConstructor, |
160 | 177 | @Cached SetExceptionCauseNode setExceptionCauseNode) {
|
161 | 178 | checkBaseClass(frame, pythonClass, validException, raise);
|
162 |
| - PBaseException pythonException = factory.createBaseException(pythonClass); |
163 |
| - setExceptionCauseNode.execute(frame, pythonException, cause); |
164 |
| - throw raise.raise(pythonException); |
| 179 | + Object newException = callConstructor.execute(frame, pythonClass); |
| 180 | + if (newException instanceof PBaseException) { |
| 181 | + setExceptionCauseNode.execute(frame, (PBaseException) newException, cause); |
| 182 | + throw raise.raise((PBaseException) newException); |
| 183 | + } else { |
| 184 | + throw raise.raise(TypeError, "calling %s should have returned an instance of BaseException, not %p", pythonClass, newException); |
| 185 | + } |
165 | 186 | }
|
166 | 187 |
|
167 | 188 | // raise <invalid> [from *]
|
|
0 commit comments