Add annotations for ref fields to public API surface (#71265)
authorAaron Robinson <arobins@microsoft.com>
Mon, 27 Jun 2022 16:50:07 +0000 (09:50 -0700)
committerGitHub <noreply@github.com>
Mon, 27 Jun 2022 16:50:07 +0000 (09:50 -0700)
Matching preview 6 changes. Will change when C#11 language support is available.

src/libraries/System.Memory/ref/System.Memory.cs
src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems
src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/LifetimeAnnotationAttribute.cs [new file with mode: 0644]
src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/Unsafe.cs
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/MemoryMarshal.cs
src/libraries/System.Runtime/ref/System.Runtime.cs

index 088efa1..c96b01b 100644 (file)
@@ -530,6 +530,17 @@ namespace System.Buffers.Text
         public static bool TryParse(System.ReadOnlySpan<byte> source, out ulong value, out int bytesConsumed, char standardFormat = '\0') { throw null; }
     }
 }
+namespace System.Runtime.CompilerServices
+{
+    // See src\libraries\System.Private.CoreLib\src\System\Runtime\CompilerServices\LifetimeAnnotationAttribute.cs
+    [System.AttributeUsageAttribute(System.AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
+    internal sealed class LifetimeAnnotationAttribute : System.Attribute
+    {
+        public LifetimeAnnotationAttribute(bool isRefScoped, bool isValueScoped) { throw null; }
+        public bool IsRefScoped { get { throw null; } }
+        public bool IsValueScoped { get { throw null; } }
+    }
+}
 namespace System.Runtime.InteropServices
 {
     public static partial class MemoryMarshal
@@ -542,16 +553,16 @@ namespace System.Runtime.InteropServices
         public static System.ReadOnlySpan<TTo> Cast<TFrom, TTo>(System.ReadOnlySpan<TFrom> span) where TFrom : struct where TTo : struct { throw null; }
         public static System.Span<TTo> Cast<TFrom, TTo>(System.Span<TFrom> span) where TFrom : struct where TTo : struct { throw null; }
         public static System.Memory<T> CreateFromPinnedArray<T>(T[]? array, int start, int length) { throw null; }
-        public static System.ReadOnlySpan<T> CreateReadOnlySpan<T>(ref T reference, int length) { throw null; }
+        public static System.ReadOnlySpan<T> CreateReadOnlySpan<T>([System.Runtime.CompilerServices.LifetimeAnnotation(true, false)] ref T reference, int length) { throw null; }
         [System.CLSCompliant(false)]
         public static unsafe ReadOnlySpan<byte> CreateReadOnlySpanFromNullTerminated(byte* value) { throw null; }
         [System.CLSCompliant(false)]
         public static unsafe ReadOnlySpan<char> CreateReadOnlySpanFromNullTerminated(char* value) { throw null; }
-        public static System.Span<T> CreateSpan<T>(ref T reference, int length) { throw null; }
+        public static System.Span<T> CreateSpan<T>([System.Runtime.CompilerServices.LifetimeAnnotation(true, false)] ref T reference, int length) { throw null; }
         public static ref T GetArrayDataReference<T>(T[] array) { throw null; }
         public static ref byte GetArrayDataReference(System.Array array) { throw null; }
-        public static ref T GetReference<T>(System.ReadOnlySpan<T> span) { throw null; }
-        public static ref T GetReference<T>(System.Span<T> span) { throw null; }
+        public static ref T GetReference<T>([System.Runtime.CompilerServices.LifetimeAnnotation(false, true)] System.ReadOnlySpan<T> span) { throw null; }
+        public static ref T GetReference<T>([System.Runtime.CompilerServices.LifetimeAnnotation(false, true)] System.Span<T> span) { throw null; }
         public static T Read<T>(System.ReadOnlySpan<byte> source) where T : struct { throw null; }
         public static System.Collections.Generic.IEnumerable<T> ToEnumerable<T>(System.ReadOnlyMemory<T> memory) { throw null; }
         public static bool TryGetArray<T>(System.ReadOnlyMemory<T> memory, out System.ArraySegment<T> segment) { throw null; }
index a079ceb..93eab8c 100644 (file)
     <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\DefaultInterpolatedStringHandler.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\IteratorStateMachineAttribute.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\ITuple.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\LifetimeAnnotationAttribute.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\LoadHint.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\MethodCodeType.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\MethodImplAttribute.cs" />
diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/LifetimeAnnotationAttribute.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/LifetimeAnnotationAttribute.cs
new file mode 100644 (file)
index 0000000..f792a7a
--- /dev/null
@@ -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.
+
+using System;
+
+namespace System.Runtime.CompilerServices
+{
+    /// <summary>
+    /// This type is defined until we consume the C# 11 compiler.
+    /// </summary>
+    /// <remarks>
+    /// Also remove in the reference assemblies.
+    /// </remarks>
+    [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
+    internal sealed class LifetimeAnnotationAttribute : Attribute
+    {
+        public LifetimeAnnotationAttribute(bool isRefScoped, bool isValueScoped)
+        {
+            IsRefScoped = isRefScoped;
+            IsValueScoped = isValueScoped;
+        }
+        public bool IsRefScoped { get; }
+        public bool IsValueScoped { get; }
+    }
+}
index 2c17b9f..d006bd5 100644 (file)
@@ -671,7 +671,7 @@ namespace System.Runtime.CompilerServices
         // Mono:AsRef
         [NonVersionable]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public static ref T AsRef<T>(in T source)
+        public static ref T AsRef<T>([LifetimeAnnotation(true, false)] in T source)
         {
             throw new PlatformNotSupportedException();
 
index c0c2bf3..f089434 100644 (file)
@@ -77,13 +77,13 @@ namespace System.Runtime.InteropServices
         /// 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
         /// would have been stored. Such a reference may or may not be null. It can be used for pinning but must never be dereferenced.
         /// </summary>
-        public static ref T GetReference<T>(Span<T> span) => ref span._reference.Value;
+        public static ref T GetReference<T>([LifetimeAnnotation(false, true)] Span<T> span) => ref span._reference.Value;
 
         /// <summary>
         /// 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
         /// would have been stored. Such a reference may or may not be null. It can be used for pinning but must never be dereferenced.
         /// </summary>
-        public static ref T GetReference<T>(ReadOnlySpan<T> span) => ref span._reference.Value;
+        public static ref T GetReference<T>([LifetimeAnnotation(false, true)] ReadOnlySpan<T> span) => ref span._reference.Value;
 
         /// <summary>
         /// 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 @@ namespace System.Runtime.InteropServices
         /// <returns>A span representing the specified reference and length.</returns>
         /// <remarks>The lifetime of the returned span will not be validated for safety by span-aware languages.</remarks>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public static Span<T> CreateSpan<T>(ref T reference, int length) => new Span<T>(ref reference, length);
+        public static Span<T> CreateSpan<T>([LifetimeAnnotation(true, false)] ref T reference, int length) => new Span<T>(ref reference, length);
 
         /// <summary>
         /// Creates a new read-only span over a portion of a regular managed object. This can be useful
@@ -231,7 +231,7 @@ namespace System.Runtime.InteropServices
         /// <returns>A read-only span representing the specified reference and length.</returns>
         /// <remarks>The lifetime of the returned span will not be validated for safety by span-aware languages.</remarks>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public static ReadOnlySpan<T> CreateReadOnlySpan<T>(ref T reference, int length) => new ReadOnlySpan<T>(ref reference, length);
+        public static ReadOnlySpan<T> CreateReadOnlySpan<T>([LifetimeAnnotation(true, false)] ref T reference, int length) => new ReadOnlySpan<T>(ref reference, length);
 
         /// <summary>Creates a new read-only span for a null-terminated string.</summary>
         /// <param name="value">The pointer to the null-terminated string of characters.</param>
index 27ab632..34a334d 100644 (file)
@@ -12523,6 +12523,14 @@ namespace System.Runtime.CompilerServices
         object? this[int index] { get; }
         int Length { get; }
     }
+    // See src\libraries\System.Private.CoreLib\src\System\Runtime\CompilerServices\LifetimeAnnotationAttribute.cs
+    [System.AttributeUsageAttribute(System.AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
+    internal sealed class LifetimeAnnotationAttribute : System.Attribute
+    {
+        public LifetimeAnnotationAttribute(bool isRefScoped, bool isValueScoped) { throw null; }
+        public bool IsRefScoped { get { throw null; } }
+        public bool IsValueScoped { get { throw null; } }
+    }
     public enum LoadHint
     {
         Default = 0,
@@ -12766,7 +12774,7 @@ namespace System.Runtime.CompilerServices
         public unsafe static void* AsPointer<T>(ref T value) { throw null; }
         [System.CLSCompliantAttribute(false)]
         public unsafe static ref T AsRef<T>(void* source) { throw null; }
-        public static ref T AsRef<T>(in T source) { throw null; }
+        public static ref T AsRef<T>([System.Runtime.CompilerServices.LifetimeAnnotation(true, false)] in T source) { throw null; }
         [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("o")]
         public static T? As<T>(object? o) where T : class? { throw null; }
         public static ref TTo As<TFrom, TTo>(ref TFrom source) { throw null; }