Skip to content

Commit

Permalink
Update design document
Browse files Browse the repository at this point in the history
  • Loading branch information
AaronRobinsonMSFT committed Mar 19, 2024
1 parent 1d2b1ae commit bc3e51c
Showing 1 changed file with 38 additions and 42 deletions.
80 changes: 38 additions & 42 deletions docs/design/features/byreflike-generics.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,37 +28,61 @@ The expansion of ByRefLike types as Generic parameters does not relax restrictio

## API Proposal

Support for the following will be indicated by a new property. For .NET 7, the feature will be marked with `RequiresPreviewFeaturesAttribute` to indicate it is in [preview](https://github.com/dotnet/designs/blob/main/accepted/2021/preview-features/preview-features.md).
A new `GenericParameterAttributes` value will be defined which also represents metadata defined in the `CorGenericParamAttr` enumeration.

```diff
namespace System.Runtime.CompilerServices
namespace System.Reflection
{
public static partial class RuntimeFeature
[Flags]
public enum GenericParameterAttributes
{
+ /// <summary>
+ /// Represents a runtime feature where byref-like types can be used in Generic parameters.
+ /// </summary>
+ public const string GenericsAcceptByRefLike = nameof(GenericsAcceptByRefLike);
+ AcceptByRefLike = 0x0020
}
}
```

The compiler will need an indication for existing troublesome APIs where ByRefLike types will be permissable, but where the failure will be handled at runtime. An attribute will be created and added to these APIs.
```diff
typedef enum CorGenericParamAttr
{
+ gpAcceptByRefLike = 0x0020 // type argument can be ByRefLike
} CorGenericParamAttr;
```

The expansion of metadata will impact at least the following:

- ILDasm/ILAsm/`System.Reflection.Metadata`/`System.Reflection.Emit` &ndash; https://github.com/dotnet/runtime
- Cecil &ndash; https://github.com/jbevain/cecil
- IL Trimmer &ndash; https://github.com/dotnet/runtime/tree/main/src/tools/illink
- F# &ndash; https://github.com/fsharp/fsharp
- C++/CLI &ndash; The MSVC team

### Troublesome API mitigation

If existing types are expected to add ByRefLike support, it is possible they contain previously valid APIs that will become invalid when ByRefLike types are permitted. A potential mitigation for this would be create an attribute to indicate to compilers that specific APIs are validated at run-time not compile-time. What follows is a potential solution.

The compiler will be imbued with knowledge of an API that tells it where ByRefLike types will be permissable and where the failure will be handled by the runtime. The compiler will only respect the attribute that is defined in the same assembly containing `System.Object`.

```csharp
namespace System.Runtime.CompilerServices
{
/// <summary>
/// Indicates to the compiler that constraint checks should be suppressed
/// and will instead be enforced at run-time.
/// Indicates to the compiler the ByRefLike constraint check should be suppressed.
/// </summary>
[AttributeUsage(AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property)]
internal sealed class SuppressConstraintChecksAttribute : Attribute
{ }
/// <remarks>
/// The checking will be suppressed for both the signature and method body. These
/// checks are deferred and will be enforced at run-time.
/// </remarks>
/// <seealso href="https://github.com/dotnet/runtime/issues/99788">Design discussion</seealso>
[AttributeUsage(AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = false)]
internal sealed class SuppressByRefLikeConstraintChecksAttribute : Attribute
{
/// <summary>Initializes the attribute.</summary>
public SuppressByRefLikeConstraintChecksAttribute() { }
}
}
```

Troublesome APIs:
Current examples of APIs that would need the attribute applied:

- [`Span<T>`](https://docs.microsoft.com/dotnet/api/system.span-1)
- `public Span(T[]? array);`
Expand All @@ -73,34 +97,6 @@ Troublesome APIs:
- `public static implicit operator ReadOnlySpan<T>(ArraySegment<T> segment);`
- `public static implicit operator ReadOnlySpan<T>(T[]? array);`

A new `GenericParameterAttributes` value will be defined which also represents metadata defined in the `CorGenericParamAttr` enumeration.

```diff
namespace System.Reflection
{
[Flags]
public enum GenericParameterAttributes
{
+ AcceptByRefLike = 0x0020
}
}
```

```diff
typedef enum CorGenericParamAttr
{
+ gpAcceptByRefLike = 0x0020 // type argument can be ByRefLike
} CorGenericParamAttr;
```

The expansion of metadata will impact at least the following:

- ILDasm/ILAsm/`System.Reflection.Metadata`/`System.Reflection.Emit` &ndash; https://github.com/dotnet/runtime
- Cecil &ndash; https://github.com/jbevain/cecil
- IL Trimmer &ndash; https://github.com/dotnet/runtime/tree/main/src/tools/illink
- F# &ndash; https://github.com/fsharp/fsharp
- C++/CLI &ndash; The MSVC team

## Semantic Proposal

An API that is a JIT-time intrinsic will be needed to determine if a parameter is ByRefLike. This API would represent a check to occur at JIT time to avoid taking paths that would be invalid for some values of `T`. The existing `Type.IsByRefLike` property will be made an intrinsic (e.g., `typeof(T).IsByRefLike`).
Expand Down

0 comments on commit bc3e51c

Please sign in to comment.