From e20294efe31f911567713b62ac70e161cc49255f Mon Sep 17 00:00:00 2001 From: Till Ehrengruber Date: Mon, 22 Jan 2024 10:21:46 +0100 Subject: [PATCH] bug[next]: Improve error message on invalid call to field operator and program (#1323) After #1275 most of the error message given to the user when calling a field operator or program with invalid arguments was only available in verbose mode. This PR shows this information again. ```python @field_operator def foo(x: IField): return x @field_operator def testee(a: IField, b: IField, c: IField) -> IField: return foo(1) ``` ``` gt4py.next.errors.exceptions.DSLError: Invalid argument types in call to `foo`. E Invalid call to function of type `FieldOperatorType(definition=FunctionType(pos_only_args=[], pos_or_kw_args={'x': FieldType(dims=[Dimension(value='IDim', kind=)], dtype=ScalarType(kind=, shape=None))}, kw_only_args={}, returns=FieldType(dims=[Dimension(value='IDim', kind=)], dtype=ScalarType(kind=, shape=None))))`: E - Expected argument `x` to be of type `Field[[IDim], int32]`, but got `int32`. E File ".../gt4py_functional/tests/next_tests/integration_tests/feature_tests/ffront_tests/test_arg_call_interface.py", line 113 E return foo(1) ``` --- src/gt4py/next/ffront/decorator.py | 4 +++- src/gt4py/next/ffront/foast_passes/type_deduction.py | 2 +- src/gt4py/next/ffront/past_passes/type_deduction.py | 2 +- .../feature_tests/ffront_tests/test_program.py | 3 ++- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/gt4py/next/ffront/decorator.py b/src/gt4py/next/ffront/decorator.py index 05cbe1c882..9f8537f59b 100644 --- a/src/gt4py/next/ffront/decorator.py +++ b/src/gt4py/next/ffront/decorator.py @@ -344,7 +344,9 @@ def _validate_args(self, *args, **kwargs) -> None: raise_exception=True, ) except ValueError as err: - raise TypeError(f"Invalid argument types in call to '{self.past_node.id}'.") from err + raise errors.DSLError( + None, f"Invalid argument types in call to '{self.past_node.id}'.\n{err}" + ) from err def _process_args(self, args: tuple, kwargs: dict) -> tuple[tuple, tuple, dict[str, Any]]: self._validate_args(*args, **kwargs) diff --git a/src/gt4py/next/ffront/foast_passes/type_deduction.py b/src/gt4py/next/ffront/foast_passes/type_deduction.py index 639e5ff009..5e289af664 100644 --- a/src/gt4py/next/ffront/foast_passes/type_deduction.py +++ b/src/gt4py/next/ffront/foast_passes/type_deduction.py @@ -694,7 +694,7 @@ def visit_Call(self, node: foast.Call, **kwargs) -> foast.Call: ) except ValueError as err: raise errors.DSLError( - node.location, f"Invalid argument types in call to '{new_func}'." + node.location, f"Invalid argument types in call to '{new_func}'.\n{err}" ) from err return_type = type_info.return_type(func_type, with_args=arg_types, with_kwargs=kwarg_types) diff --git a/src/gt4py/next/ffront/past_passes/type_deduction.py b/src/gt4py/next/ffront/past_passes/type_deduction.py index fc353d64e4..af8f5e8368 100644 --- a/src/gt4py/next/ffront/past_passes/type_deduction.py +++ b/src/gt4py/next/ffront/past_passes/type_deduction.py @@ -229,7 +229,7 @@ def visit_Call(self, node: past.Call, **kwargs): ) except ValueError as ex: - raise errors.DSLError(node.location, f"Invalid call to '{node.func.id}'.") from ex + raise errors.DSLError(node.location, f"Invalid call to '{node.func.id}'.\n{ex}") from ex return past.Call( func=new_func, diff --git a/tests/next_tests/integration_tests/feature_tests/ffront_tests/test_program.py b/tests/next_tests/integration_tests/feature_tests/ffront_tests/test_program.py index c86881ab7c..938c69fb52 100644 --- a/tests/next_tests/integration_tests/feature_tests/ffront_tests/test_program.py +++ b/tests/next_tests/integration_tests/feature_tests/ffront_tests/test_program.py @@ -20,6 +20,7 @@ import pytest import gt4py.next as gtx +from gt4py.next import errors from next_tests.integration_tests import cases from next_tests.integration_tests.cases import IDim, Ioff, JDim, cartesian_case, fieldview_backend @@ -222,7 +223,7 @@ def test_wrong_argument_type(cartesian_case, copy_program_def): inp = cartesian_case.as_field([JDim], np.ones((cartesian_case.default_sizes[JDim],))) out = cases.allocate(cartesian_case, copy_program, "out").strategy(cases.ConstInitializer(1))() - with pytest.raises(TypeError) as exc_info: + with pytest.raises(errors.DSLError) as exc_info: # program is defined on Field[[IDim], ...], but we call with # Field[[JDim], ...] copy_program(inp, out, offset_provider={})