Skip to content

Implement IEnumerator<T> on ref struct enumerators #106309

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 15 commits into
base: main
Choose a base branch
from

Conversation

AlexRadch
Copy link
Contributor

Close #105276

@ghost ghost added needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners new-api-needs-documentation labels Aug 13, 2024
@ghost
Copy link

ghost commented Aug 13, 2024

Note regarding the new-api-needs-documentation label:

This serves as a reminder for when your PR is modifying a ref *.cs file and adding/modifying public APIs, please make sure the API implementation in the src *.cs file is documented with triple slash comments, so the PR reviewers can sign off that change.

1 similar comment
@ghost
Copy link

ghost commented Aug 13, 2024

Note regarding the new-api-needs-documentation label:

This serves as a reminder for when your PR is modifying a ref *.cs file and adding/modifying public APIs, please make sure the API implementation in the src *.cs file is documented with triple slash comments, so the PR reviewers can sign off that change.

@dotnet-policy-service dotnet-policy-service bot added the community-contribution Indicates that the PR has been added by a community member label Aug 13, 2024
@@ -222,7 +222,7 @@ public static void ValidateStrides(ReadOnlySpan<nint> strides, ReadOnlySpan<nint
/// <param name="length">The length of the TensorSpan we are iterating over.</param>
public static void AdjustIndexes(int curIndex, nint addend, Span<nint> curIndexes, scoped ReadOnlySpan<nint> length)
{
if (addend <= 0 || curIndex < 0)
if (addend <= 0 || curIndex < 0 || length[curIndex] <= 0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's hitting this? Will this affect behavior of other public API?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It removes Access violation when length[curIndex] is zero. Now code throws an Access violation for an empty tensor.
That was incorrect behavior. I add tests for empty tensor.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Calling MoveNext after it's already returned false is a programmer error. It is not something we need to optimize for.
Removed redundant assertions for match properties after calling
Assert.False(enumerator.MoveNext()).
Updated test methods in ReadOnlyTensorSpanTests.cs to replace instances of TensorSpan with ReadOnlyTensorSpan. This ensures tests validate the behavior of ReadOnlyTensorSpan, including exception handling and constructor functionality. Adjustments made for handling empty and multi-dimensional spans appropriately.
- Updated `Slice` method in `ReadOnlyTensorSpan<T>` to use `ThrowHelper.ThrowIndexOutOfRangeException()` for consistent error handling.
- Removed unnecessary `using System.Reflection;` directive from `TensorSpanTests.cs`.
- Adjusted `TensorSpan_SliceTest` to call `TensorSpan_TestEnumerator(spanInt);` after defining `spanInt` and updated exception checks.
- Introduced a `value` variable in `TensorSpan_TestEnumerator<T>` to accurately restore the enumerator's current value for improved assertions.
static void TestGI<TEnumerator>(TEnumerator enumerator) where TEnumerator : IEnumerator<int>, allows ref struct
{
Assert.False(enumerator.MoveNext());
try { _ = enumerator.Current; } catch (Exception) { }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What are all of these try/catches trying to validate? Is it trying to test that an exception gets thrown? If so, there should be asserts validating that.

/// <summary>Gets the element at the current position of the enumerator.</summary>
T IEnumerator<T>.Current
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These shouldn't need AggressiveInlining on them

@@ -484,7 +486,8 @@ internal Enumerator(ReadOnlyTensorSpan<T> span)
_span = span;
_items = -1;
_curIndexes = new nint[_span.Rank];
_curIndexes[_span.Rank - 1] = -1;
if (_span.Rank > 0)
_curIndexes[_span.Rank - 1] = -1;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
_curIndexes[_span.Rank - 1] = -1;
{
_curIndexes[_span.Rank - 1] = -1;
}

_items = -1;
_curIndexes.Clear();
if (_span.Rank > 0)
_curIndexes[_span.Rank - 1] = -1;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
_curIndexes[_span.Rank - 1] = -1;
{
_curIndexes[_span.Rank - 1] = -1;
}

/// <summary>Gets the element at the current position of the enumerator.</summary>
T IEnumerator<T>.Current
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These also should not need AggressiveInlining.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-System.Memory community-contribution Indicates that the PR has been added by a community member new-api-needs-documentation
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[API Proposal]: Implement IEnumerator<T> on ref struct enumerators
5 participants