Repository: pyccel/pyccel (python)

Issue:
[SETS] Support variable declarations in Fortran
### Describe the feature
Minimal printing support should be implemented for lists. It should be possible to declare a list using a type annotation.

### Test Code
Provide code which does not currently work but which should do when this issue is fixed:
```python
def declare_list():
    a : set[int]
```

### Proposed Solution
This feature should be implemented with the https://github.com/Goddard-Fortran-Ecosystem/gFTL library. The Set type should be used.

### Target Language
Fortran

### Pre-requisites
- #1656

Pull request:
Add Fortran support for set initialisation
Add Fortran support for set initialisation in a similar way to lists. Fixes #1658 

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0823179a..38536236 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -28,6 +28,8 @@ All notable changes to this project will be documented in this file.
 -   #1659 : Add the appropriate C language equivalent for declaring a Python `set` container using the STC library.
 -   #1944 : Add the appropriate C language equivalent for declaring a Python `dict` container using the STC library.
 -   #1657 : Add the appropriate Fortran language equivalent for declaring a Python `list` container using the gFTL library.
+-   #1658 : Add the appropriate Fortran language equivalent for declaring a Python `set` container using the gFTL library.
+-   #1944 : Add the appropriate Fortran language equivalent for declaring a Python `dict` container using the gFTL library.
 -   #1874 : Add C and Fortran support for the `len()` function for the `list` container.
 -   #1875 : Add C and Fortran support for the `len()` function for the `set` container.
 -   #1908 : Add C and Fortran support for the `len()` function for the `dict` container.
