dotnet / roslyn

The Roslyn .NET compiler provides C# and Visual Basic languages with rich code analysis APIs.
https://docs.microsoft.com/dotnet/csharp/roslyn-sdk/
MIT License
19.06k stars 4.04k forks source link

Cannot use index initializer with fixed sized buffer #39632

Open reflectronic opened 5 years ago

reflectronic commented 5 years ago

You currently cannot use an index initializer to populate a fixed-sized buffer. For example:

struct Body
{
    public fixed double V[3];
}

new Body
{
    V = 
    {
        [0] = 1,
        [1] = 2,
        [2] = 3
    }
};

emits on V = an error:

error CS1666: You cannot use fixed size buffers contained in unfixed expressions. Try using the fixed statement.

Firstly, if this is intended behavior, I would at least improve the error message, especially since trying to pin Body.V emits

error CS0213: You cannot use the fixed statement to take the address of an already fixed expression

so you cannot even resolve this issue in the way the error message suggests. However, I think that it should work as expected (and I believe that it can be supported within the current parameters of the language).

Joe4evr commented 5 years ago

Does that type definition even work? Because the feature proposal, dotnet/csharplang#1314, does not mention there's been any work done on it. And if the work has been done, the proposal should be properly updated to mention that the feature has been implemented and working.

reflectronic commented 5 years ago

That proposal is about allowing fixed sized buffers for arbitrary types. Fixed-sized buffers for primitive types have been in C# since version 1.

gafter commented 5 years ago

Marking this as a diagnostic clarity issue because of the fact that you cannot use the fixed statement like so (below), even though that is recommended:

            fixed (double *v = b.V)
            {
                v[0] = 1;
                v[1] = 2;
                v[2] = 3;
            }

If you want to propose a language change, please head on over to the csharplang repo.

gafter commented 5 years ago

(I'm now looking at the language spec to see why this might be forbidden)

gafter commented 5 years ago

In looking at the spec, I cannot see any reason this should not just work. Marking it as a bug.

Perksey commented 5 years ago

Have encountered this in Silk.NET, here's the full source: https://github.com/Ultz/Silk.NET/blob/c740ec98e7264f2c3eb5cbf2f8bdde001e4e4caa/examples/VulkanTriangle/HelloTriangleApplication.cs#L855

Workarounds would be much appreciated :P

YairHalberstadt commented 5 years ago

I'll try to give this a go.

If I'm correct this should be no different to any other collection initialiser. i.e. code gen should just be :

var temp = new Body
temp.V[0] = 1;
temp.V[1] = 2;
temp.V[2] = 3;

which compiles just fine.

RikkiGibson commented 5 years ago

@333fred weren't we looking at this a few weeks back?

gafter commented 5 years ago

@YairHalberstadt That's right, however when it is nested (for example, a field of a newly created class instance) that might not be possible. It might have to be fixed in that context (and therefore an error).