Repository: stfc/PSyclone (python)

Issue:
symbol.resolve_type fails for transitive imports
```
    ~~~~~~~~~~~~~^^^^^^^^^^^^^^^
  File "/home/centos/workspace/psyclone/PSyclone/src/psyclone/transformations.py", line 597, in validate
    self.validate_it_can_run_on_gpu(node, options)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^
  File "/home/centos/workspace/psyclone/PSyclone/src/psyclone/transformations.py", line 459, in validate_it_can_run_on_gpu
    symbol.resolve_type()
    ~~~~~~~~~~~~~~~~~~~^^
  File "/home/centos/workspace/psyclone/PSyclone/src/psyclone/psyir/symbols/symbol.py", line 263, in resolve_type
    if extern_symbol.initial_value:
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'Symbol' object has no attribute 'initial_value'
```

Pull request description:
(closes #2952) Gracefully fail resolving transitive type

Patch:
diff --git a/src/psyclone/psyir/symbols/symbol.py b/src/psyclone/psyir/symbols/symbol.py
index 0638c4623..3b8c1cceb 100644
--- a/src/psyclone/psyir/symbols/symbol.py
+++ b/src/psyclone/psyir/symbols/symbol.py
@@ -248,10 +248,17 @@ class Symbol(CommentableMixin):
                   examining the Container from which it is imported.
         :rtype: subclass of :py:class:`psyclone.psyir.symbols.Symbol`
 
+        :raises SymbolError: if the type could not be resolved.
         '''
         if self.is_import:
             extern_symbol = self.get_external_symbol()
-            from psyclone.psyir.symbols import RoutineSymbol
+            # pylint: disable-next=import-outside-toplevel
+            from psyclone.psyir.symbols import RoutineSymbol, TypedSymbol
+            if not isinstance(extern_symbol, TypedSymbol):
+                raise SymbolError(
+                    f"The external symbol '{extern_symbol.name}' was found "
+                    f"but it does not have a type. Maybe it is a transitive "
+                    f"(indirect) import which is currently not resolvable.")
             if isinstance(extern_symbol, RoutineSymbol):
                 # Specialise the existing Symbol in-place so that all
                 # References to it remain valid.


Test patch:
diff --git a/src/psyclone/tests/psyir/symbols/symbol_test.py b/src/psyclone/tests/psyir/symbols/symbol_test.py
index 3040e2535..928a53da6 100644
--- a/src/psyclone/tests/psyir/symbols/symbol_test.py
+++ b/src/psyclone/tests/psyir/symbols/symbol_test.py
@@ -392,6 +392,18 @@ def test_symbol_resolve_type(monkeypatch):
     assert new_sym.datatype == INTEGER_SINGLE_TYPE
     assert new_sym.visibility == Symbol.Visibility.PRIVATE
     assert new_sym.is_import
+    # Repeat the test but get_external_symbol() just returns
+    # a new bare Symbol (e.g. because it is a transitive import)
+    bsym = Symbol("b", visibility=Symbol.Visibility.PRIVATE,
+                  interface=ImportInterface(other_container))
+    monkeypatch.setattr(bsym, "get_external_symbol",
+                        lambda: Symbol("b"))
+    with pytest.raises(SymbolError) as err:
+        new_sym = bsym.resolve_type()
+    assert ("The external symbol 'b' was found but it does not have a "
+            "type. Maybe it is a transitive (indirect) import which is "
+            "currently not resolvable." in str(err.value))
+
     # Repeat but test when the imported Symbol is a parameter.
     csym = Symbol("c", visibility=Symbol.Visibility.PRIVATE,
                   interface=ImportInterface(other_container))