2018-02-28 03:16:31 +01:00
# Indexing `fixed` fields should not require pinning regardless of the movable/unmovable context. #
The change has the size of a bug fix. It can be in 7.3 and does not conflict with whatever direction we take further.
This change is only about allowing the following scenario to work even though `s` is moveable. It is already valid when `s` is not moveable.
2018-10-03 22:07:36 +02:00
NOTE: in either case, it still requires `unsafe` context. It is possible to read uninitialized data or even out of range. That is not changing.
2018-02-28 03:16:31 +01:00
2019-03-07 22:04:57 +01:00
```csharp
2018-02-28 03:16:31 +01:00
unsafe struct S
{
public fixed int myFixedField[10];
}
class Program
{
static S s;
unsafe static void Main()
{
int p = s.myFixedField[5]; // indexing fixed-size array fields would be ok
}
}
```
The main “challenge” that I see here is how to explain the relaxation in the spec.
In particular, since the following would still need pinning.
(because `s` is moveable and we explicitly use the field as a pointer)
2019-03-07 22:04:57 +01:00
```csharp
2018-02-28 03:16:31 +01:00
unsafe struct S
{
public fixed int myFixedField[10];
}
class Program
{
static S s;
unsafe static void Main()
{
int* ptr = s.myFixedField; // taking a pointer explicitly still requires pinning.
int p = ptr[5];
}
}
```
2018-10-03 22:07:36 +02:00
One reason why we require pinning of the target when it is movable is the artifact of our code generation strategy, - we always convert to an unmanaged pointer and thus force the user to pin via `fixed` statement. However, conversion to unmanaged is unnecessary when doing indexing. The same unsafe pointer math is equally applicable when we have the receiver in the form of a managed pointer. If we do that, then the intermediate ref is managed (GC-tracked) and the pinning is unnecessary.
2018-02-28 03:16:31 +01:00
The change https://github.com/dotnet/roslyn/pull/24966 is a prototype PR that relaxes this requirement.