diff --git a/docs/builtin-functions.md b/docs/builtin-functions.md
index d15f0e6d..c22d25f6 100644
--- a/docs/builtin-functions.md
+++ b/docs/builtin-functions.md
@@ -92,6 +92,27 @@ Python contains a limited number of builtin functions defined [here](https://doc
 | `reverse` | No |
 | `sort` | Python-only |
 
+## Set methods
+
+| Method | Supported |
+|----------|-----------|
+| `add` | Python-only |
+| `clear` | Python-only |
+| `copy` | Python-only |
+| `difference` | No |
+| `difference_update` | No |
+| `discard` | Python-only |
+| `intersection` | No |
+| `intersection_update` | No |
+| `isdisjoint` | No |
+| `issubset` | No |
+| `issuperset` | No |
+| `pop` | Python-only |
+| `remove` | Python-only |
+| `symmetric_difference` | No |
+| `symmetric_difference_update` | No |
+| `union` | No |
+| `update` | Python-only |
 
 ## Dictionary methods
 
diff --git a/pyccel/ast/builtins.py b/pyccel/ast/builtins.py
index 9c3cead5..99f0d820 100644
--- a/pyccel/ast/builtins.py
+++ b/pyccel/ast/builtins.py
@@ -730,8 +730,10 @@ class PythonListFunction(PyccelFunction):
     __slots__ = ('_class_type', '_shape')
     _attribute_nodes = ()
 
-    def __new__(cls, arg):
-        if isinstance(arg, PythonList):
+    def __new__(cls, arg = None):
+        if arg is None:
+            return PythonList()
+        elif isinstance(arg, PythonList):
             return arg
         elif isinstance(arg.shape[0], LiteralInteger):
             return PythonList(*[arg[i] for i in range(arg.shape[0])])
@@ -774,6 +776,11 @@ class PythonSet(TypedAstNode):
         super().__init__()
         if pyccel_stage == 'syntactic':
             return
+        elif len(args) == 0:
+            self._shape = (LiteralInteger(0),)
+            self._class_type = HomogeneousSetType(GenericType())
+            return
+
         arg0 = args[0]
         is_homogeneous = arg0.class_type is not GenericType() and \
                          all(a.class_type is not GenericType() and \
@@ -829,8 +836,10 @@ class PythonSetFunction(PyccelFunction):
 
     __slots__ = ('_shape', '_class_type')
     name = 'set'
-    def __new__(cls, arg):
-        if isinstance(arg.class_type, HomogeneousSetType):
+    def __new__(cls, arg = None):
+        if arg is None:
+            return PythonSet()
+        elif isinstance(arg.class_type, HomogeneousSetType):
             return arg
         elif isinstance(arg, (PythonList, PythonSet, PythonTuple)):
             return PythonSet(*arg)
diff --git a/pyccel/codegen/pipeline.py b/pyccel/codegen/pipeline.py
index 2663da57..a7bc2319 100644
--- a/pyccel/codegen/pipeline.py
+++ b/pyccel/codegen/pipeline.py
@@ -335,13 +335,19 @@ def execute_pyccel(fname, *,
                               verbose  = verbose)
 
             mod_obj.add_dependencies(stdlib)
-
+            modules.append(stdlib)
 
     # Iterate over the external_libs list and determine if the printer
     # requires an external lib to be included.
     for key, import_node in codegen.get_printer_imports().items():
         try:
-            deps = generate_extension_modules(key, import_node, pyccel_dirpath, language)
+            deps = generate_extension_modules(key, import_node, pyccel_dirpath,
+                                              includes     = includes,
+                                              libs         = compile_libs,
+                                              libdirs      = libdirs,
+                                              dependencies = modules,
+                                              accelerators = accelerators,
+                                              language = language)
         except NotImplementedError as error:
             errors.report(f'{error}\n'+PYCCEL_RESTRICTION_TODO,
                 severity='error',
diff --git a/pyccel/codegen/printing/fcode.py b/pyccel/codegen/printing/fcode.py
index 4e8ad525..03c78221 100644
--- a/pyccel/codegen/printing/fcode.py
+++ b/pyccel/codegen/printing/fcode.py
@@ -24,7 +24,7 @@ from pyccel.ast.builtins import PythonInt, PythonType, PythonPrint, PythonRange
 from pyccel.ast.builtins import PythonTuple, DtypePrecisionToCastFunction
 from pyccel.ast.builtins import PythonBool, PythonList, PythonSet
 
-from pyccel.ast.core import FunctionDef
+from pyccel.ast.core import FunctionDef, FunctionDefArgument, FunctionDefResult
 from pyccel.ast.core import SeparatorComment, Comment
 from pyccel.ast.core import ConstructorCall
 from pyccel.ast.core import FunctionCallArgument
@@ -37,7 +37,7 @@ from pyccel.ast.core import FunctionCall, PyccelFunctionDef
 from pyccel.ast.datatypes import PrimitiveBooleanType, PrimitiveIntegerType, PrimitiveFloatingPointType, PrimitiveComplexType
 from pyccel.ast.datatypes import SymbolicType, StringType, FixedSizeNumericType, HomogeneousContainerType
 from pyccel.ast.datatypes import HomogeneousTupleType, HomogeneousListType, HomogeneousSetType, DictType
-from pyccel.ast.datatypes import PythonNativeInt
+from pyccel.ast.datatypes import PythonNativeInt, PythonNativeBool
 from pyccel.ast.datatypes import CustomDataType, InhomogeneousTupleType, TupleType
 from pyccel.ast.datatypes import pyccel_type_to_original_type, PyccelType
 
@@ -550,22 +550,46 @@ class FCodePrinter(CodePrinter):
                 include = Import(LiteralString('vector/template.inc'), Module('_', (), ()))
                 element_type = expr_type.element_type
                 if isinstance(element_type, FixedSizeNumericType):
-                    macros = [MacroDefinition('T', element_type.primitive_type),
+                    imports_and_macros = [MacroDefinition('T', element_type.primitive_type),
                               MacroDefinition('T_KINDLEN(context)', KindSpecification(element_type))]
                 else:
-                    macros = [MacroDefinition('T', element_type)]
+                    imports_and_macros = [MacroDefinition('T', element_type)]
                 if isinstance(element_type, (NumpyNDArrayType, HomogeneousTupleType)):
-                    macros.append(MacroDefinition('T_rank', element_type.rank))
+                    imports_and_macros.append(MacroDefinition('T_rank', element_type.rank))
                 elif not isinstance(element_type, FixedSizeNumericType):
                     raise NotImplementedError("Support for lists of types defined in other modules is not yet implemented")
-                macros.append(MacroDefinition('Vector', expr_type))
-                macros.append(MacroDefinition('VectorIterator', IteratorType(expr_type)))
+                imports_and_macros.append(MacroDefinition('Vector', expr_type))
+                imports_and_macros.append(MacroDefinition('VectorIterator', IteratorType(expr_type)))
+            elif isinstance(expr_type, HomogeneousSetType):
+                include = Import(LiteralString('set/template.inc'), Module('_', (), ()))
+                element_type = expr_type.element_type
+                imports_and_macros = []
+                if isinstance(element_type, FixedSizeNumericType):
+                    tmpVar_x = Variable(element_type, 'x')
+                    tmpVar_y = Variable(element_type, 'y')
+                    if isinstance(element_type.primitive_type, PrimitiveComplexType):
+                        complex_tool_import = Import('pyc_tools_f90', Module('pyc_tools_f90',(),()))
+                        self.add_import(complex_tool_import)
+                        imports_and_macros.append(complex_tool_import)
+                        compare_func = FunctionDef('complex_comparison',
+                                                   [FunctionDefArgument(tmpVar_x), FunctionDefArgument(tmpVar_y)],
+                                                   [FunctionDefResult(Variable(PythonNativeBool(), 'c'))], [])
+                        lt_def = FunctionCall(compare_func, [tmpVar_x, tmpVar_y])
+                    else:
+                        lt_def = PyccelAssociativeParenthesis(PyccelLt(tmpVar_x, tmpVar_y))
+                    imports_and_macros.extend([MacroDefinition('T', element_type.primitive_type),
+                              MacroDefinition('T_KINDLEN(context)', KindSpecification(element_type)),
+                              MacroDefinition('T_LT(x,y)', lt_def)])
+                else:
+                    raise NotImplementedError("Support for sets of types which define their own < operator is not yet implemented")
+                imports_and_macros.append(MacroDefinition('Set', expr_type))
+                imports_and_macros.append(MacroDefinition('SetIterator', IteratorType(expr_type)))
             else:
                 raise NotImplementedError(f"Unkown gFTL import for type {expr_type}")
 
             typename = self._print(expr_type)
             mod_name = f'{typename}_mod'
-            module = Module(mod_name, (), (), scope = Scope(), imports = [*macros, include],
+            module = Module(mod_name, (), (), scope = Scope(), imports = [*imports_and_macros, include],
                                        is_external = True)
 
             self._generated_gFTL_extensions[expr_type] = module
@@ -1091,6 +1115,21 @@ class FCodePrinter(CodePrinter):
             vec_type = self._print(expr.class_type)
         return f'{vec_type}({list_arg})'
 
+    def _print_PythonSet(self, expr):
+        if len(expr.args) == 0:
+            list_arg = ''
+            assign = expr.get_direct_user_nodes(lambda a : isinstance(a, Assign))
+            if assign:
+                set_type = self._print(assign[0].lhs.class_type)
+            else:
+                raise errors.report("Can't use an empty set without assigning it to a variable as the type cannot be deduced",
+                        severity='fatal', symbol=expr)
+
+        else:
+            list_arg = self._print_PythonTuple(expr)
+            set_type = self._print(expr.class_type)
+        return f'{set_type}({list_arg})'
+
     def _print_InhomogeneousTupleVariable(self, expr):
         fs = ', '.join(self._print(f) for f in expr)
         return '[{0}]'.format(fs)
@@ -1967,7 +2006,7 @@ class FCodePrinter(CodePrinter):
             Pyccel_del_args = [FunctionCallArgument(var)]
             return self._print(FunctionCall(Pyccel__del, Pyccel_del_args))
 
-        if var.is_alias or isinstance(class_type, HomogeneousListType):
+        if var.is_alias or isinstance(class_type, (HomogeneousListType, HomogeneousSetType)):
             return ''
         elif isinstance(class_type, (NumpyNDArrayType, HomogeneousTupleType, StringType)):
             var_code = self._print(var)
@@ -2011,6 +2050,9 @@ class FCodePrinter(CodePrinter):
     def _print_HomogeneousListType(self, expr):
         return 'Vector_'+self._print(expr.element_type)
 
+    def _print_HomogeneousSetType(self, expr):
+        return 'Set_'+self._print(expr.element_type)
+
     def _print_IteratorType(self, expr):
         iterable_type = self._print(expr.iterable_type)
         return f"{iterable_type}_Iterator"
diff --git a/pyccel/codegen/utilities.py b/pyccel/codegen/utilities.py
index 7303d520..0f6111f7 100644
--- a/pyccel/codegen/utilities.py
+++ b/pyccel/codegen/utilities.py
@@ -40,6 +40,7 @@ internal_libs = {
     "ndarrays"        : ("ndarrays", CompileObj("ndarrays.c",folder="ndarrays")),
     "pyc_math_f90"    : ("math", CompileObj("pyc_math_f90.f90",folder="math")),
     "pyc_math_c"      : ("math", CompileObj("pyc_math_c.c",folder="math")),
+    "pyc_tools_f90"   : ("tools", CompileObj("pyc_tools_f90.f90",folder="tools")),
     "cwrapper"        : ("cwrapper", CompileObj("cwrapper.c",folder="cwrapper", accelerators=('python',))),
     "numpy_f90"       : ("numpy", CompileObj("numpy_f90.f90",folder="numpy")),
     "numpy_c"         : ("numpy", CompileObj("numpy_c.c",folder="numpy")),
@@ -180,7 +181,9 @@ def copy_internal_library(lib_folder, pyccel_dirpath, extra_files = None):
     return lib_dest_path
 
 #==============================================================================
-def generate_extension_modules(import_key, import_node, pyccel_dirpath, language):
+def generate_extension_modules(import_key, import_node, pyccel_dirpath,
+                               includes, libs, libdirs, dependencies,
+                               accelerators, language):
     """
     Generate any new modules that describe extensions.
 
@@ -196,6 +199,16 @@ def generate_extension_modules(import_key, import_node, pyccel_dirpath, language
         be printed).
     pyccel_dirpath : str
         The folder where files are being saved.
+    includes : iterable of strs
+        Include directories paths.
+    libs : iterable of strs
+        Required libraries.
+    libdirs : iterable of strs
+        Paths to directories containing the required libraries.
+    dependencies : iterable of CompileObjs
+        Objects which must also be compiled in order to compile this module/program.
+    accelerators : iterable of str
+        Tool used to accelerate the code (e.g. openmp openacc).
     language : str
         The language in which code is being printed.
 
@@ -221,7 +234,9 @@ def generate_extension_modules(import_key, import_node, pyccel_dirpath, language
                 f.write(code)
 
         new_dependencies.append(CompileObj(os.path.basename(filename), folder=folder,
-                            includes=(os.path.join(pyccel_dirpath, 'gFTL'),)))
+                            includes=(os.path.join(pyccel_dirpath, 'gFTL'), *includes),
+                            libs=libs, libdirs=libdirs, dependencies=dependencies,
+                            accelerators=accelerators))
 
     if lib_name in external_libs:
         copy_internal_library(lib_name, pyccel_dirpath)
diff --git a/pyccel/stdlib/tools/pyc_tools_f90.f90 b/pyccel/stdlib/tools/pyc_tools_f90.f90
new file mode 100644
index 00000000..9eddb09b
--- /dev/null
+++ b/pyccel/stdlib/tools/pyc_tools_f90.f90
@@ -0,0 +1,51 @@
+! -------------------------------------------------------------------------------------- !
+! This file is part of Pyccel which is released under MIT License. See the LICENSE file  !
+! or go to https://github.com/pyccel/pyccel/blob/devel/LICENSE for full license details. !
+! -------------------------------------------------------------------------------------- !
+
+module pyc_tools_f90
+
+  use, intrinsic :: ISO_C_Binding, only : b1 => C_BOOL, &
+         f32 => C_FLOAT, & 
+         f64 => C_DOUBLE, &
+         c64 => C_DOUBLE_COMPLEX, &
+         c32 => C_FLOAT_COMPLEX
+
+  implicit none
+
+  interface complex_comparison
+    module procedure complex_comparison_4
+    module procedure complex_comparison_8
+  end interface complex_comparison
+
+  contains
+
+  function complex_comparison_4(x, y) result(c)
+    complex(c32) :: x
+    complex(c32) :: y
+    logical(b1) :: c
+    real(f32) :: real_x
+    real(f32) :: real_y
+
+    real_x = real(x)
+    real_y = real(y)
+
+    c = merge(real_x < real_y, aimag(x) < aimag(y), real_x /= real_y)
+
+  end function complex_comparison_4
+
+  function complex_comparison_8(x, y) result(c)
+    complex(c64) :: x
+    complex(c64) :: y
+    logical(b1) :: c
+    real(f64) :: real_x
+    real(f64) :: real_y
+
+    real_x = real(x)
+    real_y = real(y)
+
+    c = merge(real_x < real_y, aimag(x) < aimag(y), real_x /= real_y)
+
+  end function complex_comparison_8
+
+end module pyc_tools_f90


Test patch:
diff --git a/tests/epyccel/test_epyccel_sets.py b/tests/epyccel/test_epyccel_sets.py
index 204815af..b6056dd7 100644
--- a/tests/epyccel/test_epyccel_sets.py
+++ b/tests/epyccel/test_epyccel_sets.py
@@ -13,76 +13,76 @@ from pyccel import epyccel
     ],
     scope = "module"
 )
-def language(request):
+def python_only_language(request):
     return request.param
 
-def test_add_literal_int(language) :
+def test_add_literal_int(python_only_language) :
     def add_int():
         a = {1,3,45}
         a.add(4)
         return a
-    epyc_add_element = epyccel(add_int, language = language)
+    epyc_add_element = epyccel(add_int, language = python_only_language)
     pyccel_result = epyc_add_element()
     python_result = add_int()
     assert python_result == pyccel_result
 
-def test_add_literal_complex(language) :
+def test_add_literal_complex(python_only_language) :
     def add_complex():
         a = {6j,7j,8j}
         a.add(9j)
         return a
-    epyc_add_element = epyccel(add_complex, language = language)
+    epyc_add_element = epyccel(add_complex, language = python_only_language)
     pyccel_result = epyc_add_element()
     python_result = add_complex()
     assert python_result == pyccel_result
 
-def test_add_variable_int(language):
+def test_add_variable_int(python_only_language):
     def add_element_range():
         a = {1, 2, 3}
         for i in range(50, 100):
             a.add(i)
         return a
-    epyc_add_element = epyccel(add_element_range, language = language)
+    epyc_add_element = epyccel(add_element_range, language = python_only_language)
     pyccel_result = epyc_add_element()
     python_result = add_element_range()
     assert python_result == pyccel_result
 
-def test_clear_int(language):
+def test_clear_int(python_only_language):
     def clear_int():
         se = {1,2,4,5}
         se.clear()
         return se
-    epyccel_clear = epyccel(clear_int, language = language)
+    epyccel_clear = epyccel(clear_int, language = python_only_language)
     pyccel_result = epyccel_clear()
     python_result = clear_int()
     assert python_result == pyccel_result
 
-def test_clear_float(language):
+def test_clear_float(python_only_language):
     def clear_float():
         se = {7.2, 2.1, 9.8, 6.4}
         se.clear()
         return se
-    epyccel_clear = epyccel(clear_float, language = language)
+    epyccel_clear = epyccel(clear_float, language = python_only_language)
     pyccel_result = epyccel_clear()
     python_result = clear_float()
     assert python_result == pyccel_result
 
-def test_clear_complex(language):
+def test_clear_complex(python_only_language):
     def clear_complex():
         se = {3j, 6j, 2j}
         se.clear()
         return se
-    epyccel_clear = epyccel(clear_complex, language = language)
+    epyccel_clear = epyccel(clear_complex, language = python_only_language)
     pyccel_result = epyccel_clear()
     python_result = clear_complex()
     assert python_result == pyccel_result
 
-def test_copy_int(language):
+def test_copy_int(python_only_language):
     def copy_int():
         se = {1, 2, 4, 5}
         cop = se.copy()
         return cop
-    epyccel_copy = epyccel(copy_int, language = language)
+    epyccel_copy = epyccel(copy_int, language = python_only_language)
     pyccel_result = epyccel_copy()
     python_result = copy_int()
     assert isinstance(python_result, type(pyccel_result))
@@ -90,103 +90,103 @@ def test_copy_int(language):
     assert all(isinstance(elem, type(pyccel_result.pop())) for elem in python_result)
 
 
-def test_copy_float(language):
+def test_copy_float(python_only_language):
     def copy_float():
         se = {5.7, 6.2, 4.3, 9.8}
         cop = se.copy()
         return cop
-    epyccel_copy = epyccel(copy_float, language = language)
+    epyccel_copy = epyccel(copy_float, language = python_only_language)
     pyccel_result = epyccel_copy()
     python_result = copy_float()
     assert isinstance(python_result, type(pyccel_result))
     assert python_result == pyccel_result
     assert all(isinstance(elem, type(pyccel_result.pop())) for elem in python_result)
 
-def test_copy_complex(language):
+def test_copy_complex(python_only_language):
     def copy_complex():
         se = {7j, 6j, 9j}
         cop = se.copy()
         return cop
-    epyccel_copy = epyccel(copy_complex, language = language)
+    epyccel_copy = epyccel(copy_complex, language = python_only_language)
     pyccel_result = epyccel_copy()
     python_result = copy_complex()
     assert isinstance(python_result, type(pyccel_result))
     assert python_result == pyccel_result
     assert all(isinstance(elem, type(pyccel_result.pop())) for elem in python_result)
 
-def test_remove_complex(language):
+def test_remove_complex(python_only_language):
     def remove_complex():
         se = {1j, 3j, 8j}
         se.remove(3j)
         return se
-    epyccel_remove = epyccel(remove_complex, language = language)
+    epyccel_remove = epyccel(remove_complex, language = python_only_language)
     pyccel_result = epyccel_remove()
     python_result = remove_complex()
     assert python_result == pyccel_result
 
-def test_remove_int(language):
+def test_remove_int(python_only_language):
     def remove_int():
         se = {2, 4, 9}
         se.remove(4)
         return se
-    epyccel_remove = epyccel(remove_int, language = language)
+    epyccel_remove = epyccel(remove_int, language = python_only_language)
     pyccel_result = epyccel_remove()
     python_result = remove_int()
     assert python_result == pyccel_result
 
-def test_remove_float(language):
+def test_remove_float(python_only_language):
     def remove_float():
         se = {5.7, 2.4, 8.1}
         se.remove(8.1)
         return se
-    epyccel_remove = epyccel(remove_float, language = language)
+    epyccel_remove = epyccel(remove_float, language = python_only_language)
     pyccel_result = epyccel_remove()
     python_result = remove_float()
     assert python_result == pyccel_result
 
-def test_Discard_int(language):
+def test_Discard_int(python_only_language):
     def Discard_int():
         se = {2.7, 4.3, 9.2}
         se.discard(4.3)
         return se
-    epyccel_remove = epyccel(Discard_int, language = language)
+    epyccel_remove = epyccel(Discard_int, language = python_only_language)
     pyccel_result = epyccel_remove()
     python_result = Discard_int()
     assert python_result == pyccel_result
 
-def test_Discard_complex(language):
+def test_Discard_complex(python_only_language):
     def Discard_complex():
         se = {2j, 5j, 3j, 7j}
         se.discard(5j)
         return se
-    epyccel_remove = epyccel(Discard_complex, language = language)
+    epyccel_remove = epyccel(Discard_complex, language = python_only_language)
     pyccel_result = epyccel_remove()
     python_result = Discard_complex()
     assert python_result == pyccel_result
 
-def test_Discard_wrong_arg(language):
+def test_Discard_wrong_arg(python_only_language):
     def Discard_wrong_arg():
         se = {4.7, 1.3, 8.2}
         se.discard(8.6)
         return se
-    epyccel_remove = epyccel(Discard_wrong_arg, language = language)
+    epyccel_remove = epyccel(Discard_wrong_arg, language = python_only_language)
     pyccel_result = epyccel_remove()
     python_result = Discard_wrong_arg()
     assert python_result == pyccel_result
 
-def test_update_basic(language):
+def test_update_basic(python_only_language):
     def update_basic():
         a = {1, 2, 3}
         b = {4, 5, 6}
         a.update(b)
         return a
 
-    epyccel_update = epyccel(update_basic, language=language)
+    epyccel_update = epyccel(update_basic, language=python_only_language)
     pyccel_result = epyccel_update()
     python_result =  update_basic()
     assert python_result == pyccel_result
 
-def test_update_multiple(language):
+def test_update_multiple(python_only_language):
     def update_multiple():
         a = {1, 2, 3}
         a.update({4, 5})
@@ -194,142 +194,142 @@ def test_update_multiple(language):
         a.update({10})
         return a
 
-    epyccel_update = epyccel(update_multiple, language=language)
+    epyccel_update = epyccel(update_multiple, language=python_only_language)
     pyccel_result = epyccel_update()
     python_result =  update_multiple()
     assert python_result == pyccel_result
 
 
-def test_update_boolean_tuple(language):
+def test_update_boolean_tuple(python_only_language):
     def update_boolean_tuple():
         a = {True}
         b = (False, True, False)
         a.update(b)
         return a
-    epyccel_update = epyccel(update_boolean_tuple, language=language)
+    epyccel_update = epyccel(update_boolean_tuple, language=python_only_language)
     pyccel_result = epyccel_update()
     python_result =  update_boolean_tuple()
     assert python_result == pyccel_result
 
 
-def test_update_complex_list(language):
+def test_update_complex_list(python_only_language):
     def update_complex_list():
         a = {1j, 2 + 3j, 0 + 0j}
         b = {4j, 5j, 1 + 6j}
         a.update(b)
         return a
-    epyccel_update = epyccel(update_complex_list, language=language)
+    epyccel_update = epyccel(update_complex_list, language=python_only_language)
     pyccel_result = epyccel_update()
     python_result =  update_complex_list()
     assert python_result == pyccel_result
 
-def test_update_range(language):
+def test_update_range(python_only_language):
     def update_range():
         a = {1, 2, 3}
         a.update(range(4, 9))
         return a
-    epyccel_update = epyccel(update_range, language=language)
+    epyccel_update = epyccel(update_range, language=python_only_language)
     pyccel_result = epyccel_update()
     python_result =  update_range()
     assert python_result == pyccel_result
 
-def test_update_set_as_arg(language):
+def test_update_set_as_arg(python_only_language):
     def update_set_as_arg():
         a = {1, 2, 3}
         a.update({4, 5, 6})
         return a
 
-    epyccel_update = epyccel(update_set_as_arg, language=language)
+    epyccel_update = epyccel(update_set_as_arg, language=python_only_language)
     pyccel_result = epyccel_update()
     python_result =  update_set_as_arg()
     assert python_result == pyccel_result
 
-def test_update_tuple_as_arg(language):
+def test_update_tuple_as_arg(python_only_language):
     def update_tuple_as_arg():
         a = {1, 2, 3}
         a.update((4, 5, 6))
         return a
-    epyccel_update = epyccel(update_tuple_as_arg, language=language)
+    epyccel_update = epyccel(update_tuple_as_arg, language=python_only_language)
     pyccel_result = epyccel_update()
     python_result =  update_tuple_as_arg()
     assert python_result == pyccel_result
 
-def test_set_with_list(language):
+def test_set_with_list(python_only_language):
     def set_With_list():
         a = [1.6, 6.3, 7.2]
         b = set(a)
         return b
 
-    epyc_set_With_list = epyccel(set_With_list, language = language)
+    epyc_set_With_list = epyccel(set_With_list, language = python_only_language)
     pyccel_result = epyc_set_With_list()
     python_result = set_With_list()
     assert isinstance(python_result, type(pyccel_result))
     assert python_result == pyccel_result
 
-def test_set_with_tuple(language):
+def test_set_with_tuple(python_only_language):
     def set_With_tuple():
         a = (1j, 6j, 7j)
         b = set(a)
         return b
 
-    epyc_set_With_tuple = epyccel(set_With_tuple, language = language)
+    epyc_set_With_tuple = epyccel(set_With_tuple, language = python_only_language)
     pyccel_result = epyc_set_With_tuple()
     python_result = set_With_tuple()
     assert isinstance(python_result, type(pyccel_result))
     assert python_result == pyccel_result
 
-def test_set_with_set(language):
+def test_set_with_set(python_only_language):
     def set_With_set():
         a = {True, False, True}  #pylint: disable=duplicate-value
         b = set(a)
         return b
 
-    epyc_set_With_set = epyccel(set_With_set, language = language)
+    epyc_set_With_set = epyccel(set_With_set, language = python_only_language)
     pyccel_result = epyc_set_With_set()
     python_result = set_With_set()
     assert isinstance(python_result, type(pyccel_result))
     assert python_result == pyccel_result
 
-def test_init_with_set(language):
+def test_init_with_set(python_only_language):
     def init_with_set():
         b = set({4.6, 7.9, 2.5})
         return b
 
-    epyc_init_with_set = epyccel(init_with_set, language = language)
+    epyc_init_with_set = epyccel(init_with_set, language = python_only_language)
     pyccel_result = epyc_init_with_set()
     python_result = init_with_set()
     assert isinstance(python_result, type(pyccel_result))
     assert python_result == pyccel_result
 
-def test_set_init_with_list(language):
+def test_set_init_with_list(python_only_language):
     def init_with_list():
         b = set([4.6, 7.9, 2.5])
         return b
 
-    epyc_init_with_list = epyccel(init_with_list, language = language)
+    epyc_init_with_list = epyccel(init_with_list, language = python_only_language)
     pyccel_result = epyc_init_with_list()
     python_result = init_with_list()
     assert isinstance(python_result, type(pyccel_result))
     assert python_result == pyccel_result
 
 
-def test_set_copy_from_arg1(language):
+def test_set_copy_from_arg1(python_only_language):
     def copy_from_arg1(a : 'list[float]'):
         b = set(a)
         return b
     a = [2.5, 1.4, 9.2]
-    epyc_copy_from_arg = epyccel(copy_from_arg1, language = language)
+    epyc_copy_from_arg = epyccel(copy_from_arg1, language = python_only_language)
     pyccel_result = epyc_copy_from_arg(a)
     python_result = copy_from_arg1(a)
     assert isinstance(python_result, type(pyccel_result))
     assert python_result == pyccel_result
 
-def test_set_copy_from_arg2(language):
+def test_set_copy_from_arg2(python_only_language):
     def copy_from_arg2(a : 'set[float]'):
         b = set(a)
         return b
     a = {2.5, 1.4, 9.2}
-    epyc_copy_from_arg = epyccel(copy_from_arg2, language = language)
+    epyc_copy_from_arg = epyccel(copy_from_arg2, language = python_only_language)
     pyccel_result = epyc_copy_from_arg(a)
     python_result = copy_from_arg2(a)
     assert isinstance(python_result, type(pyccel_result))
diff --git a/tests/epyccel/test_epyccel_variable_annotations.py b/tests/epyccel/test_epyccel_variable_annotations.py
index 1ea48ceb..a79f3a86 100644
--- a/tests/epyccel/test_epyccel_variable_annotations.py
+++ b/tests/epyccel/test_epyccel_variable_annotations.py
@@ -166,42 +166,56 @@ def test_homogeneous_tuple_2_annotation_str(language):
     assert epyc_homogeneous_tuple_annotation() == homogeneous_tuple_annotation()
     assert isinstance(epyc_homogeneous_tuple_annotation(), type(homogeneous_tuple_annotation()))
 
-def test_homogeneous_set_annotation_int(stc_language):
+def test_homogeneous_set_annotation_int(language):
     def homogeneous_set_annotation ():
         a : 'set[int]' #pylint: disable=unused-variable
         a = {1, 2, 3, 4}
-    epyc_homogeneous_set_annotation =  epyccel(homogeneous_set_annotation, language=stc_language)
+        return len(a)
+    epyc_homogeneous_set_annotation =  epyccel(homogeneous_set_annotation, language=language)
     assert epyc_homogeneous_set_annotation() == homogeneous_set_annotation()
     assert isinstance(epyc_homogeneous_set_annotation(), type(homogeneous_set_annotation()))
 
-def test_homogeneous_set_without_annotation(stc_language):
+def test_homogeneous_set_without_annotation(language):
     def homogeneous_set():
         a = {1, 2, 3, 4} #pylint: disable=unused-variable
-    epyc_homogeneous_set =  epyccel(homogeneous_set, language=stc_language)
+        return len(a)
+    epyc_homogeneous_set =  epyccel(homogeneous_set, language=language)
     assert epyc_homogeneous_set() == homogeneous_set()
     assert isinstance(epyc_homogeneous_set(), type(homogeneous_set()))
 
-def test_homogeneous_set_annotation_float(stc_language):
+def test_homogeneous_set_annotation_float(language):
     def homogeneous_set_annotation ():
         a : 'set[float]' #pylint: disable=unused-variable
         a = {1.5, 2.5, 3.3, 4.3}
-    epyc_homogeneous_set_annotation =  epyccel(homogeneous_set_annotation, language=stc_language)
+        return len(a)
+    epyc_homogeneous_set_annotation =  epyccel(homogeneous_set_annotation, language=language)
     assert epyc_homogeneous_set_annotation() == homogeneous_set_annotation()
     assert isinstance(epyc_homogeneous_set_annotation(), type(homogeneous_set_annotation()))
 
-def test_homogeneous_set_annotation_bool(stc_language):
+def test_homogeneous_set_annotation_bool(language):
     def homogeneous_set_annotation ():
         a : 'set[bool]' #pylint: disable=unused-variable
         a = {False, True, False, True} #pylint: disable=duplicate-value
-    epyc_homogeneous_set_annotation =  epyccel(homogeneous_set_annotation, language=stc_language)
+        return len(a)
+    epyc_homogeneous_set_annotation =  epyccel(homogeneous_set_annotation, language=language)
     assert epyc_homogeneous_set_annotation() == homogeneous_set_annotation()
     assert isinstance(epyc_homogeneous_set_annotation(), type(homogeneous_set_annotation()))
 
-def test_homogeneous_set_annotation_complex(stc_language):
+def test_homogeneous_set_annotation_complex(language):
     def homogeneous_set_annotation():
         a: 'set[complex]'  # pylint: disable=unused-variable
-        a = {1+1j, 2+2j, 3+3j, 4+4j}
-    epyc_homogeneous_set_annotation = epyccel(homogeneous_set_annotation, language=stc_language)
+        a = {1+1j, 2+2j, 3+3j, 1-1j}
+        return len(a)
+    epyc_homogeneous_set_annotation = epyccel(homogeneous_set_annotation, language=language)
+    assert epyc_homogeneous_set_annotation() == homogeneous_set_annotation()
+    assert isinstance(epyc_homogeneous_set_annotation(), type(homogeneous_set_annotation()))
+
+def test_empty_homogeneous_set_annotation_int(language):
+    def homogeneous_set_annotation ():
+        a : 'set[int]' #pylint: disable=unused-variable
+        a = set()
+        return len(a)
+    epyc_homogeneous_set_annotation =  epyccel(homogeneous_set_annotation, language=language)
     assert epyc_homogeneous_set_annotation() == homogeneous_set_annotation()
     assert isinstance(epyc_homogeneous_set_annotation(), type(homogeneous_set_annotation()))
 
@@ -209,6 +223,16 @@ def test_homogeneous_empty_list_annotation_int(language):
     def homogeneous_list_annotation():
         a: 'list[int]'  # pylint: disable=unused-variable
         a = []
+        return len(a)
+    epyc_homogeneous_list_annotation = epyccel(homogeneous_list_annotation, language=language)
+    assert epyc_homogeneous_list_annotation() == homogeneous_list_annotation()
+    assert isinstance(epyc_homogeneous_list_annotation(), type(homogeneous_list_annotation()))
+
+def test_homogeneous_empty_list_2_annotation_int(language):
+    def homogeneous_list_annotation():
+        a: 'list[int]'  # pylint: disable=unused-variable
+        a = list() #pylint: disable=use-list-literal
+        return len(a)
     epyc_homogeneous_list_annotation = epyccel(homogeneous_list_annotation, language=language)
     assert epyc_homogeneous_list_annotation() == homogeneous_list_annotation()
     assert isinstance(epyc_homogeneous_list_annotation(), type(homogeneous_list_annotation()))