microsoft / CsWin32

A source generator to add a user-defined set of Win32 P/Invoke methods and supporting types to a C# project.
MIT License
2.07k stars 87 forks source link

VariableLengthInlineArray - VS2019 - CS8170 and CS8347 #1251

Open RFBomb opened 2 months ago

RFBomb commented 2 months ago

Actual behavior

I'm making this post in case the dev team wants to review Visual Studio 2019 compatibility with this generator. This generator has absolute no issues for this particular problem when I ran it in VS2022. ( Earlier in development, I had an issue where tests passed in VS2022, and failed in VS2019 when calling CopyFileEx, so I finished development in 2022, and was about to re-test in 2019 when this stopped me. )

image

Expected behavior

The generator should work for either studio.

Repro steps

This was working without issue (and passing unit tests) when compiled in VS2022.

For what its worth, I was able to compile and pass the tests I was concerned with after downgrading to CSWin32 v0.3.49-beta ( I did have to whip up a quick extension method fix in RoboSharp.Extensions.SymbolicLinkSupport.SymbolicLink)

private static Span<char> AsSpan(this MSWin.Wdk.__char_1 ch, int length)
        {
#if NETFRAMEWORK
            Span<char> r = new char[length];
            ch.CopyTo(r, length);
            return r;
#else
            return ch.AsSpan();
#endif
        }

this brief workaround makes sense, as VariableLengthInlineArray did not exist in v0.3.49-beta

  1. NativeMethods.txt content:
    
    // IFileCopiers
    CopyFileEx
    MoveFileWithProgressW

// Symbolic Links CreateSymbolicLink CreateFile DeviceIoControl GetFinalPathNameByHandle PathRelativePathToW GENERIC_ACCESS_RIGHTS IO_REPARSE_TAG_SYMLINK IO_REPARSE_TAG_MOUNT_POINT FSCTL_GET_REPARSE_POINT MAXIMUM_REPARSE_DATA_BUFFER_SIZE MAX_PATH REPARSE_DATA_BUFFER SYMLINK_FLAG_RELATIVE WIN32_ERROR


2. `NativeMethods.json` content (if present): N/A

3. Any of your own code that should be shared?

Link to the github repo : https://github.com/RFBomb/RoboSharp/tree/AsyncCopy

relevant portions of the CSProj file:
net462; net48; netstandard2.0; netstandard2.1; netcoreapp3.1; net5.0; net6.0; // Removed when opened in VS2019 net8.0; // Removed when opened in VS2019 all runtime; build; native; contentfiles; analyzers; buildtransitive
<Choose>
    <!-- NetFramework | NetStandard 2.0 -->
    <When Condition=" $([System.Text.RegularExpressions.Regex]::IsMatch('$(TargetFramework)', '$(NetFrameworkRegex)'))">
        <PropertyGroup>
            <langversion>9</langversion>
        </PropertyGroup>
        <ItemGroup>
            <PackageReference Include="System.Memory" Version="4.5.5" />
        </ItemGroup>
    </When>
    <!-- NetStandard 2.1 -->
    <When Condition=" '$(TargetFramework)' == 'netstandard2.1' Or '$(TargetFramework)' == 'netcoreapp3.1'">
        <PropertyGroup>
            <langversion>9</langversion>
        </PropertyGroup>
    </When>

    <!-- NetCoreApp | .Net5+ -->
    <Otherwise>
    </Otherwise>
</Choose>

Generated Code:

namespace Windows.Win32 { internal struct VariableLengthInlineArray where T : unmanaged { internal T e0;

    internal ref T this[int index]
    {
                    [UnscopedRef]
        [MethodImpl(MethodImplOptions.AggressiveInlining)]

get => ref Unsafe.Add(ref this.e0, index); }

    [UnscopedRef]
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    internal Span<T> AsSpan(int length)

    {

unsafe

        {
            fixed (void* p = &this.e0)
            {
                return new Span<T>(p, length);
            }
        }
    }
}

}



### Context

- CsWin32 version: [0.3.106]
- Win32Metadata version (if explicitly set by project):
- Target Framework: Net48, Net5
- `LangVersion` 9