Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update docs for ByRefLike with generics for work in .NET 10 #103318

Merged
merged 33 commits into from
Jul 25, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
711bb86
Update docs for byreflike with generics
AaronRobinsonMSFT Jun 11, 2024
997df5c
Apply suggestions from code review
AaronRobinsonMSFT Jun 11, 2024
d51a810
Apply suggestions from code review
AaronRobinsonMSFT Jun 11, 2024
77fd682
Feedback.
AaronRobinsonMSFT Jun 12, 2024
afd39c6
Offline feedback.
AaronRobinsonMSFT Jun 13, 2024
234889a
Add additional tests based on feedback.
AaronRobinsonMSFT Jun 13, 2024
111f4da
Add check at run-time to CoreCLR and native AOT.
AaronRobinsonMSFT Jun 16, 2024
04a31c3
New JIT helper mean rev'ing JIT interface ID.
AaronRobinsonMSFT Jun 16, 2024
85341b9
Merge remote-tracking branch 'upstream/main' into update_ecma335
AaronRobinsonMSFT Jun 16, 2024
7f01e29
Update JIT interface GUID for new JIT helper.
AaronRobinsonMSFT Jun 16, 2024
a1e62e9
Apply JIT format
AaronRobinsonMSFT Jun 16, 2024
ebf31d3
Feedback on rename
AaronRobinsonMSFT Jun 16, 2024
0d848ce
Merge remote-tracking branch 'upstream/main' into update_ecma335
AaronRobinsonMSFT Jun 16, 2024
2a4b2c6
Update JIT interface ID
AaronRobinsonMSFT Jun 16, 2024
f21b33b
Merge remote-tracking branch 'upstream/main' into update_ecma335
AaronRobinsonMSFT Jun 17, 2024
fcf32a7
Review feedback.
AaronRobinsonMSFT Jun 17, 2024
634c207
Update spec.
AaronRobinsonMSFT Jun 17, 2024
65e6c87
Updates
AaronRobinsonMSFT Jun 21, 2024
3eccef8
Updates
AaronRobinsonMSFT Jun 24, 2024
c43cddd
Updates
AaronRobinsonMSFT Jun 29, 2024
391c7f6
Updates
AaronRobinsonMSFT Jul 1, 2024
84141d5
Feedback
AaronRobinsonMSFT Jul 8, 2024
879733a
Update docs/design/features/byreflike-generics.md
AaronRobinsonMSFT Jul 9, 2024
e01d457
Update tests
AaronRobinsonMSFT Jul 10, 2024
077ba31
Merge remote-tracking branch 'upstream/main' into update_ecma335
AaronRobinsonMSFT Jul 10, 2024
6c8daf2
Remove the statement of "undefined behavior".
AaronRobinsonMSFT Jul 12, 2024
0e9691a
Merge remote-tracking branch 'upstream/main' into update_ecma335
AaronRobinsonMSFT Jul 16, 2024
20dda62
Updates
AaronRobinsonMSFT Jul 16, 2024
be202d9
Updates
AaronRobinsonMSFT Jul 17, 2024
cc78df4
Apply suggestions from code review
AaronRobinsonMSFT Jul 24, 2024
3472ff9
Update docs/design/features/byreflike-generics.md
AaronRobinsonMSFT Jul 24, 2024
6936b11
Feedback.
AaronRobinsonMSFT Jul 24, 2024
90dfc5f
Updates
AaronRobinsonMSFT Jul 25, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 9 additions & 7 deletions docs/design/features/byreflike-generics.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ Supporting ByRefLike type as Generic parameters will impact the following IL ins
- `stsfld` / `ldsfld` – Type fields of a ByRefLike parameter cannot be marked `static`.
- `newarr` / `stelem` / `ldelem` / `ldelema` – Arrays are not able to contain ByRefLike types.
- `newobj` – For multi-dimensional array construction.
- `constrained.callvirt` – If this IL sequence resolves to a method implemented on `object` or default interface method, an error will occur during the attempt to box the instance.
- `constrained.callvirt` – When applied to a ByRefLike instance, if this IL sequence resolves to a method implemented on `object` or a default interface method, an error will occur during the attempt to box the ByRefLike instance.
AaronRobinsonMSFT marked this conversation as resolved.
Show resolved Hide resolved

If any of the above instructions are attempted to be used with a ByRefLike type, the runtime will throw an `InvalidProgramException`. Sequences involving some of the above instructions are considered optimizations and represent cases that will remain valid regardless of a `T` being ByRefLike. See "Special IL Sequences" section below for details.
If any of the above instructions are attempted to be used with a ByRefLike type, the runtime will throw an `InvalidProgramException`.
AaronRobinsonMSFT marked this conversation as resolved.
Show resolved Hide resolved

The following instructions are already set up to support this feature since their behavior will fail as currently defined due to the inability to box a ByRefLike type.

Expand All @@ -24,6 +24,8 @@ The following instructions are already set up to support this feature since thei
- `isinst` – Will always place `null` on stack.
- `castclass` – Will always throw `InvalidCastException`.

