roslyn: Type `T[]*` reports parser error

Version Used:

VS 17.5p1

Steps to Reproduce:

Type a code snippet that uses int[]*:

#pragma warning disable CS8500

static unsafe long IterateBits(long* array, int length, int* @out)
{
    var baseVec = Vector256.Create(-1);
    var incVec = Vector256.Create(64);
    var add8 = Vector256.Create(8);
    var initOut = @out;

    for (var i = 0; i < length; i++)
    {
        var w = array[i];
        if (w == 0)
        {
            baseVec += incVec;
        }
        else
        {
            for (var k = 0; k < 4; k++)
            {
                var byteA = (byte)w;
                var byteB = (byte)(w >> 8);
                w >>= 16;

//                       ↓ here
                fixed (int[]* pVt = BitPosTable)
//                     ~~~~~~
                fixed (int* pByteA = pVt[byteA], pByteB = pVt[byteB])
                {
                    var vecA = Vector256.Load(pByteA);
                    var vecB = Vector256.Load(pByteB);
                    var advanceA = LengthTable[byteA];
                    var advanceB = LengthTable[byteB];
                    vecA = baseVec + vecA;
                    baseVec += add8;
                    vecB = baseVec + vecB;
                    baseVec += add8;

                    Vector256.Store(vecA, @out);
                    @out += advanceA;
                    Vector256.Store(vecB, @out);
                    @out += advanceB;
                }
            }
        }
    }

    return @out - initOut;
}

sharplab

Expected Behavior:

No parser error on int[]*: C# 11 allows managed-typed pointers.

Actual Behavior:

It seems that C# syntax parser cannot correctly handle the expression int[]*; we should add an extra but unnecessary token ? to make parser behave well: int[]?*.

image

image

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 1
  • Comments: 15 (14 by maintainers)

Most upvoted comments

This strikes me as a case of using grammars to enforce semantic rules, which we don’t really do in the implementation. The “grammar” effectively in use in the implementation permits parsing many invalid programs simply so we can have a better guess at what the user meant to do. The corresponding spot in the grammar generated by the implementation is:

https://github.com/dotnet/roslyn/blob/1c349c7032ec178955a8fcccc62015ee39b00031/src/Compilers/CSharp/Portable/Generated/CSharp.Generated.g4#L400-L402

Since we are downgrading the pointer to managed type from error to warning in unsafe context, we might want to adjust the standard for C# 11 to indicate that pointers can also refer to managed types.

The part about the nullable annotation is confusing me a bit. Is that saying a work around for the bug is to add the nullable annotation?

When parsing a type, the parser says: if we got * and previous token was ], don’t parse. So adding the ? in between makes the parser happy.

This was part of the general theme of downgrade errors to warnings for memory safe diagonstics if they occur inside an unsafe context. The ask to make int[]* follows from that decision.

Gotcha. Then making this change def makes sense to me.