diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/callable/InvokeConversionNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/callable/InvokeConversionNode.java index fcba1c6228ac..ba6a633674eb 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/callable/InvokeConversionNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/callable/InvokeConversionNode.java @@ -103,7 +103,12 @@ static boolean hasType(TypeOfNode typeOfNode, Object value) { return typeOfNode.execute(value) instanceof Type; } - @Specialization(guards = {"hasType(dispatch, that)"}) + static boolean isDataflowError(Object value) { + return value instanceof DataflowError; + } + + @Specialization( + guards = {"hasType(dispatch, that)", "!isDataflowError(self)", "!isDataflowError(that)"}) Object doConvertFrom( VirtualFrame frame, State state, @@ -123,8 +128,9 @@ Object doConvertFrom( } } + /** If {@code that} is a dataflow error, we try to find a conversion for it. */ @Specialization - Object doDataflowError( + Object doConvertDataflowError( VirtualFrame frame, State state, UnresolvedConversion conversion, @@ -143,6 +149,18 @@ Object doDataflowError( } } + /** If {@code self} is a dataflow error, we just propagate it. */ + @Specialization + Object doDataflowErrorSentinel( + VirtualFrame frame, + State state, + UnresolvedConversion conversion, + DataflowError self, + Object that, + Object[] arguments) { + return self; + } + @Specialization Object doPanicSentinel( VirtualFrame frame, diff --git a/test/Base_Tests/src/Semantic/Conversion_Spec.enso b/test/Base_Tests/src/Semantic/Conversion_Spec.enso index 421a4152343d..43e9f5345d8e 100644 --- a/test/Base_Tests/src/Semantic/Conversion_Spec.enso +++ b/test/Base_Tests/src/Semantic/Conversion_Spec.enso @@ -135,6 +135,15 @@ add_specs suite_builder = group_builder.specify "should call extension conversions" <| Text.from Methods.get_bar . should_equal "bar" + group_builder.specify "should propagate dataflow errors on builtin type" <| + Float.from 42 . is_error . should_be_false + Float.from (Error.throw "ERR") . is_error . should_be_true + (Error.throw "ERR") . to Float . is_error . should_be_true + + group_builder.specify "should propagate dataflow errors on custom type" <| + Bar.from (Error.throw "ERR") . is_error . should_be_true + (Error.throw "ERR") . to Bar . is_error . should_be_true + group_builder.specify "should fail graciously when there is no conversion" <| Panic.recover Any (Foo.from (Quux.Value 10)) . catch Any .to_display_text . should_equal "Could not find a conversion from `Quux.Value` to `Foo`." group_builder.specify "should fail graciously when the conversion target is invalid" <|