**NOTE** There are sequences involving some of the above instructions that will remain valid regardless of a `T` being ByRefLike—see ["Special IL Sequences" section](#special_il_sequences) below for details.

The expansion of ByRefLike types as Generic parameters does not relax restrictions on where ByRefLike types can be used. When `T` is ByRefLike, the use of `T` as a field will require the enclosing type to be ByRefLike.

## API Proposal
Expand Down Expand Up @@ -112,21 +114,21 @@ Adding `gpAcceptByRefLike` to the metadata of a Generic parameter will be consid

Enumerating of constructors/methods on `Span<T>` and `ReadOnlySpan<T>` may throw `TypeLoadException` if `T` is a ByRefLike type. See "Troublesome APIs" above for the list of APIs that cause this condition.

## Special IL Sequences
## <a name="special_il_sequences"></a> Special IL Sequences

The following are IL sequences involving the `box` instruction. They are used for common C# language constructs and shall continue to be valid, even with ByRefLike types, in cases where the result can be computed at JIT time and elided safely. These sequences must now be elided when the target type is ByRefLike. The conditions where each sequence is elided are described below and each condition will be added to the ECMA-335 addendum.
The following are IL sequences involving the `box` instruction. They are used for common C# language constructs and shall continue to be valid, even with ByRefLike types, in cases where the result can be computed at JIT compile time or interpretation and elided safely. These sequences **must** now be elided when the target type is ByRefLike. The conditions where each sequence is elided are described below and each condition will be added to the ECMA-335 addendum.

`box` ; `unbox.any` &ndash; The box target type is equal to the unboxed target type.

`box` ; `br_true/false` &ndash; The box target type is non-`Nullable<T>`.

`box` ; `isinst` ; `unbox.any` &ndash; The box, `isint`, and unbox target types are all equal.
`box` ; `isinst` ; `unbox.any` &ndash; The box, `isinst`, and unbox target types are all equal.

`box` ; `isinst` ; `br_true/false` &ndash; The box target type is equal to the unboxed target type or the box target type is `Nullable<T>` and target type equalities can be computed.
`box` ; `isinst` ; `br_true/false` &ndash; The box target type is ByRefLike or the box target type is `Nullable<T>` and target type equalities can be computed.

## Examples

Below are valid and invalid examples of ByRefLike as Generic parameters. All examples use the **not official** syntax, `allows ref struct`, for indicating the Generic permits ByRefLike types.
Below are valid and invalid examples of ByRefLike as Generic parameters.

**1) Valid**
```csharp
Expand Down
33 changes: 32 additions & 1 deletion docs/design/specs/Ecma-335-Augments.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ This is a list of additions and edits to be made in ECMA-335 specifications. It
- [Covariant Return Types](#covariant-return-types)
- [Function Pointer Type Identity](#function-pointer-type-identity)
- [Unsigned data conversion with overflow detection](#unsigned-data-conversion-with-overflow-detection)
- [Ref field support](#ref-fields)
- [Ref fields support](#ref-fields)
- [ByRefLike types in generics](#byreflike-generics)
- [Rules for IL rewriters](#rules-for-il-rewriters)
- [Checked user-defined operators](#checked-user-defined-operators)
- [Atomic reads and writes](#atomic-reads-and-writes)
Expand Down Expand Up @@ -1026,6 +1027,36 @@ Changes to signatures:
- Add a bullet point
- Managed pointers which point at null, the address just past the end of an object, or the address where an element just past the end of an array would be stored, are permitted but not dereferenceable.

## <a name="byreflike-generics"></a> ByRefLike types in generics

ByRefLike types, defined in C# with the `ref struct` syntax, represent types that cannot escape to the managed heap and must remain on the stack. It is possible for these types to be used as generic parameters, but in order to improve utility certain affordances are required.

### II.10.1.7
An additional IL keyword, `byreflike`, is introduced to indicate use of ByRefLike types is permitted. This expands the set of permissible types used by this parameters, but limits the potential instructions that can be used on instances of this generic parameter type.

AaronRobinsonMSFT marked this conversation as resolved.
Show resolved Hide resolved
### II.23.1.7
Update the `SpecialConstraintMask` flag value and description, and add a new flag, `AllowByRefLike`.

| Flag | Value | Description |
| --- | ----- | ----------- |
| `SpecialConstraintMask` | `0x3C` | These 4 bits contain one of the following values: |
| ... | ... | ... |
| `AllowByRefLike` | `0x20` | The generic parameter is allowed to be ByRefLike |

### III.4
New sub-section should be added after III.4.33 that describes sequences of IL instructions that can be used on ByRefLike types when using within a generic context.
jkotas marked this conversation as resolved.
Show resolved Hide resolved

#### III.4.X
The following are IL sequences involving the `box` instruction. They are used for ByRefLike types and shall be valid in cases where the result can be computed at run-time and elided safely&mdash;through JIT compilation or interpretation. These sequences **must** now be elided when the target type is ByRefLike. The conditions where each sequence is elided are described below.

`box` ; `unbox.any` &ndash; The box target type is equal to the unboxed target type.

`box` ; `br_true/false` &ndash; The box target type is non-`Nullable<T>`.

`box` ; `isinst` ; `unbox.any` &ndash; The box, `isinst`, and unbox target types are all equal.

`box` ; `isinst` ; `br_true/false` &ndash; The box target type is ByRefLike or the box target type is `Nullable<T>` and target type equalities can be computed.

## Rules for IL Rewriters

There are apis such as `System.Runtime.CompilerServices.RuntimeHelpers.CreateSpan<T>(...)` which require that the PE file have a particular structure. In particular, that api requires that the associated RVA of a FieldDef which is used to create a span must be naturally aligned over the data type that `CreateSpan` is instantiated over. There are 2 major concerns.
Expand Down