Skip to content

Commit f8ca8da

Browse files
committed
Add [RequiresPreviewFeatures] to unsafe APIs
1 parent 6f20b26 commit f8ca8da

File tree

7 files changed

+79
-0
lines changed

7 files changed

+79
-0
lines changed

CommunityToolkit.HighPerformance/Extensions/SpinLockExtensions.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
using System.ComponentModel;
66
using System.Runtime.CompilerServices;
7+
using System.Runtime.Versioning;
78
using System.Threading;
89

910
namespace CommunityToolkit.HighPerformance;
@@ -94,6 +95,9 @@ public void Dispose()
9495
/// <param name="spinLock">The target <see cref="SpinLock"/> to use</param>
9596
/// <returns>A wrapper type that will release <paramref name="spinLock"/> when its <see cref="System.IDisposable.Dispose"/> method is called.</returns>
9697
/// <remarks>The returned <see cref="Lock"/> value shouldn't be used directly: use this extension in a <see langword="using"/> block or statement.</remarks>
98+
[RequiresPreviewFeatures(
99+
"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.",
100+
Url = "https://github.com/dotnet/runtime/issues/46104")]
97101
[MethodImpl(MethodImplOptions.AggressiveInlining)]
98102
public static Lock Enter(ref this SpinLock spinLock)
99103
{
@@ -131,6 +135,9 @@ public static Lock Enter(object owner, ref SpinLock spinLock)
131135
/// A <see langword="struct"/> that is used to enter and hold a <see cref="SpinLock"/> through a <see langword="using"/> block or statement.
132136
/// </summary>
133137
[EditorBrowsable(EditorBrowsableState.Never)]
138+
[RequiresPreviewFeatures(
139+
"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.",
140+
Url = "https://github.com/dotnet/runtime/issues/46104")]
134141
public readonly ref struct Lock
135142
{
136143
/// <summary>

CommunityToolkit.HighPerformance/NullableReadOnlyRef{T}.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,17 @@
77
using System;
88
using System.Runtime.CompilerServices;
99
using System.Runtime.InteropServices;
10+
using System.Runtime.Versioning;
1011

1112
namespace CommunityToolkit.HighPerformance;
1213

1314
/// <summary>
1415
/// A <see langword="struct"/> that can store an optional readonly reference to a value of a specified type.
1516
/// </summary>
1617
/// <typeparam name="T">The type of value to reference.</typeparam>
18+
[RequiresPreviewFeatures(
19+
"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.",
20+
Url = "https://github.com/dotnet/runtime/issues/46104")]
1721
public readonly ref struct NullableReadOnlyRef<T>
1822
{
1923
/// <summary>

CommunityToolkit.HighPerformance/NullableRef{T}.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,17 @@
77
using System;
88
using System.Runtime.CompilerServices;
99
using System.Runtime.InteropServices;
10+
using System.Runtime.Versioning;
1011

1112
namespace CommunityToolkit.HighPerformance;
1213

1314
/// <summary>
1415
/// A <see langword="struct"/> that can store an optional reference to a value of a specified type.
1516
/// </summary>
1617
/// <typeparam name="T">The type of value to reference.</typeparam>
18+
[RequiresPreviewFeatures(
19+
"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.",
20+
Url = "https://github.com/dotnet/runtime/issues/46104")]
1721
public readonly ref struct NullableRef<T>
1822
{
1923
/// <summary>
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
#if !NET6_0_OR_GREATER
6+
7+
namespace System.Runtime.Versioning;
8+
9+
/// <summary>
10+
/// Indicates that an API is in preview.
11+
/// </summary>
12+
[AttributeUsage(
13+
AttributeTargets.Assembly |
14+
AttributeTargets.Module |
15+
AttributeTargets.Class |
16+
AttributeTargets.Interface |
17+
AttributeTargets.Delegate |
18+
AttributeTargets.Struct |
19+
AttributeTargets.Enum |
20+
AttributeTargets.Constructor |
21+
AttributeTargets.Method |
22+
AttributeTargets.Property |
23+
AttributeTargets.Field |
24+
AttributeTargets.Event,
25+
Inherited = false)]
26+
internal sealed class RequiresPreviewFeaturesAttribute : Attribute
27+
{
28+
/// <summary>
29+
/// Initializes a new instance of the <seealso cref="RequiresPreviewFeaturesAttribute"/> class.
30+
/// </summary>
31+
public RequiresPreviewFeaturesAttribute()
32+
{
33+
}
34+
35+
/// <summary>
36+
/// Initializes a new instance of the <seealso cref="RequiresPreviewFeaturesAttribute"/> class with the specified message.
37+
/// </summary>
38+
/// <param name="message">An optional message associated with this attribute instance.</param>
39+
public RequiresPreviewFeaturesAttribute(string? message)
40+
{
41+
Message = message;
42+
}
43+
44+
/// <summary>
45+
/// Returns the optional message associated with this attribute instance.
46+
/// </summary>
47+
public string? Message { get; }
48+
49+
/// <summary>
50+
/// Returns the optional URL associated with this attribute instance.
51+
/// </summary>
52+
public string? Url { get; set; }
53+
}
54+
55+
#endif

CommunityToolkit.HighPerformance/ReadOnlyRef{T}.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
using System;
66
using System.Runtime.CompilerServices;
7+
using System.Runtime.Versioning;
78
#if NETSTANDARD2_1_OR_GREATER
89
using System.Runtime.InteropServices;
910
#else
@@ -16,6 +17,9 @@ namespace CommunityToolkit.HighPerformance;
1617
/// A <see langword="struct"/> that can store a readonly reference to a value of a specified type.
1718
/// </summary>
1819
/// <typeparam name="T">The type of value to reference.</typeparam>
20+
[RequiresPreviewFeatures(
21+
"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.",
22+
Url = "https://github.com/dotnet/runtime/issues/46104")]
1923
public readonly ref struct ReadOnlyRef<T>
2024
{
2125
#if NETSTANDARD2_1_OR_GREATER

CommunityToolkit.HighPerformance/Ref{T}.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
using System;
66
using System.Runtime.CompilerServices;
7+
using System.Runtime.Versioning;
78
#if NETSTANDARD2_1_OR_GREATER
89
using System.Runtime.InteropServices;
910
#else
@@ -16,6 +17,9 @@ namespace CommunityToolkit.HighPerformance;
1617
/// A <see langword="struct"/> that can store a reference to a value of a specified type.
1718
/// </summary>
1819
/// <typeparam name="T">The type of value to reference.</typeparam>
20+
[RequiresPreviewFeatures(
21+
"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.",
22+
Url = "https://github.com/dotnet/runtime/issues/46104")]
1923
public readonly ref struct Ref<T>
2024
{
2125
#if NETSTANDARD2_1_OR_GREATER

tests/CommunityToolkit.HighPerformance.UnitTests/CommunityToolkit.HighPerformance.UnitTests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
<PropertyGroup>
44
<TargetFrameworks>net472;netcoreapp3.1;net6.0</TargetFrameworks>
5+
<EnablePreviewFeatures>true</EnablePreviewFeatures>
56
</PropertyGroup>
67

78
<ItemGroup>

0 commit comments

Comments
 (0)