Consume Span moves - #26467
Conversation
| <!-- disable warnings about obsolete APIs --> | ||
| <NoWarn>$(NoWarn);0809</NoWarn> | ||
| <IsPartialFacadeAssembly Condition="'$(TargetGroup)' == 'netcoreapp' Or '$(TargetGroup)' == 'uap'">true</IsPartialFacadeAssembly> | ||
| <DefineConstants Condition="'$(IsPartialFacadeAssembly)' != 'true'">$(DefineConstants);netstandard;FEATURE_PORTABLE_SPAN</DefineConstants> |
There was a problem hiding this comment.
Can we remove the netstandard constant?
| { | ||
| [Fact] | ||
| public static void DangerousCreate1() | ||
| public static void CreateReadOnlySpan1() |
There was a problem hiding this comment.
nit: remove the 1 suffix from the test name.
| { | ||
| [Fact] | ||
| public static void DangerousCreate1() | ||
| public static void CreateSpan1() |
There was a problem hiding this comment.
Same here. Not sure why it was DangerousCreate1 to begin with.
Also elsewhere.
| <AllowUnsafeBlocks>true</AllowUnsafeBlocks> | ||
| <ProjectGuid>{15DB0DCC-68B4-4CFB-8BD2-F26BCCAF5A3F}</ProjectGuid> | ||
| <IsPartialFacadeAssembly Condition="'$(TargetGroup)' == 'netcoreapp' OR '$(TargetGroup)' == 'uap'">true</IsPartialFacadeAssembly> | ||
| <DefineConstants Condition="'$(IsPartialFacadeAssembly)' != 'true'">$(DefineConstants);netstandard;FEATURE_PORTABLE_SPAN</DefineConstants> |
There was a problem hiding this comment.
These constants seem unnecessary (not used).
There was a problem hiding this comment.
Good point. I added them to keep the new tests in a single file and used IFDEFS but decided that was cumbersome so broke them up into group-specific files included based on IsPartialFacadeAssembly.
I'll remove the DefineConstants.
ahsonkhan
left a comment
There was a problem hiding this comment.
We need to add the ToString() methods to the System.Memory ref as well (for Span/ReadOnlySpan).
| public int Length { get { throw null; } } | ||
| public void CopyTo(System.Span<T> destination) { } | ||
| [System.ComponentModel.EditorBrowsableAttribute((System.ComponentModel.EditorBrowsableState)(1))] | ||
| public static System.ReadOnlySpan<T> DangerousCreate(object obj, ref T objectData, int length) { throw null; } |
There was a problem hiding this comment.
All these changes need to be made to the System.Runtime ref as well.
|
@ahsonkhan thanks for the feedback! I addressed all of it. |
|
Pinging @KrzysztofCwalina @GrabYourPitchforks @ahsonkhan @stephentoub for final feedback. |
| if (SpanHelpers.IsReferenceOrContainsReferences<TTo>()) | ||
| ThrowHelper.ThrowArgumentException_InvalidTypeWithPointersNotSupported(typeof(TTo)); | ||
|
|
||
| int newLength = checked((int)((long)source.Length * Unsafe.SizeOf<TFrom>() / Unsafe.SizeOf<TTo>())); |
There was a problem hiding this comment.
Should we check that TTo's size is more than zero? i.e. what happens if I cast from span of bytes to a span of empty structs?
There was a problem hiding this comment.
Unsafe.SizeOf<TTo> returns a nonzero value for all types.
Added this test:
struct EmptyStruct { }
[Fact]
public static void CastSpanToEmptyStruct()
{
Span<uint> span = new Span<uint>(new uint[] { 1 });
Span<EmptyStruct> emptyspan = MemoryMarshal.Cast<uint, EmptyStruct>(span);
Assert.Equal(1, Unsafe.SizeOf<EmptyStruct>());
Assert.Equal(4, emptyspan.Length);
}| <Compile Include="MemoryMarshal\AsMemory.cs" /> | ||
| <Compile Include="MemoryMarshal\GetReference.cs" /> | ||
| <Compile Include="MemoryMarshal\TryGetArray.cs" /> | ||
| <Compile Include="MemoryMarshal\CastReadOnlySpan.cs" /> |
|
The checked multiply pattern in See notes over in dotnet/coreclr#15492. If we're going to leave it as is, then I'd get rid of the aggressive inlining attribute. |
- [Move Span.DangerousCreate to MemoryMarshal.CreateSpan](#26139) - [Move ReadOnlySpan.DangerousCreate to MemoryMarshal.CreateReadOnlySpan](#26139) - [Move Span.NonPortableCast to MemoryMarshal.Cast](#26368) - [Move ReadOnlySpan.NonPortableCast to MemoryMarshal.Cast](#26368) - [Add ToString override to Span and ReadOnlySpan](#26295) - [Add ToEnumerable function to MemoryMarshal that takes a Memory](#24854)
|
@ianhays, can you please maintain the commit history during PR review? It makes it easier to view only the diffs between commits. |
| /// Returns a <see cref="String"/> with the name of the type and the number of elements | ||
| /// </summary> | ||
| /// <returns>A <see cref="String"/> with the name of the type and the number of elements</returns> | ||
| public override string ToString() => $"System.Span[{Length}]"; |
There was a problem hiding this comment.
Should this be identical to the DebuggerDisplay string (i.e. should we include typeof(T).Name to ToString) - SpanDebuggerDisplay / ReadOnlySpanDebuggerDisplay?
Similarly, should we add the prefix "System.Span" to the DebuggerDisplay, with angle brackets around the type T?
For instance, I propose the following:
Span<int> span = new int[10];
string str = span.ToString(); //System.Span<int>[10]There was a problem hiding this comment.
Sure, that would be useful.
There was a problem hiding this comment.
Updated with the new ToString/DebuggerDisplay string.
I'll post a PR to coreclr with the new strings to FastSpan along with the removal of the old NonPortableCast functions after this PR in corefx is merged.
Apologies, I wasn't expecting any more feedback. That rebase was to remove the feedback commits pre-merge. |
|
Thanks for the feedback! merged. |
Consume Span moves - [Move Span.DangerousCreate to MemoryMarshal.CreateSpan](dotnet/corefx#26139) - [Move ReadOnlySpan.DangerousCreate to MemoryMarshal.CreateReadOnlySpan](dotnet/corefx#26139) - [Move Span.NonPortableCast to MemoryMarshal.Cast](dotnet/corefx#26368) - [Move ReadOnlySpan.NonPortableCast to MemoryMarshal.Cast](dotnet/corefx#26368) - [Add ToString override to Span and ReadOnlySpan](dotnet/corefx#26295) - [Add ToEnumerable function to MemoryMarshal that takes a Memory](dotnet/corefx#24854) Commit migrated from dotnet/corefx@540a99c
Depends on dotnet/coreclr#15941
resolves #26368
resolves #24854
resolves #26295
resolves #26139