Skip to content

Commit

Permalink
Mark the new tensor APIs as experimental for .NET 9 (#105268)
Browse files Browse the repository at this point in the history
* Mark the new tensor APIs as experimental for .NET 9

* Apply SNTEXP0001 to other internal API

* Suppress SNTEXP0001 in System.Numerics.Tensors.Tests

* Use SYSLIB5001. Central registration of experimental API diagnostic ids.

* Add Experimentals.cs (missed in prior commit)

* Revert SLN changes. Add UrlFormat property to attributes where missing.

* Ensure the net8 tensors tests also don't warn for the experimental API usage

---------

Co-authored-by: Eric StJohn <ericstj@microsoft.com>
Co-authored-by: Jeff Handley <jeffhandley@users.noreply.github.com>
  • Loading branch information
3 people authored Jul 24, 2024
1 parent cbfd8ec commit 5998f88
Show file tree
Hide file tree
Showing 19 changed files with 80 additions and 2 deletions.
17 changes: 17 additions & 0 deletions docs/project/list-of-diagnostics.md
Original file line number Diff line number Diff line change
Expand Up @@ -276,3 +276,20 @@ The diagnostic id values reserved for .NET Libraries analyzer warnings are `SYSL
| __`SYSLIBSUPPRESS0001`__ | CA1822 | Do not offer to make methods static when the methods need to be instance methods for a custom marshaller shape. |
| __`SYSLIBSUPPRESS0002`__ | IL2026 | ConfigurationBindingGenerator: suppress RequiresUnreferencedCode diagnostic for binding call that has been intercepted by a generated static variant. |
| __`SYSLIBSUPPRESS0003`__ | IL3050 | ConfigurationBindingGenerator: suppress RequiresDynamicCode diagnostic for binding call that has been intercepted by a generated static variant. |

## Experimental APIs

APIs can be marked as `[Experimental]` if their shape or functionality is included in a release but not yet officially supported. Experimental APIs offer the opportunity to collect customer feedback on these APIs in a major release, usually refining the APIs and removing the `[Experimental]` attribute in the next release. The `[Experimental]` attribute differs from `[RequiresPreviewFeatures]`, wherein:

* `[RequiresPreviewFeatures]` APIs require a corresponding preview feature in another product area such as the compiler or SDK
* `[Experimental]` APIs are entirely self-contained within the libraries and do not require preview features in other parts of the product

The diagnostic id values reserved for experimental APIs are `SYSLIB5001` through `SYSLIB5999`. When marking an API as `[Experimental]`, claim the next three-digit identifier in the `SYSLIB5###` sequence and add it to the list below. The URL template for all experimental APIs is `https://aka.ms/dotnet-warnings/{0}`. The `{0}` placeholder is replaced by the compiler with the `SYSLIB5###` identifier.

### Experimental Diagnostics (`SYSLIB5001` - `SYSLIB5999`)

Diagnostic id values for experimental APIs must not be recycled, as that could silently opt customers into new experimental APIs where they had previously suppressed the ID for a previous usage of the value.

| Diagnostic ID | Introduced | Removed | Description |
| :---------------- | ---------: | ------: | :---------- |
| __`SYSLIB5001`__ | .NET 9 | TBD | `Tensor<T>` and related APIs in System.Numerics.Tensors are experimental in .NET 9 |
25 changes: 25 additions & 0 deletions src/libraries/Common/src/System/Experimentals.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace System
{
internal static class Experimentals
{
internal const string SharedUrlFormat = "https://aka.ms/dotnet-warnings/{0}";

// Please see docs\project\list-of-diagnostics.md for instructions on the steps required
// to introduce an experimental API, claim a diagnostic id, and ensure the
// "aka.ms/dotnet-warnings/{0}" URL points to documentation for the API.
// The diagnostic IDs reserved for experimental APIs are SYSLIB5### (SYSLIB5001 - SYSLIB5999).

// When an API is no longer marked as experimental, the diagnostic ID should be removed from this file
// but retained in the table in docs\project\list-of-diagnostics.md to prevent reuse. Be sure to remove
// suppressions from the codebase as well.

// Tensor<T> and related APIs are marked as [Experimental] in .NET 9
internal const string TensorTDiagId = "SYSLIB5001";

// When adding a new diagnostic ID, add it to the table in docs\project\list-of-diagnostics.md as well.
// Keep new const identifiers above this comment.
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

namespace System.Buffers
{
[System.Diagnostics.CodeAnalysis.Experimental("SYSLIB5001", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")]
public readonly partial struct NIndex : System.IEquatable<System.Buffers.NIndex>
{
private readonly int _dummyPrimitive;
Expand All @@ -29,6 +30,7 @@ namespace System.Buffers
public System.Index ToIndexUnchecked() { throw null; }
public override string ToString() { throw null; }
}
[System.Diagnostics.CodeAnalysis.Experimental("SYSLIB5001", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")]
public readonly partial struct NRange : System.IEquatable<System.Buffers.NRange>
{
private readonly int _dummyPrimitive;
Expand All @@ -53,6 +55,7 @@ namespace System.Buffers
}
namespace System.Numerics.Tensors
{
[System.Diagnostics.CodeAnalysis.Experimental("SYSLIB5001", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")]
public partial interface IReadOnlyTensor<TSelf, T> : System.Collections.Generic.IEnumerable<T>, System.Collections.IEnumerable where TSelf : System.Numerics.Tensors.IReadOnlyTensor<TSelf, T>
{
static abstract TSelf? Empty { get; }
Expand Down Expand Up @@ -80,6 +83,7 @@ public partial interface IReadOnlyTensor<TSelf, T> : System.Collections.Generic.
bool TryCopyTo(scoped System.Numerics.Tensors.TensorSpan<T> destination);
bool TryFlattenTo(scoped System.Span<T> destination);
}
[System.Diagnostics.CodeAnalysis.Experimental("SYSLIB5001", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")]
public partial interface ITensor<TSelf, T> : System.Collections.Generic.IEnumerable<T>, System.Collections.IEnumerable, System.Numerics.Tensors.IReadOnlyTensor<TSelf, T> where TSelf : System.Numerics.Tensors.ITensor<TSelf, T>
{
bool IsReadOnly { get; }
Expand All @@ -98,6 +102,7 @@ public partial interface ITensor<TSelf, T> : System.Collections.Generic.IEnumera
void Fill(T value);
new ref T GetPinnableReference();
}
[System.Diagnostics.CodeAnalysis.Experimental("SYSLIB5001", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")]
public readonly ref partial struct ReadOnlyTensorSpan<T>
{
private readonly object _dummy;
Expand Down Expand Up @@ -157,6 +162,7 @@ public ref partial struct Enumerator
public bool MoveNext() { throw null; }
}
}
[System.Diagnostics.CodeAnalysis.Experimental("SYSLIB5001", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")]
public static partial class Tensor
{
public static System.Numerics.Tensors.Tensor<T> Abs<T>(in System.Numerics.Tensors.ReadOnlyTensorSpan<T> x) where T : System.Numerics.INumberBase<T> { throw null; }
Expand Down Expand Up @@ -674,6 +680,7 @@ public static void Truncate<T>(System.ReadOnlySpan<T> x, System.Span<T> destinat
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> { }
public static void Xor<T>(System.ReadOnlySpan<T> x, T y, System.Span<T> destination) where T : System.Numerics.IBitwiseOperators<T, T, T> { }
}
[System.Diagnostics.CodeAnalysis.Experimental("SYSLIB5001", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")]
public readonly ref partial struct TensorSpan<T>
{
private readonly object _dummy;
Expand Down Expand Up @@ -735,6 +742,7 @@ public ref partial struct Enumerator
public bool MoveNext() { throw null; }
}
}
[System.Diagnostics.CodeAnalysis.Experimental("SYSLIB5001", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")]
public sealed partial class Tensor<T> : System.Collections.Generic.IEnumerable<T>, System.Collections.IEnumerable, System.Numerics.Tensors.IReadOnlyTensor<System.Numerics.Tensors.Tensor<T>, T>, System.Numerics.Tensors.ITensor<System.Numerics.Tensors.Tensor<T>, T>
{
internal Tensor() { }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,15 @@
<PackageDescription>Provides support for operating over tensors.</PackageDescription>
<GenAPIExcludeApiList>ReferenceAssemblyExclusions.txt</GenAPIExcludeApiList>
<ApiCompatValidateAssemblies>true</ApiCompatValidateAssemblies>
<!-- SYSLIB5001: Tensor<T> and related APIs are Experimental in .NET 9 -->
<NoWarn>$(NoWarn);SYSLIB5001</NoWarn>
</PropertyGroup>

<ItemGroup>
<Compile Include="System\Numerics\Tensors\TensorPrimitives.Single.cs" />
<Compile Include="System\Numerics\Tensors\TensorPrimitives.Helpers.cs" />
<Compile Include="System\ThrowHelper.cs" />
<Compile Include="$(CommonPath)System\Experimentals.cs" Link="Common\System\Experimentals.cs" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp'">
Expand Down
1 change: 1 addition & 0 deletions src/libraries/System.Numerics.Tensors/src/System/NIndex.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ namespace System.Buffers
/// int lastElement = someArray[^1]; // lastElement = 5
/// </code>
/// </remarks>
[Experimental(Experimentals.TensorTDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
public readonly struct NIndex : IEquatable<NIndex>
{
private readonly nint _value;
Expand Down
1 change: 1 addition & 0 deletions src/libraries/System.Numerics.Tensors/src/System/NRange.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ namespace System.Buffers
/// int[] subArray2 = someArray[1..^0]; // { 2, 3, 4, 5 }
/// </code>
/// </remarks>
[Experimental(Experimentals.TensorTDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
public readonly struct NRange : IEquatable<NRange>
{
/// <summary>Represent the inclusive start NIndex of the NRange.</summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

namespace System.Numerics.Tensors
{
[Experimental(Experimentals.TensorTDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
public interface IReadOnlyTensor<TSelf, T> : IEnumerable<T>
where TSelf : IReadOnlyTensor<TSelf, T>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System.Buffers;
using System.Diagnostics.CodeAnalysis;

namespace System.Numerics.Tensors
{
[Experimental(Experimentals.TensorTDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
public interface ITensor<TSelf, T>
: IReadOnlyTensor<TSelf, T>
where TSelf : ITensor<TSelf, T>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ namespace System.Numerics.Tensors
/// </summary>
[DebuggerTypeProxy(typeof(TensorSpanDebugView<>))]
[DebuggerDisplay("{ToString(),raw}")]
[Experimental(Experimentals.TensorTDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
public readonly ref struct ReadOnlyTensorSpan<T>
{
/// <summary>A byref or a native ptr.</summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Runtime.InteropServices;
using Microsoft.VisualBasic;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection.Metadata.Ecma335;
using System.Runtime.CompilerServices;
Expand All @@ -17,6 +18,7 @@

namespace System.Numerics.Tensors
{
[Experimental(Experimentals.TensorTDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
public sealed class Tensor<T>
: ITensor<Tensor<T>, T>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@
using static System.Runtime.InteropServices.JavaScript.JSType;
using System.Security.Cryptography;
using System.Runtime.Serialization;
using System.Diagnostics.CodeAnalysis;

#pragma warning disable CS8601 // Possible null reference assignment.
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.

namespace System.Numerics.Tensors
{
[Experimental(Experimentals.TensorTDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
public static partial class Tensor
{
#region AsReadOnlySpan
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Runtime.InteropServices;

namespace System.Numerics.Tensors
{
[Experimental(Experimentals.TensorTDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
internal static class TensorHelpers
{

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

namespace System.Numerics.Tensors
{

[Experimental(Experimentals.TensorTDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
internal readonly struct TensorShape
{
// Used to determine when we need to allocate a metadata array
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ namespace System.Numerics.Tensors
/// </summary>
[DebuggerTypeProxy(typeof(TensorSpanDebugView<>))]
[DebuggerDisplay("{ToString(),raw}")]
[Experimental(Experimentals.TensorTDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
public readonly ref struct TensorSpan<T>
{
/// <summary>A byref or a native ptr.</summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;

namespace System.Numerics.Tensors
{

[Experimental(Experimentals.TensorTDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
internal sealed class TensorSpanDebugView<T>
{
private readonly T[] _array;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@
using System.Buffers;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;

namespace System.Numerics.Tensors
{

[Experimental(Experimentals.TensorTDiagId, UrlFormat = Experimentals.SharedUrlFormat)]
internal static partial class TensorSpanHelpers
{
internal static bool AreShapesTheSame<T>(ReadOnlyTensorSpan<T> tensor1, ReadOnlyTensorSpan<T> tensor2)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@
-->

<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>$(NetCoreAppCurrent)</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefineConstants>$(DefineConstants);SNT_NET8_TESTS</DefineConstants>
<NoWarn>$(NoWarn);SYSLIB5001</NoWarn>
</PropertyGroup>

<ItemGroup>
Expand All @@ -21,7 +22,7 @@
<Compile Include="..\TensorPrimitives.ConvertTo.cs" />
<Compile Include="..\TensorPrimitives.Generic.cs" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\System.Numerics.Tensors.csproj" SkipUseReferenceAssembly="true">
<SetTargetFramework>TargetFramework=net8.0</SetTargetFramework>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
<PropertyGroup>
<TargetFrameworks>$(NetCoreAppCurrent);$(NetFrameworkMinimum)</TargetFrameworks>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<!-- SYSLIB5001: Tensor<T> and related APIs are Experimental in .NET 9 -->
<NoWarn>$(NoWarn);SYSLIB5001</NoWarn>
</PropertyGroup>

<PropertyGroup>
Expand Down

0 comments on commit 5998f88

Please sign in to comment.