Skip to content

[API Proposal] Mark Unsafe as caller-unsafe #126956

@EgorBo

Description

@EgorBo

Background and motivation

This proposal lists the APIs in System.Runtime.CompilerServices.Unsafe and marks them as caller-unsafe. I'm using a diff format where + indicates that it's now caller-unsafe and - indicates the unsafe modifier has been removed (a non-breaking change).

If you are happy with this format, I'll create further proposals, likely grouped by namespace.

API Proposal

public static partial class Unsafe
{
+   public static unsafe ref T AddByteOffset<T>(ref T source, System.IntPtr byteOffset) where T : allows ref struct { throw null; }
+   public static unsafe ref T AddByteOffset<T>(ref T source, nuint byteOffset) where T : allows ref struct { throw null; }
+   public static unsafe ref T Add<T>(ref T source, int elementOffset) where T : allows ref struct { throw null; }
+   public static unsafe ref T Add<T>(ref T source, System.IntPtr elementOffset) where T : allows ref struct { throw null; }
+   public static unsafe ref T Add<T>(ref T source, nuint elementOffset) where T : allows ref struct { throw null; }
    public static bool AreSame<T>([System.Diagnostics.CodeAnalysis.AllowNull] ref readonly T left, [System.Diagnostics.CodeAnalysis.AllowNull] ref readonly T right) where T : allows ref struct { throw null; }
+   public static unsafe ref T AsRef<T>(scoped ref readonly T source) where T : allows ref struct { throw null; }
+   public static unsafe T? As<T>(object? o) where T : class? { throw null; }
+   public static unsafe ref TTo As<TFrom, TTo>(ref TFrom source) where TFrom : allows ref struct where TTo : allows ref struct { throw null; }
+   public static unsafe TTo BitCast<TFrom, TTo>(TFrom source) where TFrom : allows ref struct where TTo : allows ref struct { throw null; }
    public static System.IntPtr ByteOffset<T>([System.Diagnostics.CodeAnalysis.AllowNull] ref readonly T origin, [System.Diagnostics.CodeAnalysis.AllowNull] ref readonly T target) where T : allows ref struct { throw null; }
+   public static unsafe void CopyBlock(ref byte destination, ref readonly byte source, uint byteCount) { }
+   public static unsafe void CopyBlockUnaligned(ref byte destination, ref readonly byte source, uint byteCount) { }
+   public static unsafe void InitBlock(ref byte startAddress, byte value, uint byteCount) { }
+   public static unsafe void InitBlockUnaligned(ref byte startAddress, byte value, uint byteCount) { }
    public static bool IsAddressGreaterThan<T>([System.Diagnostics.CodeAnalysis.AllowNull] ref readonly T left, [System.Diagnostics.CodeAnalysis.AllowNull] ref readonly T right) where T : allows ref struct { throw null; }
    public static bool IsAddressGreaterThanOrEqualTo<T>([System.Diagnostics.CodeAnalysis.AllowNull] ref readonly T left, [System.Diagnostics.CodeAnalysis.AllowNull] ref readonly T right) where T : allows ref struct { throw null; }
    public static bool IsAddressLessThan<T>([System.Diagnostics.CodeAnalysis.AllowNull] ref readonly T left, [System.Diagnostics.CodeAnalysis.AllowNull] ref readonly T right) where T : allows ref struct { throw null; }
    public static bool IsAddressLessThanOrEqualTo<T>([System.Diagnostics.CodeAnalysis.AllowNull] ref readonly T left, [System.Diagnostics.CodeAnalysis.AllowNull] ref readonly T right) where T : allows ref struct { throw null; }
    public static bool IsNullRef<T>(ref readonly T source) where T : allows ref struct { throw null; }
    public static ref T NullRef<T>() where T : allows ref struct { throw null; }
+   public static unsafe T ReadUnaligned<T>(scoped ref readonly byte source) where T : allows ref struct { throw null; }
    public static int SizeOf<T>() where T : allows ref struct { throw null; }
+   public static unsafe void SkipInit<T>(out T value) where T : allows ref struct { throw null; }
+   public static unsafe ref T SubtractByteOffset<T>(ref T source, System.IntPtr byteOffset) where T : allows ref struct { throw null; }
+   public static unsafe ref T SubtractByteOffset<T>(ref T source, nuint byteOffset) where T : allows ref struct { throw null; }
+   public static unsafe ref T Subtract<T>(ref T source, int elementOffset) where T : allows ref struct { throw null; }
+   public static unsafe ref T Subtract<T>(ref T source, System.IntPtr elementOffset) where T : allows ref struct { throw null; }
+   public static unsafe ref T Subtract<T>(ref T source, nuint elementOffset) where T : allows ref struct { throw null; }
+   public static unsafe ref T Unbox<T>(object box) where T : struct { throw null; }
+   public static unsafe void WriteUnaligned<T>(ref byte destination, T value) where T : allows ref struct { }
    
    // APIs with unmanaged pointers in the signature.
-   public static void* Add<T>(void* source, int elementOffset) where T : allows ref struct { throw null; }
-   public static void* AsPointer<T>(ref readonly T value) where T : allows ref struct { throw null; }
    public unsafe static ref T AsRef<T>(void* source) where T : allows ref struct { throw null; }
    public unsafe static void CopyBlock(void* destination, void* source, uint byteCount) { }
    public unsafe static void CopyBlockUnaligned(void* destination, void* source, uint byteCount) { }
    public unsafe static void Copy<T>(void* destination, ref readonly T source) where T : allows ref struct { }
    public unsafe static void Copy<T>(ref T destination, void* source) where T : allows ref struct { }
    public unsafe static void InitBlock(void* startAddress, byte value, uint byteCount) { }
    public unsafe static void InitBlockUnaligned(void* startAddress, byte value, uint byteCount) { }
    public unsafe static T ReadUnaligned<T>(void* source) where T : allows ref struct { throw null; }
    public unsafe static T Read<T>(void* source) where T : allows ref struct { throw null; }
-   public static void* Subtract<T>(void* source, int elementOffset) where T : allows ref struct { throw null; }
    public unsafe static void WriteUnaligned<T>(void* destination, T value) where T : allows ref struct { }
    public unsafe static void Write<T>(void* destination, T value) where T : allows ref struct { }
}

API Usage

The annotated APIs will require unsafe{} context at their call site.

Alternative Designs

No response

Risks

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions