Repository: GridTools/gt4py
Pull request #1323 (2023-08-16 09:04:04)

bug[next]: Improve error message on invalid call to field operator and program
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=<DimensionKind.HORIZONTAL: 'horizontal'>)], dtype=ScalarType(kind=<ScalarKind.INT32: 32>, shape=None))}, kw_only_args={}, returns=FieldType(dims=[Dimension(value='IDim', kind=<DimensionKind.HORIZONTAL: 'horizontal'>)], dtype=ScalarType(kind=<ScalarKind.INT32: 32>, 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)
```


Patch:
diff --git a/src/gt4py/next/ffront/decorator.py b/src/gt4py/next/ffront/decorator.py
index 53159008..71192037 100644
--- a/src/gt4py/next/ffront/decorator.py
+++ b/src/gt4py/next/ffront/decorator.py
@@ -32,7 +32,7 @@ from devtools import debug
 from gt4py._core import definitions as core_defs
 from gt4py.eve import utils as eve_utils
 from gt4py.eve.extended_typing import Any, Optional
-from gt4py.next import allocators as next_allocators, embedded as next_embedded
+from gt4py.next import allocators as next_allocators, embedded as next_embedded, errors
 from gt4py.next.common import Dimension, DimensionKind, GridType
 from gt4py.next.embedded import operators as embedded_operators
 from gt4py.next.ffront import (
@@ -344,7 +344,9 @@ class Program:
                 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 639e5ff0..5e289af6 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 @@ class FieldOperatorTypeDeduction(traits.VisitorWithSymbolTableTrait, NodeTransla
             )
         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 fc353d64..af8f5e83 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 @@ class ProgramTypeDeduction(traits.VisitorWithSymbolTableTrait, NodeTranslator):
                 )
 
         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,


Test patch:
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 c86881ab..938c69fb 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 numpy as np
 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={})