diff --git a/CommunityToolkit.HighPerformance/Extensions/SpinLockExtensions.cs b/CommunityToolkit.HighPerformance/Extensions/SpinLockExtensions.cs index 35e975b..87b23b0 100644 --- a/CommunityToolkit.HighPerformance/Extensions/SpinLockExtensions.cs +++ b/CommunityToolkit.HighPerformance/Extensions/SpinLockExtensions.cs @@ -4,6 +4,7 @@ using System.ComponentModel; using System.Runtime.CompilerServices; +using System.Runtime.Versioning; using System.Threading; namespace CommunityToolkit.HighPerformance; @@ -94,6 +95,9 @@ public void Dispose() /// <param name="spinLock">The target <see cref="SpinLock"/> to use</param> /// <returns>A wrapper type that will release <paramref name="spinLock"/> when its <see cref="System.IDisposable.Dispose"/> method is called.</returns> /// <remarks>The returned <see cref="Lock"/> value shouldn't be used directly: use this extension in a <see langword="using"/> block or statement.</remarks> + [RequiresPreviewFeatures( + "The Lock type has no compiler support to ensure the lifetime of referenced values is respected, and as such using it incorrectly may lead to GC holes.", + Url = "https://github.com/dotnet/runtime/issues/46104")] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Lock Enter(ref this SpinLock spinLock) { @@ -131,6 +135,9 @@ public static Lock Enter(object owner, ref SpinLock spinLock) /// A <see langword="struct"/> that is used to enter and hold a <see cref="SpinLock"/> through a <see langword="using"/> block or statement. /// </summary> [EditorBrowsable(EditorBrowsableState.Never)] + [RequiresPreviewFeatures( + "The Lock type has no compiler support to ensure the lifetime of referenced values is respected, and as such using it incorrectly may lead to GC holes.", + Url = "https://github.com/dotnet/runtime/issues/46104")] public readonly ref struct Lock { /// <summary> diff --git a/CommunityToolkit.HighPerformance/NullableReadOnlyRef{T}.cs b/CommunityToolkit.HighPerformance/NullableReadOnlyRef{T}.cs index 9813be8..104b96b 100644 --- a/CommunityToolkit.HighPerformance/NullableReadOnlyRef{T}.cs +++ b/CommunityToolkit.HighPerformance/NullableReadOnlyRef{T}.cs @@ -7,6 +7,7 @@ using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Runtime.Versioning; namespace CommunityToolkit.HighPerformance; @@ -14,6 +15,9 @@ namespace CommunityToolkit.HighPerformance; /// A <see langword="struct"/> that can store an optional readonly reference to a value of a specified type. /// </summary> /// <typeparam name="T">The type of value to reference.</typeparam> +[RequiresPreviewFeatures( + "The NullableReadOnlyRef<T> type has no compiler support to ensure the lifetime of referenced values is respected, and as such using it incorrectly may lead to GC holes.", + Url = "https://github.com/dotnet/runtime/issues/46104")] public readonly ref struct NullableReadOnlyRef<T> { /// <summary> diff --git a/CommunityToolkit.HighPerformance/NullableRef{T}.cs b/CommunityToolkit.HighPerformance/NullableRef{T}.cs index 300e416..e8251e8 100644 --- a/CommunityToolkit.HighPerformance/NullableRef{T}.cs +++ b/CommunityToolkit.HighPerformance/NullableRef{T}.cs @@ -7,6 +7,7 @@ using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Runtime.Versioning; namespace CommunityToolkit.HighPerformance; @@ -14,6 +15,9 @@ namespace CommunityToolkit.HighPerformance; /// A <see langword="struct"/> that can store an optional reference to a value of a specified type. /// </summary> /// <typeparam name="T">The type of value to reference.</typeparam> +[RequiresPreviewFeatures( + "The NullableRef<T> type has no compiler support to ensure the lifetime of referenced values is respected, and as such using it incorrectly may lead to GC holes.", + Url = "https://github.com/dotnet/runtime/issues/46104")] public readonly ref struct NullableRef<T> { /// <summary> diff --git a/CommunityToolkit.HighPerformance/Properties/Polyfills/RequiresPreviewFeaturesAttribute.cs b/CommunityToolkit.HighPerformance/Properties/Polyfills/RequiresPreviewFeaturesAttribute.cs new file mode 100644 index 0000000..103d6f0 --- /dev/null +++ b/CommunityToolkit.HighPerformance/Properties/Polyfills/RequiresPreviewFeaturesAttribute.cs @@ -0,0 +1,55 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#if !NET6_0_OR_GREATER + +namespace System.Runtime.Versioning; + +/// <summary> +/// Indicates that an API is in preview. +/// </summary> +[AttributeUsage( + AttributeTargets.Assembly | + AttributeTargets.Module | + AttributeTargets.Class | + AttributeTargets.Interface | + AttributeTargets.Delegate | + AttributeTargets.Struct | + AttributeTargets.Enum | + AttributeTargets.Constructor | + AttributeTargets.Method | + AttributeTargets.Property | + AttributeTargets.Field | + AttributeTargets.Event, + Inherited = false)] +internal sealed class RequiresPreviewFeaturesAttribute : Attribute +{ + /// <summary> + /// Initializes a new instance of the <seealso cref="RequiresPreviewFeaturesAttribute"/> class. + /// </summary> + public RequiresPreviewFeaturesAttribute() + { + } + + /// <summary> + /// Initializes a new instance of the <seealso cref="RequiresPreviewFeaturesAttribute"/> class with the specified message. + /// </summary> + /// <param name="message">An optional message associated with this attribute instance.</param> + public RequiresPreviewFeaturesAttribute(string? message) + { + Message = message; + } + + /// <summary> + /// Returns the optional message associated with this attribute instance. + /// </summary> + public string? Message { get; } + + /// <summary> + /// Returns the optional URL associated with this attribute instance. + /// </summary> + public string? Url { get; set; } +} + +#endif \ No newline at end of file diff --git a/CommunityToolkit.HighPerformance/ReadOnlyRef{T}.cs b/CommunityToolkit.HighPerformance/ReadOnlyRef{T}.cs index cb40d58..785d4e4 100644 --- a/CommunityToolkit.HighPerformance/ReadOnlyRef{T}.cs +++ b/CommunityToolkit.HighPerformance/ReadOnlyRef{T}.cs @@ -4,6 +4,7 @@ using System; using System.Runtime.CompilerServices; +using System.Runtime.Versioning; #if NETSTANDARD2_1_OR_GREATER using System.Runtime.InteropServices; #else @@ -16,6 +17,9 @@ namespace CommunityToolkit.HighPerformance; /// A <see langword="struct"/> that can store a readonly reference to a value of a specified type. /// </summary> /// <typeparam name="T">The type of value to reference.</typeparam> +[RequiresPreviewFeatures( + "The ReadOnlyRef<T> type has no compiler support to ensure the lifetime of referenced values is respected, and as such using it incorrectly may lead to GC holes.", + Url = "https://github.com/dotnet/runtime/issues/46104")] public readonly ref struct ReadOnlyRef<T> { #if NETSTANDARD2_1_OR_GREATER diff --git a/CommunityToolkit.HighPerformance/Ref{T}.cs b/CommunityToolkit.HighPerformance/Ref{T}.cs index 4f623dd..d0c93cf 100644 --- a/CommunityToolkit.HighPerformance/Ref{T}.cs +++ b/CommunityToolkit.HighPerformance/Ref{T}.cs @@ -4,6 +4,7 @@ using System; using System.Runtime.CompilerServices; +using System.Runtime.Versioning; #if NETSTANDARD2_1_OR_GREATER using System.Runtime.InteropServices; #else @@ -16,6 +17,9 @@ namespace CommunityToolkit.HighPerformance; /// A <see langword="struct"/> that can store a reference to a value of a specified type. /// </summary> /// <typeparam name="T">The type of value to reference.</typeparam> +[RequiresPreviewFeatures( + "The Ref<T> type has no compiler support to ensure the lifetime of referenced values is respected, and as such using it incorrectly may lead to GC holes.", + Url = "https://github.com/dotnet/runtime/issues/46104")] public readonly ref struct Ref<T> { #if NETSTANDARD2_1_OR_GREATER diff --git a/tests/CommunityToolkit.HighPerformance.UnitTests/CommunityToolkit.HighPerformance.UnitTests.csproj b/tests/CommunityToolkit.HighPerformance.UnitTests/CommunityToolkit.HighPerformance.UnitTests.csproj index cf334d2..015efac 100644 --- a/tests/CommunityToolkit.HighPerformance.UnitTests/CommunityToolkit.HighPerformance.UnitTests.csproj +++ b/tests/CommunityToolkit.HighPerformance.UnitTests/CommunityToolkit.HighPerformance.UnitTests.csproj @@ -2,6 +2,7 @@ <PropertyGroup> <TargetFrameworks>net472;netcoreapp3.1;net6.0</TargetFrameworks> + <EnablePreviewFeatures>true</EnablePreviewFeatures> </PropertyGroup> <ItemGroup>