Skip to content

Commit d3fa592

Browse files
Add annotations for ref fields to public API surface (#71266)
Co-authored-by: Aaron Robinson <[email protected]>
1 parent e45c708 commit d3fa592

File tree

6 files changed

+55
-10
lines changed

6 files changed

+55
-10
lines changed

src/libraries/System.Memory/ref/System.Memory.cs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -530,6 +530,17 @@ public static partial class Utf8Parser
530530
public static bool TryParse(System.ReadOnlySpan<byte> source, out ulong value, out int bytesConsumed, char standardFormat = '\0') { throw null; }
531531
}
532532
}
533+
namespace System.Runtime.CompilerServices
534+
{
535+
// See src\libraries\System.Private.CoreLib\src\System\Runtime\CompilerServices\LifetimeAnnotationAttribute.cs
536+
[System.AttributeUsageAttribute(System.AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
537+
internal sealed class LifetimeAnnotationAttribute : System.Attribute
538+
{
539+
public LifetimeAnnotationAttribute(bool isRefScoped, bool isValueScoped) { throw null; }
540+
public bool IsRefScoped { get { throw null; } }
541+
public bool IsValueScoped { get { throw null; } }
542+
}
543+
}
533544
namespace System.Runtime.InteropServices
534545
{
535546
public static partial class MemoryMarshal
@@ -542,16 +553,16 @@ public static partial class MemoryMarshal
542553
public static System.ReadOnlySpan<TTo> Cast<TFrom, TTo>(System.ReadOnlySpan<TFrom> span) where TFrom : struct where TTo : struct { throw null; }
543554
public static System.Span<TTo> Cast<TFrom, TTo>(System.Span<TFrom> span) where TFrom : struct where TTo : struct { throw null; }
544555
public static System.Memory<T> CreateFromPinnedArray<T>(T[]? array, int start, int length) { throw null; }
545-
public static System.ReadOnlySpan<T> CreateReadOnlySpan<T>(ref T reference, int length) { throw null; }
556+
public static System.ReadOnlySpan<T> CreateReadOnlySpan<T>([System.Runtime.CompilerServices.LifetimeAnnotation(true, false)] ref T reference, int length) { throw null; }
546557
[System.CLSCompliant(false)]
547558
public static unsafe ReadOnlySpan<byte> CreateReadOnlySpanFromNullTerminated(byte* value) { throw null; }
548559
[System.CLSCompliant(false)]
549560
public static unsafe ReadOnlySpan<char> CreateReadOnlySpanFromNullTerminated(char* value) { throw null; }
550-
public static System.Span<T> CreateSpan<T>(ref T reference, int length) { throw null; }
561+
public static System.Span<T> CreateSpan<T>([System.Runtime.CompilerServices.LifetimeAnnotation(true, false)] ref T reference, int length) { throw null; }
551562
public static ref T GetArrayDataReference<T>(T[] array) { throw null; }
552563
public static ref byte GetArrayDataReference(System.Array array) { throw null; }
553-
public static ref T GetReference<T>(System.ReadOnlySpan<T> span) { throw null; }
554-
public static ref T GetReference<T>(System.Span<T> span) { throw null; }
564+
public static ref T GetReference<T>([System.Runtime.CompilerServices.LifetimeAnnotation(false, true)] System.ReadOnlySpan<T> span) { throw null; }
565+
public static ref T GetReference<T>([System.Runtime.CompilerServices.LifetimeAnnotation(false, true)] System.Span<T> span) { throw null; }
555566
public static T Read<T>(System.ReadOnlySpan<byte> source) where T : struct { throw null; }
556567
public static System.Collections.Generic.IEnumerable<T> ToEnumerable<T>(System.ReadOnlyMemory<T> memory) { throw null; }
557568
public static bool TryGetArray<T>(System.ReadOnlyMemory<T> memory, out System.ArraySegment<T> segment) { throw null; }

src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -758,6 +758,7 @@
758758
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\DefaultInterpolatedStringHandler.cs" />
759759
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\IteratorStateMachineAttribute.cs" />
760760
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\ITuple.cs" />
761+
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\LifetimeAnnotationAttribute.cs" />
761762
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\LoadHint.cs" />
762763
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\MethodCodeType.cs" />
763764
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\MethodImplAttribute.cs" />
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
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+
4+
using System;
5+
6+
namespace System.Runtime.CompilerServices
7+
{
8+
/// <summary>
9+
/// This type is defined until we consume the C# 11 compiler.
10+
/// </summary>
11+
/// <remarks>
12+
/// Also remove in the reference assemblies.
13+
/// </remarks>
14+
[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
15+
internal sealed class LifetimeAnnotationAttribute : Attribute
16+
{
17+
public LifetimeAnnotationAttribute(bool isRefScoped, bool isValueScoped)
18+
{
19+
IsRefScoped = isRefScoped;
20+
IsValueScoped = isValueScoped;
21+
}
22+
public bool IsRefScoped { get; }
23+
public bool IsValueScoped { get; }
24+
}
25+
}

src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/Unsafe.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -671,7 +671,7 @@ public static ref T AsRef<T>(void* source)
671671
// Mono:AsRef
672672
[NonVersionable]
673673
[MethodImpl(MethodImplOptions.AggressiveInlining)]
674-
public static ref T AsRef<T>(in T source)
674+
public static ref T AsRef<T>([LifetimeAnnotation(true, false)] in T source)
675675
{
676676
throw new PlatformNotSupportedException();
677677

src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/MemoryMarshal.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,13 +77,13 @@ public static Memory<T> AsMemory<T>(ReadOnlyMemory<T> memory) =>
7777
/// Returns a reference to the 0th element of the Span. If the Span is empty, returns a reference to the location where the 0th element
7878
/// would have been stored. Such a reference may or may not be null. It can be used for pinning but must never be dereferenced.
7979
/// </summary>
80-
public static ref T GetReference<T>(Span<T> span) => ref span._reference.Value;
80+
public static ref T GetReference<T>([LifetimeAnnotation(false, true)] Span<T> span) => ref span._reference.Value;
8181

8282
/// <summary>
8383
/// Returns a reference to the 0th element of the ReadOnlySpan. If the ReadOnlySpan is empty, returns a reference to the location where the 0th element
8484
/// would have been stored. Such a reference may or may not be null. It can be used for pinning but must never be dereferenced.
8585
/// </summary>
86-
public static ref T GetReference<T>(ReadOnlySpan<T> span) => ref span._reference.Value;
86+
public static ref T GetReference<T>([LifetimeAnnotation(false, true)] ReadOnlySpan<T> span) => ref span._reference.Value;
8787

8888
/// <summary>
8989
/// Returns a reference to the 0th element of the Span. If the Span is empty, returns a reference to fake non-null pointer. Such a reference can be used
@@ -219,7 +219,7 @@ ref Unsafe.As<TFrom, TTo>(ref MemoryMarshal.GetReference(span)),
219219
/// <returns>A span representing the specified reference and length.</returns>
220220
/// <remarks>The lifetime of the returned span will not be validated for safety by span-aware languages.</remarks>
221221
[MethodImpl(MethodImplOptions.AggressiveInlining)]
222-
public static Span<T> CreateSpan<T>(ref T reference, int length) => new Span<T>(ref reference, length);
222+
public static Span<T> CreateSpan<T>([LifetimeAnnotation(true, false)] ref T reference, int length) => new Span<T>(ref reference, length);
223223

224224
/// <summary>
225225
/// Creates a new read-only span over a portion of a regular managed object. This can be useful
@@ -231,7 +231,7 @@ ref Unsafe.As<TFrom, TTo>(ref MemoryMarshal.GetReference(span)),
231231
/// <returns>A read-only span representing the specified reference and length.</returns>
232232
/// <remarks>The lifetime of the returned span will not be validated for safety by span-aware languages.</remarks>
233233
[MethodImpl(MethodImplOptions.AggressiveInlining)]
234-
public static ReadOnlySpan<T> CreateReadOnlySpan<T>(ref T reference, int length) => new ReadOnlySpan<T>(ref reference, length);
234+
public static ReadOnlySpan<T> CreateReadOnlySpan<T>([LifetimeAnnotation(true, false)] ref T reference, int length) => new ReadOnlySpan<T>(ref reference, length);
235235

236236
/// <summary>Creates a new read-only span for a null-terminated string.</summary>
237237
/// <param name="value">The pointer to the null-terminated string of characters.</param>

src/libraries/System.Runtime/ref/System.Runtime.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12523,6 +12523,14 @@ public partial interface ITuple
1252312523
object? this[int index] { get; }
1252412524
int Length { get; }
1252512525
}
12526+
// See src\libraries\System.Private.CoreLib\src\System\Runtime\CompilerServices\LifetimeAnnotationAttribute.cs
12527+
[System.AttributeUsageAttribute(System.AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
12528+
internal sealed class LifetimeAnnotationAttribute : System.Attribute
12529+
{
12530+
public LifetimeAnnotationAttribute(bool isRefScoped, bool isValueScoped) { throw null; }
12531+
public bool IsRefScoped { get { throw null; } }
12532+
public bool IsValueScoped { get { throw null; } }
12533+
}
1252612534
public enum LoadHint
1252712535
{
1252812536
Default = 0,
@@ -12766,7 +12774,7 @@ public static partial class Unsafe
1276612774
public unsafe static void* AsPointer<T>(ref T value) { throw null; }
1276712775
[System.CLSCompliantAttribute(false)]
1276812776
public unsafe static ref T AsRef<T>(void* source) { throw null; }
12769-
public static ref T AsRef<T>(in T source) { throw null; }
12777+
public static ref T AsRef<T>([System.Runtime.CompilerServices.LifetimeAnnotation(true, false)] in T source) { throw null; }
1277012778
[return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("o")]
1277112779
public static T? As<T>(object? o) where T : class? { throw null; }
1277212780
public static ref TTo As<TFrom, TTo>(ref TFrom source) { throw null; }

0 commit comments

Comments
 (0)