Skip to content

Commit

Permalink
Fix infinite loop when slices are found in array call (#1615)
Browse files Browse the repository at this point in the history
Remove wrong assumption that elements of a list passed to a call
to `array` are always scalars, which resulted in an infinite loop when
a slice was encountered. To this end handle a multi-dimensional
`IndexedElement` in the same way as a `Variable`. This fixes #1613.

Add a condition to ensure that an error is raised if this problem
re-arises, rather than entering an infinite loop.
  • Loading branch information
EmilyBourne committed Nov 22, 2023
1 parent f884e24 commit 6a2348a
Show file tree
Hide file tree
Showing 5 changed files with 19 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ All notable changes to this project will be documented in this file.
- #1582 : Allow homogeneous tuples in classes.
- #1619 : Give priority to imported functions over builtin functions.
- #1614 : Allow relative paths for custom compilation file.
- #1615 : Fixed infinite loop when passing slices while copying arrays.

### Changed

Expand Down
5 changes: 4 additions & 1 deletion pyccel/codegen/printing/ccode.py
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,7 @@ def copy_NumpyArray_Data(self, expr):
while i < num_elements:
current_element = flattened_list[i]
# Copy an array element
if isinstance(current_element, Variable) and current_element.rank >= 1:
if isinstance(current_element, (Variable, IndexedElement)) and current_element.rank >= 1:
elem_name = self._print(current_element)
target = self._print(ObjectAddress(copy_to))
operations += f"array_copy_data({target}, {elem_name}, {offset_str});\n"
Expand All @@ -447,6 +447,9 @@ def copy_NumpyArray_Data(self, expr):
self.add_import(c_imports['string'])
remaining_elements = flattened_list[i:]
lenSubset = next((i for i,v in enumerate(remaining_elements) if v.rank != 0), len(remaining_elements))
if lenSubset == 0:
errors.report(f"Can't copy {rhs} into {lhs}", symbol=expr,
severity='fatal')
subset = remaining_elements[:lenSubset]

# Declare list of consecutive elements
Expand Down
2 changes: 1 addition & 1 deletion pyccel/parser/semantic.py
Original file line number Diff line number Diff line change
Expand Up @@ -2165,7 +2165,7 @@ def _visit_IndexedElement(self, expr):
elif any(isinstance(getattr(a, 'class_type', None), NativeTuple) for a in args):
n_exprs = None
for a in args:
if a.shape and isinstance(a.shape[0], LiteralInteger):
if getattr(a, 'shape', None) and isinstance(a.shape[0], LiteralInteger):
a_len = a.shape[0]
if n_exprs:
assert n_exprs == a_len
Expand Down
4 changes: 4 additions & 0 deletions tests/epyccel/modules/arrays.py
Original file line number Diff line number Diff line change
Expand Up @@ -1674,6 +1674,10 @@ def arrs_2d_negative_index():
b = a[1:-1, :-1] + a[2:, -9:]
return np.shape(b)[0], np.shape(b)[1], np.sum(b)

def arr_tuple_slice_index(a : 'int[:,:]'):
r = a[(0,1,3),1:]
return r

#==============================================================================
# NUMPY ARANGE
#==============================================================================
Expand Down
9 changes: 9 additions & 0 deletions tests/epyccel/test_arrays.py
Original file line number Diff line number Diff line change
Expand Up @@ -3549,6 +3549,15 @@ def test_arrs_1d_int64_index(language):
f2 = epyccel(f1, language = language)
assert f1() == f2()

def test_arr_tuple_slice_index(language):
f1 = arrays.arr_tuple_slice_index
f2 = epyccel(f1, language = language)

r_python = f1(arrays.a_2d_c)
r_pyccel = f2(arrays.a_2d_c)

check_array_equal(r_python, r_pyccel)

@pytest.mark.parametrize( 'language', [
pytest.param("c", marks = [
pytest.mark.skip(reason="negative step does not work in c. See #1311"),
Expand Down

0 comments on commit 6a2348a

Please sign in to comment.