Skip to content

Commit 08863f2

Browse files
Remove the experimental attribute from the tensor APIs (#117103)
* Remove the experimental attribute from the tensor APIs * Ensure the relevant interfaces are implemented on the TensorSpan and ReadOnlyTensorSpan types * Don't use the tuple based swap, it asserts LocalDataFlowVisitor * Apply suggestions from code review Co-authored-by: Stephen Toub <[email protected]> * Update src/libraries/System.Numerics.Tensors/ref/System.Numerics.Tensors.csproj * Update src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/Tensor.cs * Update src/libraries/System.Numerics.Tensors/src/System.Numerics.Tensors.csproj --------- Co-authored-by: Stephen Toub <[email protected]>
1 parent 5cd3afb commit 08863f2

25 files changed

+759
-781
lines changed

docs/project/list-of-diagnostics.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -310,9 +310,9 @@ Diagnostic id values for experimental APIs must not be recycled, as that could s
310310

311311
| Diagnostic ID | Introduced | Removed | Description |
312312
| :---------------- | ---------: | ------: | :---------- |
313-
| __`SYSLIB5001`__ | .NET 9 | TBD | `Tensor<T>` and related APIs in System.Numerics.Tensors are experimental |
313+
| __`SYSLIB5001`__ | .NET 9 | .NET 10 | `Tensor<T>` and related APIs in System.Numerics.Tensors are experimental |
314314
| __`SYSLIB5002`__ | .NET 9 | TBD | `SystemColors` alternate colors are experimental |
315315
| __`SYSLIB5003`__ | .NET 9 | TBD | `System.Runtime.Intrinsics.Arm.Sve` is experimental |
316316
| __`SYSLIB5004`__ | .NET 9 | TBD | `X86Base.DivRem` is experimental since performance is not as optimized as `T.DivRem` |
317-
| __`SYSLIB5005`__ | .NET 9 | TBD | `System.Formats.Nrbf` is experimental |
317+
| __`SYSLIB5005`__ | .NET 9 | .NET 10 | `System.Formats.Nrbf` is experimental |
318318
| __`SYSLIB5006`__ | .NET 10 | TBD | Types for Post-Quantum Cryptography (PQC) are experimental. |

src/libraries/System.Numerics.Tensors/ref/System.Numerics.Tensors.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
<PropertyGroup>
44
<TargetFrameworks>$(NetCoreAppCurrent);$(NetCoreAppPrevious);$(NetCoreAppMinimum);netstandard2.0;$(NetFrameworkMinimum)</TargetFrameworks>
55
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
6-
<!-- SYSLIB5001: Tensor<T> and related APIs in System.Numerics.Tensors are experimental in .NET 9 -->
7-
<NoWarn>$(NoWarn);SYSLIB5001</NoWarn>
6+
<!-- SA1001: Commas should not be preceded by a whitespace; needed due to ifdef -->
7+
<NoWarn>$(NoWarn);SA1001</NoWarn>
88
</PropertyGroup>
99

1010
<ItemGroup>

src/libraries/System.Numerics.Tensors/ref/System.Numerics.Tensors.net9.cs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,16 @@ public readonly ref partial struct ReadOnlyTensorDimensionSpan<T>
1919
void System.IDisposable.Dispose() { }
2020
}
2121
}
22+
public readonly ref partial struct ReadOnlyTensorSpan<T> : System.Numerics.Tensors.IReadOnlyTensor, System.Numerics.Tensors.IReadOnlyTensor<System.Numerics.Tensors.ReadOnlyTensorSpan<T>, T>
23+
{
24+
object? System.Numerics.Tensors.IReadOnlyTensor.this[params scoped System.ReadOnlySpan<System.Buffers.NIndex> indexes] { get { throw null; } }
25+
object? System.Numerics.Tensors.IReadOnlyTensor.this[params scoped System.ReadOnlySpan<nint> indexes] { get { throw null; } }
26+
System.Numerics.Tensors.ReadOnlyTensorSpan<T> System.Numerics.Tensors.IReadOnlyTensor<System.Numerics.Tensors.ReadOnlyTensorSpan<T>, T>.AsReadOnlyTensorSpan() { throw null; }
27+
System.Numerics.Tensors.ReadOnlyTensorSpan<T> System.Numerics.Tensors.IReadOnlyTensor<System.Numerics.Tensors.ReadOnlyTensorSpan<T>, T>.AsReadOnlyTensorSpan(params scoped System.ReadOnlySpan<nint> startIndexes) { throw null; }
28+
System.Numerics.Tensors.ReadOnlyTensorSpan<T> System.Numerics.Tensors.IReadOnlyTensor<System.Numerics.Tensors.ReadOnlyTensorSpan<T>, T>.AsReadOnlyTensorSpan(params scoped System.ReadOnlySpan<System.Buffers.NIndex> startIndexes) { throw null; }
29+
System.Numerics.Tensors.ReadOnlyTensorSpan<T> System.Numerics.Tensors.IReadOnlyTensor<System.Numerics.Tensors.ReadOnlyTensorSpan<T>, T>.AsReadOnlyTensorSpan(params scoped System.ReadOnlySpan<System.Buffers.NRange> ranges) { throw null; }
30+
System.Numerics.Tensors.ReadOnlyTensorSpan<T> System.Numerics.Tensors.IReadOnlyTensor<System.Numerics.Tensors.ReadOnlyTensorSpan<T>, T>.ToDenseTensor() { throw null; }
31+
}
2232
public readonly ref partial struct TensorDimensionSpan<T>
2333
{
2434
public ref partial struct Enumerator : System.Collections.Generic.IEnumerator<System.Numerics.Tensors.TensorSpan<T>>, System.Collections.IEnumerator, System.IDisposable
@@ -27,4 +37,31 @@ public readonly ref partial struct TensorDimensionSpan<T>
2737
void System.IDisposable.Dispose() { }
2838
}
2939
}
40+
public readonly ref partial struct TensorSpan<T> : System.Numerics.Tensors.IReadOnlyTensor, System.Numerics.Tensors.IReadOnlyTensor<System.Numerics.Tensors.TensorSpan<T>, T>, System.Numerics.Tensors.ITensor, System.Numerics.Tensors.ITensor<System.Numerics.Tensors.TensorSpan<T>, T>
41+
{
42+
object? System.Numerics.Tensors.IReadOnlyTensor.this[params scoped System.ReadOnlySpan<System.Buffers.NIndex> indexes] { get { throw null; } }
43+
object? System.Numerics.Tensors.IReadOnlyTensor.this[params scoped System.ReadOnlySpan<nint> indexes] { get { throw null; } }
44+
ref readonly T System.Numerics.Tensors.IReadOnlyTensor<System.Numerics.Tensors.TensorSpan<T>, T>.this[params scoped System.ReadOnlySpan<System.Buffers.NIndex> indexes] { get { throw null; } }
45+
ref readonly T System.Numerics.Tensors.IReadOnlyTensor<System.Numerics.Tensors.TensorSpan<T>, T>.this[params scoped System.ReadOnlySpan<nint> indexes] { get { throw null; } }
46+
System.Numerics.Tensors.ReadOnlyTensorSpan<T> System.Numerics.Tensors.IReadOnlyTensor<System.Numerics.Tensors.TensorSpan<T>, T>.AsReadOnlyTensorSpan() { throw null; }
47+
System.Numerics.Tensors.ReadOnlyTensorSpan<T> System.Numerics.Tensors.IReadOnlyTensor<System.Numerics.Tensors.TensorSpan<T>, T>.AsReadOnlyTensorSpan(params scoped System.ReadOnlySpan<nint> startIndexes) { throw null; }
48+
System.Numerics.Tensors.ReadOnlyTensorSpan<T> System.Numerics.Tensors.IReadOnlyTensor<System.Numerics.Tensors.TensorSpan<T>, T>.AsReadOnlyTensorSpan(params scoped System.ReadOnlySpan<System.Buffers.NIndex> startIndexes) { throw null; }
49+
System.Numerics.Tensors.ReadOnlyTensorSpan<T> System.Numerics.Tensors.IReadOnlyTensor<System.Numerics.Tensors.TensorSpan<T>, T>.AsReadOnlyTensorSpan(params scoped System.ReadOnlySpan<System.Buffers.NRange> ranges) { throw null; }
50+
System.Numerics.Tensors.ReadOnlyTensorDimensionSpan<T> System.Numerics.Tensors.IReadOnlyTensor<System.Numerics.Tensors.TensorSpan<T>, T>.GetDimensionSpan(int dimension) { throw null; }
51+
ref readonly T System.Numerics.Tensors.IReadOnlyTensor<System.Numerics.Tensors.TensorSpan<T>, T>.GetPinnableReference() { throw null; }
52+
System.Numerics.Tensors.TensorSpan<T> System.Numerics.Tensors.IReadOnlyTensor<System.Numerics.Tensors.TensorSpan<T>, T>.ToDenseTensor() { throw null; }
53+
54+
bool System.Numerics.Tensors.ITensor.IsReadOnly { get { throw null; } }
55+
object? System.Numerics.Tensors.ITensor.this[params scoped System.ReadOnlySpan<System.Buffers.NIndex> indexes] { get { throw null; } set { } }
56+
object? System.Numerics.Tensors.ITensor.this[params scoped System.ReadOnlySpan<nint> indexes] { get { throw null; } set { } }
57+
void System.Numerics.Tensors.ITensor.Fill(object value) { }
58+
static System.Numerics.Tensors.TensorSpan<T> ITensor<TensorSpan<T>, T>.Create(scoped System.ReadOnlySpan<nint> lengths, bool pinned) { throw null; }
59+
static System.Numerics.Tensors.TensorSpan<T> ITensor<TensorSpan<T>, T>.Create(scoped System.ReadOnlySpan<nint> lengths, scoped System.ReadOnlySpan<nint> strides, bool pinned) { throw null; }
60+
static System.Numerics.Tensors.TensorSpan<T> ITensor<TensorSpan<T>, T>.CreateUninitialized(scoped System.ReadOnlySpan<nint> lengths, bool pinned) { throw null; }
61+
static System.Numerics.Tensors.TensorSpan<T> ITensor<TensorSpan<T>, T>.CreateUninitialized(scoped System.ReadOnlySpan<nint> lengths, scoped System.ReadOnlySpan<nint> strides, bool pinned) { throw null; }
62+
System.Numerics.Tensors.TensorSpan<T> System.Numerics.Tensors.ITensor<System.Numerics.Tensors.TensorSpan<T>, T>.AsTensorSpan() { throw null; }
63+
System.Numerics.Tensors.TensorSpan<T> System.Numerics.Tensors.ITensor<System.Numerics.Tensors.TensorSpan<T>, T>.AsTensorSpan(params scoped System.ReadOnlySpan<nint> startIndexes) { throw null; }
64+
System.Numerics.Tensors.TensorSpan<T> System.Numerics.Tensors.ITensor<System.Numerics.Tensors.TensorSpan<T>, T>.AsTensorSpan(params scoped System.ReadOnlySpan<System.Buffers.NIndex> startIndexes) { throw null; }
65+
System.Numerics.Tensors.TensorSpan<T> System.Numerics.Tensors.ITensor<System.Numerics.Tensors.TensorSpan<T>, T>.AsTensorSpan(params scoped System.ReadOnlySpan<System.Buffers.NRange> ranges) { throw null; }
66+
}
3067
}

src/libraries/System.Numerics.Tensors/ref/System.Numerics.Tensors.netcore.cs

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66

77
namespace System.Buffers
88
{
9-
[System.Diagnostics.CodeAnalysis.ExperimentalAttribute("SYSLIB5001", UrlFormat="https://aka.ms/dotnet-warnings/{0}")]
109
public readonly partial struct NIndex : System.IEquatable<System.Buffers.NIndex>
1110
{
1211
private readonly int _dummyPrimitive;
@@ -30,7 +29,6 @@ namespace System.Buffers
3029
public System.Index ToIndexUnchecked() { throw null; }
3130
public override string ToString() { throw null; }
3231
}
33-
[System.Diagnostics.CodeAnalysis.ExperimentalAttribute("SYSLIB5001", UrlFormat="https://aka.ms/dotnet-warnings/{0}")]
3432
public readonly partial struct NRange : System.IEquatable<System.Buffers.NRange>
3533
{
3634
private readonly int _dummyPrimitive;
@@ -55,7 +53,6 @@ namespace System.Buffers
5553
}
5654
namespace System.Numerics.Tensors
5755
{
58-
[System.Diagnostics.CodeAnalysis.ExperimentalAttribute("SYSLIB5001", UrlFormat="https://aka.ms/dotnet-warnings/{0}")]
5956
public partial interface IReadOnlyTensor
6057
{
6158
nint FlattenedLength { get; }
@@ -70,10 +67,12 @@ public partial interface IReadOnlyTensor
7067
int Rank { get; }
7168
[System.Diagnostics.CodeAnalysis.UnscopedRefAttribute]
7269
System.ReadOnlySpan<nint> Strides { get; }
73-
System.Buffers.MemoryHandle GetPinnedHandle();
7470
}
75-
[System.Diagnostics.CodeAnalysis.ExperimentalAttribute("SYSLIB5001", UrlFormat="https://aka.ms/dotnet-warnings/{0}")]
76-
public partial interface IReadOnlyTensor<TSelf, T> : System.Collections.Generic.IEnumerable<T>, System.Collections.IEnumerable, System.Numerics.Tensors.IReadOnlyTensor where TSelf : System.Numerics.Tensors.IReadOnlyTensor<TSelf, T>
71+
public partial interface IReadOnlyTensor<TSelf, T> : System.Numerics.Tensors.IReadOnlyTensor
72+
where TSelf : System.Numerics.Tensors.IReadOnlyTensor<TSelf, T>
73+
#if NET9_0_OR_GREATER
74+
, allows ref struct
75+
#endif
7776
{
7877
static abstract TSelf Empty { get; }
7978
new ref readonly T this[params scoped System.ReadOnlySpan<System.Buffers.NIndex> indexes] { get; }
@@ -94,7 +93,6 @@ public partial interface IReadOnlyTensor<TSelf, T> : System.Collections.Generic.
9493
bool TryCopyTo(scoped in System.Numerics.Tensors.TensorSpan<T> destination);
9594
bool TryFlattenTo(scoped System.Span<T> destination);
9695
}
97-
[System.Diagnostics.CodeAnalysis.ExperimentalAttribute("SYSLIB5001", UrlFormat="https://aka.ms/dotnet-warnings/{0}")]
9896
public partial interface ITensor : System.Numerics.Tensors.IReadOnlyTensor
9997
{
10098
bool IsReadOnly { get; }
@@ -103,8 +101,11 @@ public partial interface ITensor : System.Numerics.Tensors.IReadOnlyTensor
103101
void Clear();
104102
void Fill(object value);
105103
}
106-
[System.Diagnostics.CodeAnalysis.ExperimentalAttribute("SYSLIB5001", UrlFormat="https://aka.ms/dotnet-warnings/{0}")]
107-
public partial interface ITensor<TSelf, T> : System.Collections.Generic.IEnumerable<T>, System.Collections.IEnumerable, System.Numerics.Tensors.IReadOnlyTensor, System.Numerics.Tensors.IReadOnlyTensor<TSelf, T>, System.Numerics.Tensors.ITensor where TSelf : System.Numerics.Tensors.ITensor<TSelf, T>
104+
public partial interface ITensor<TSelf, T> : System.Numerics.Tensors.IReadOnlyTensor, System.Numerics.Tensors.IReadOnlyTensor<TSelf, T>, System.Numerics.Tensors.ITensor
105+
where TSelf : System.Numerics.Tensors.ITensor<TSelf, T>
106+
#if NET9_0_OR_GREATER
107+
, allows ref struct
108+
#endif
108109
{
109110
new ref T this[params scoped System.ReadOnlySpan<System.Buffers.NIndex> indexes] { get; }
110111
new TSelf this[params scoped System.ReadOnlySpan<System.Buffers.NRange> ranges] { get; set; }
@@ -126,6 +127,7 @@ public readonly ref partial struct ReadOnlyTensorDimensionSpan<T>
126127
private readonly object _dummy;
127128
private readonly int _dummyPrimitive;
128129
public System.Numerics.Tensors.ReadOnlyTensorSpan<T> this[nint index] { get { throw null; } }
130+
public bool IsDense { get { throw null; } }
129131
public nint Length { get { throw null; } }
130132
public System.Numerics.Tensors.ReadOnlyTensorDimensionSpan<T>.Enumerator GetEnumerator() { throw null; }
131133
public ref partial struct Enumerator
@@ -137,7 +139,6 @@ public ref partial struct Enumerator
137139
public void Reset() { }
138140
}
139141
}
140-
[System.Diagnostics.CodeAnalysis.ExperimentalAttribute("SYSLIB5001", UrlFormat="https://aka.ms/dotnet-warnings/{0}")]
141142
public readonly ref partial struct ReadOnlyTensorSpan<T>
142143
{
143144
private readonly object _dummy;
@@ -162,6 +163,7 @@ public readonly ref partial struct ReadOnlyTensorSpan<T>
162163
public bool HasAnyDenseDimensions { get { throw null; } }
163164
public bool IsDense { get { throw null; } }
164165
public bool IsEmpty { get { throw null; } }
166+
public bool IsPinned { get { throw null; } }
165167
public ref readonly T this[params scoped System.ReadOnlySpan<System.Buffers.NIndex> indexes] { get { throw null; } }
166168
public System.Numerics.Tensors.ReadOnlyTensorSpan<T> this[params scoped System.ReadOnlySpan<System.Buffers.NRange> ranges] { get { throw null; } }
167169
public ref readonly T this[params scoped System.ReadOnlySpan<nint> indexes] { get { throw null; } }
@@ -205,10 +207,9 @@ public void FlattenTo(scoped System.Span<T> destination) { }
205207
readonly object? System.Collections.IEnumerator.Current { get { throw null; } }
206208
public bool MoveNext() { throw null; }
207209
public void Reset() { }
208-
void System.IDisposable.Dispose() { }
210+
readonly void System.IDisposable.Dispose() { }
209211
}
210212
}
211-
[System.Diagnostics.CodeAnalysis.ExperimentalAttribute("SYSLIB5001", UrlFormat="https://aka.ms/dotnet-warnings/{0}")]
212213
public static partial class Tensor
213214
{
214215
public static System.Numerics.Tensors.Tensor<T> Abs<T>(in System.Numerics.Tensors.ReadOnlyTensorSpan<T> x) where T : System.Numerics.INumberBase<T> { throw null; }
@@ -578,7 +579,9 @@ public readonly ref partial struct TensorDimensionSpan<T>
578579
private readonly object _dummy;
579580
private readonly int _dummyPrimitive;
580581
public System.Numerics.Tensors.TensorSpan<T> this[nint index] { get { throw null; } }
582+
public bool IsDense { get { throw null; } }
581583
public nint Length { get { throw null; } }
584+
public static implicit operator System.Numerics.Tensors.ReadOnlyTensorDimensionSpan<T>(scoped in System.Numerics.Tensors.TensorDimensionSpan<T> tensorDimension) { throw null; }
582585
public System.Numerics.Tensors.TensorDimensionSpan<T>.Enumerator GetEnumerator() { throw null; }
583586
public ref partial struct Enumerator
584587
{
@@ -823,7 +826,6 @@ public static void Truncate<T>(System.ReadOnlySpan<T> x, System.Span<T> destinat
823826
public static void Xor<T>(System.ReadOnlySpan<T> x, System.ReadOnlySpan<T> y, System.Span<T> destination) where T : System.Numerics.IBitwiseOperators<T, T, T> { }
824827
public static void Xor<T>(System.ReadOnlySpan<T> x, T y, System.Span<T> destination) where T : System.Numerics.IBitwiseOperators<T, T, T> { }
825828
}
826-
[System.Diagnostics.CodeAnalysis.ExperimentalAttribute("SYSLIB5001", UrlFormat="https://aka.ms/dotnet-warnings/{0}")]
827829
public readonly ref partial struct TensorSpan<T>
828830
{
829831
private readonly object _dummy;
@@ -848,6 +850,7 @@ public readonly ref partial struct TensorSpan<T>
848850
public bool HasAnyDenseDimensions { get { throw null; } }
849851
public bool IsDense { get { throw null; } }
850852
public bool IsEmpty { get { throw null; } }
853+
public bool IsPinned { get { throw null; } }
851854
public ref T this[params scoped System.ReadOnlySpan<System.Buffers.NIndex> indexes] { get { throw null; } }
852855
public System.Numerics.Tensors.TensorSpan<T> this[params scoped System.ReadOnlySpan<System.Buffers.NRange> ranges] { get { throw null; } set { } }
853856
public ref T this[params scoped System.ReadOnlySpan<nint> indexes] { get { throw null; } }
@@ -897,11 +900,10 @@ public void FlattenTo(scoped System.Span<T> destination) { }
897900
readonly object? System.Collections.IEnumerator.Current { get { throw null; } }
898901
public bool MoveNext() { throw null; }
899902
public void Reset() { }
900-
void System.IDisposable.Dispose() { }
903+
readonly void System.IDisposable.Dispose() { }
901904
}
902905
}
903-
[System.Diagnostics.CodeAnalysis.ExperimentalAttribute("SYSLIB5001", UrlFormat="https://aka.ms/dotnet-warnings/{0}")]
904-
public sealed partial class Tensor<T> : System.Collections.Generic.IEnumerable<T>, System.Collections.IEnumerable, System.Numerics.Tensors.IReadOnlyTensor, System.Numerics.Tensors.IReadOnlyTensor<System.Numerics.Tensors.Tensor<T>, T>, System.Numerics.Tensors.ITensor, System.Numerics.Tensors.ITensor<System.Numerics.Tensors.Tensor<T>, T>
906+
public sealed partial class Tensor<T> : System.Collections.IEnumerable, System.Collections.Generic.IEnumerable<T>, System.Numerics.Tensors.IReadOnlyTensor, System.Numerics.Tensors.IReadOnlyTensor<System.Numerics.Tensors.Tensor<T>, T>, System.Numerics.Tensors.ITensor, System.Numerics.Tensors.ITensor<System.Numerics.Tensors.Tensor<T>, T>
905907
{
906908
internal Tensor() { }
907909
public static System.Numerics.Tensors.Tensor<T> Empty { get { throw null; } }

0 commit comments

Comments
 (0)