microsoft / CsWinRT

C# language projection for the Windows Runtime
MIT License
546 stars 104 forks source link

CS8785 error after updating from 8.0.304 to 8.0.306 SDK #1828

Open bh-sijtnic opened 6 days ago

bh-sijtnic commented 6 days ago

Describe the bug

After updating the .NET 8 SDK from 8.0.304 to the latest 8.0.306 some or our projects targeting framework net8.0-windows10.0.19041 fail with error. We use Visual Studio 2022 17.10.7.

CSC : error CS8785: Generator 'WinRTAotSourceGenerator' failed to generate source. It will not contribute to the output and compilation errors may as a result. Exception was of type 'IndexOutOfRangeException' with message 'Index was outside the bounds of the array.'

and

C:\Development\RepoName\.int\Debug\projectname\net8.0-windows10.0.19041\win-x64\WinRT.SourceGenerator\Generator.WinRTAotSourceGenerator\WinRTGlobalVtableLookup.g.cs(5,19): error CS0116: A namespace cannot directly contain members such as fields, methods or statements

We did find that adding this to our Directory.Build.props code base "resolves" the issue, though in the documentation we can read its not recommended to use this property. For now we can keep this as a workarround, but we would like to understand the proper fix.

<WindowsSdkPackageVersion>10.0.19041.34</WindowsSdkPackageVersion>

To Reproduce

I have not been able to reproduce this yet outside our own code base. We don't know where this code generator comes from and what it triggers.

Exceptions (if any)

CSC : error CS8785: Generator 'WinRTAotSourceGenerator' failed to generate source. It will not contribute to the output and compilation errors may as a result. Exception was of type 'IndexOutOfRangeException' with message 'Index was outside the bounds of the array.'

and

C:\Development\RepoName\.int\Debug\projectname\net8.0-windows10.0.19041\win-x64\WinRT.SourceGenerator\Generator.WinRTAotSourceGenerator\WinRTGlobalVtableLookup.g.cs(5,19): error CS0116: A namespace cannot directly contain members such as fields, methods or statements

Further technical details

.NET SDKs installed: 2.1.202 [C:\Program Files\dotnet\sdk] 2.1.512 [C:\Program Files\dotnet\sdk] 3.1.423 [C:\Program Files\dotnet\sdk] 5.0.416 [C:\Program Files\dotnet\sdk] 6.0.310 [C:\Program Files\dotnet\sdk] 6.0.427 [C:\Program Files\dotnet\sdk] 8.0.304 [C:\Program Files\dotnet\sdk] 8.0.306 [C:\Program Files\dotnet\sdk]

Visual Studio 2022 - 17.10.7

Windows 10 / Windows 11 Version 23H2

bh-sijtnic commented 6 days ago

As per the recommendation of @manodasanW we attempted to use the version published last night

<WindowsSdkPackageVersion>10.0.19041.52</WindowsSdkPackageVersion>

via: https://github.com/dotnet/sdk/issues/44145

This did not fix the issue, the error remains the same.

manodasanW commented 5 days ago

Thanks for trying out the new build. Can you confirm whether you have any special characters in your project / assembly name and if so which? If you do, I think our escaping logic is incomplete and I think I am going to take a new approach to fix that.

For IndexOutOfRangeException, can you try the below steps and see if there is any stack you can share that would be helpful to us figuring out the issue:

bh-sijtnic commented 5 days ago

Even with diag logging, the string "'WinRTAotSourceGenerator' failed to generate source" does not exist in the log file. The only hits on WinRTAotSourceGenerator are still these:

4>    C:\Development\Main\.int\Debug\addinspecflowtest\net6.0-windows10.0.19041\win-x64\WinRT.SourceGenerator\Generator.WinRTAotSourceGenerator\WinRTGlobalVtableLookup.g.cs(5,19,5,50): error CS0116: A namespace cannot directly contain members such as fields, methods or statements
4>    C:\Development\Main\.int\Debug\addinspecflowtest\net6.0-windows10.0.19041\win-x64\WinRT.SourceGenerator\Generator.WinRTAotSourceGenerator\WinRTGlobalVtableLookup.g.cs(5,16,5,19): error CS1514: { expected
4>    C:\Development\Main\.int\Debug\addinspecflowtest\net6.0-windows10.0.19041\win-x64\WinRT.SourceGenerator\Generator.WinRTAotSourceGenerator\WinRTGlobalVtableLookup.g.cs(6,1,6,2): error CS1022: Type or namespace definition, or end-of-file expected
4>    CompilerServer: server - server processed compilation - Addin.SpecFlowTest (net6.0-windows10.0.19041)
4>  Done executing task "Csc" -- FAILED.
4>Done building target "CoreCompile" in project "Addin.SpecFlowTest.csproj" -- FAILED.

We only see this issue in 2 of our 1200 csproj files, i cannot find a pattern yet. This project itself is one of our 50 SpecFlow projects, it may have "many" project and package references, but the project itself does not contain a whole lot.

In the diag logs i can confirm version 52 is used, as i see these lines

    Line 317051: 4>            C:\Users\username\.nuget\packages\microsoft.windows.sdk.net.ref\10.0.19041.52\lib/net6.0/WinRT.Runtime.dll
    Line 318833: 4>            C:\Users\username\.nuget\packages\microsoft.windows.sdk.net.ref\10.0.19041.52\analyzers/dotnet/cs/WinRT.SourceGenerator.dll
dongle-the-gadget commented 5 days ago

Try checking in your build output, not the log.txt file.

bh-sijtnic commented 5 days ago

This is output from the Output window in Visual Studio.

dongle-the-gadget commented 5 days ago

It looks like the stack should be above the line that you shared. Can you check if it exists there?

bh-sijtnic commented 5 days ago

Above those you will find the csc.exe command line and header output. Nothing else.

bh-sijtnic commented 5 days ago

Oke, i tried the same steps on the 2nd project that fails, here we do see a callstack, hope this helps:

1>        Microsoft (R) Visual C# Compiler version 4.10.0-3.24372.12 (1c559959)
1>        Copyright (C) Microsoft Corporation. All rights reserved.
1>        CSC : error CS8785: Generator 'WinRTAotSourceGenerator' failed to generate source. It will not contribute to the output and compilation errors may occur as a result. Exception was of type 'IndexOutOfRangeException' with message 'Index was outside the bounds of the array.'.
1>        System.IndexOutOfRangeException: Index was outside the bounds of the array.
1>        at Generator.WinRTAotSourceGenerator.GetVtableAttributesToAddOnLookupTable(GeneratorSyntaxContext context, TypeMapper typeMapper, Func`3 isWinRTType, Func`2 isWinRTClass)
1>        at Generator.WinRTAotSourceGenerator.GetVtableAttributesToAddOnLookupTable(GeneratorSyntaxContext context, TypeMapper typeMapper)
1>        at Generator.WinRTAotSourceGenerator.<>c.<Initialize>b__0_17(ValueTuple`2 t, CancellationToken _)
1>        at Microsoft.CodeAnalysis.TransformNode`2.<>c__DisplayClass6_0.<.ctor>b__0(TInput i, CancellationToken token)
1>        at Microsoft.CodeAnalysis.TransformNode`2.UpdateStateTable(Builder builder, NodeStateTable`1 previousTable, CancellationToken cancellationToken)
1>        -----
1>        CSC : error AD0001: Analyzer 'WinRT.SourceGenerator.WinRTAotDiagnosticAnalyzer' threw an exception of type 'System.IndexOutOfRangeException' with message 'Index was outside the bounds of the array.'.
1>        Exception occurred with following context:
1>        Compilation: DomainAddin.UI.Windows.Logic
1>        SyntaxTree: C:\Development\Main\Addins\DomainAddin\DomainAddin.UI.Windows.Logic\ViewModels\SetElementSizeViewModel.cs
1>        SyntaxNode: ActionToFunction(fillinRegionIntoViewmodel ... [InvocationExpressionSyntax]@[37856..37932) (795,35)-(795,111)
1>        System.IndexOutOfRangeException: Index was outside the bounds of the array.
1>        at WinRT.SourceGenerator.WinRTAotDiagnosticAnalyzer.<>c__DisplayClass3_0.<Initialize>b__2(SyntaxNodeAnalysisContext context)
1>        at Microsoft.CodeAnalysis.Diagnostics.AnalyzerExecutor.<>c__52`1.<ExecuteSyntaxNodeAction>b__52_0(ValueTuple`2 data)
1>        at Microsoft.CodeAnalysis.Diagnostics.AnalyzerExecutor.ExecuteAndCatchIfThrows_NoLock[TArg](DiagnosticAnalyzer analyzer, Action`1 analyze, TArg argument, Nullable`1 info, CancellationToken cancellationToken)
1>        -----
1>        Suppress the following diagnostics to disable this analyzer: CsWinRT1028, CsWinRT1029, CsWinRT1030
1>        CompilerServer: server - server processed compilation - DomainAddin.UI.Windows.Logic_gcxbedqq_wpftmp (net6.0-windows10.0.19041)
1>      Done executing task "Csc" -- FAILED.
1>    Done building target "CoreCompile" in project "DomainAddin.UI.Windows.Logic_gcxbedqq_wpftmp.csproj" -- FAILED.
1>
1>    Done building project "DomainAddin.UI.Windows.Logic_gcxbedqq_wpftmp.csproj" -- FAILED.
1>  Done executing task "GenerateTemporaryTargetAssembly" -- FAILED.
1>Done building target "GenerateTemporaryTargetAssembly" in project "DomainAddin.UI.Windows.Logic.csproj" -- FAILED.
bh-sijtnic commented 5 days ago

To be user again with .52, but looks the same

1>        Microsoft (R) Visual C# Compiler version 4.10.0-3.24372.12 (1c559959)
1>        Copyright (C) Microsoft Corporation. All rights reserved.
1>        CSC : error CS8785: Generator 'WinRTAotSourceGenerator' failed to generate source. It will not contribute to the output and compilation errors may occur as a result. Exception was of type 'IndexOutOfRangeException' with message 'Index was outside the bounds of the array.'.
1>        System.IndexOutOfRangeException: Index was outside the bounds of the array.
1>        at Generator.WinRTAotSourceGenerator.GetVtableAttributesToAddOnLookupTable(GeneratorSyntaxContext context, TypeMapper typeMapper, Func`3 isWinRTType, Func`2 isWinRTClass)
1>        at Generator.WinRTAotSourceGenerator.GetVtableAttributesToAddOnLookupTable(GeneratorSyntaxContext context, TypeMapper typeMapper, Boolean isCsWinRTComponent)
1>        at Generator.WinRTAotSourceGenerator.<>c.<Initialize>b__0_16(ValueTuple`2 value, CancellationToken _)
1>        at Microsoft.CodeAnalysis.TransformNode`2.<>c__DisplayClass6_0.<.ctor>b__0(TInput i, CancellationToken token)
1>        at Microsoft.CodeAnalysis.TransformNode`2.UpdateStateTable(Builder builder, NodeStateTable`1 previousTable, CancellationToken cancellationToken)
1>        -----
1>        CSC : error AD0001: Analyzer 'WinRT.SourceGenerator.WinRTAotDiagnosticAnalyzer' threw an exception of type 'System.IndexOutOfRangeException' with message 'Index was outside the bounds of the array.'.
1>        Exception occurred with following context:
1>        Compilation: DomainAddin.UI.Windows.Logic
1>        SyntaxTree: C:\Development\Main\Addins\DomainAddin\DomainAddin.UI.Windows.Logic\ViewModels\SetElementSizeViewModel.cs
1>        SyntaxNode: ActionToFunction(fillinRegionIntoViewmodel ... [InvocationExpressionSyntax]@[37856..37932) (795,35)-(795,111)
1>        System.IndexOutOfRangeException: Index was outside the bounds of the array.
1>        at WinRT.SourceGenerator.WinRTAotDiagnosticAnalyzer.<>c__DisplayClass3_0.<Initialize>b__2(SyntaxNodeAnalysisContext context)
1>        at Microsoft.CodeAnalysis.Diagnostics.AnalyzerExecutor.<>c__52`1.<ExecuteSyntaxNodeAction>b__52_0(ValueTuple`2 data)
1>        at Microsoft.CodeAnalysis.Diagnostics.AnalyzerExecutor.ExecuteAndCatchIfThrows_NoLock[TArg](DiagnosticAnalyzer analyzer, Action`1 analyze, TArg argument, Nullable`1 info, CancellationToken cancellationToken)
1>        -----
1>        Suppress the following diagnostics to disable this analyzer: CsWinRT1028, CsWinRT1029, CsWinRT1030
1>        CompilerServer: server - server processed compilation - DomainAddin.UI.Windows.Logic_lnzdakes_wpftmp (net6.0-windows10.0.19041)
1>      Done executing task "Csc" -- FAILED.
1>    Done building target "CoreCompile" in project "DomainAddin.UI.Windows.Logic_lnzdakes_wpftmp.csproj" -- FAILED.
1>
1>    Done building project "DomainAddin.UI.Windows.Logic_lnzdakes_wpftmp.csproj" -- FAILED.
1>  Done executing task "GenerateTemporaryTargetAssembly" -- FAILED.
1>Done building target "GenerateTemporaryTargetAssembly" in project "DomainAddin.UI.Windows.Logic.csproj" -- FAILED.
dongle-the-gadget commented 5 days ago

What is the signature of the ActionToFunction method and how are you calling it?

bh-sijtnic commented 5 days ago

I hope this is sufficient

Func<TA1, TA2, TA1> ActionToFunction<TA1, TA2>(Action<TA1, TA2> action) =>
                    (a1, a2) =>
                    {
                        action(a1, a2);
                        return a1;
                    };
return items.Select(data => (
                        viewmodel: ActionToFunction(fill)(data.viewmodel, data.info),
                        data.info));
bh-sijtnic commented 5 days ago

We are able to reproduce this in a sample project, do you have a way for me to share this with you?

manodasanW commented 5 days ago

Thanks for all this information, I was able to reproduce the exception with what you have provided. I may need some additional information for the first issue with error CS0116: A namespace cannot directly as that isn't clear why you are hitting it, but I follow up on that after as I might have a potential general fix for that.

bh-sijtnic commented 5 days ago

Great, we have also narrowed down the "problem" of our SpecFlow project. This project has 2 pieces of code that causes a failure in the WinRT generator. We commented out the original code for you to see, it builds fine with these lines. Both pieces are in a different class.

//IGenericObject hor = new GenericObject("name", Type.Hor);
var horizon = new GenericObject("name", Type.Hor);
            return null;
            //if (k <= 0 || k > ar.Count - 1)
            //    return ar;
            //return ar.Skip(k)            // Start with the last elements
            //         .Concat(ar.Take(k)) // Then the first elements
            //         .ToList();          // Then make it an array

So far we are unable to cause a failure for this in a sample solution. Hope this helps

bh-sijtnic commented 5 days ago

A question though, why is this generator suddenly enabled? Both on net6 and net8? Can we this be changed to an opt-in model? We don't believe we need these generators enabled.

Please advise.

dongle-the-gadget commented 4 days ago

The generator was added to make C#/WinRT AOT compatible, and they were added as you specified the Windows 10+ TFM. The <CsWinRTAotOptimizerEnabled> switch should disable the generator, but I'm not sure if that is allowed or not.

bh-sijtnic commented 4 days ago

Thanks, in our case, we don't make use of WinRT, or AoT. Yet the changes you applied do affect us and suddenly enable new features, even on older (NET6) products. I see other issues have been reported and users ask for this to be opt-in, not by default. https://github.com/microsoft/CsWinRT/issues/1814 https://github.com/dotnet/sdk/issues/44026

We would like to request you to change the defaults of the SDK on the already released SDK's

This way, you don't introduce breaking changes in one of your patch releases, but allow users to get the functionality when they upgrade to a newer SDK.

If i have to opt-out, i need to do this in 40 repositories, in 3 releases, so that means 120 pull requests. Please don't make us do this.

dongle-the-gadget commented 4 days ago

This is because since you're using the Windows 10 TFM, .NET assumes you wish to use WinRT. This WinRT-inclusion behavior is present on older versions of .NET as well, not just this new one.

bh-sijtnic commented 4 days ago

In addition to CsWinRTAotOptimizerEnabled, are there more properties we can disable to disable WinRT as a whole?

dongle-the-gadget commented 4 days ago

You can remove the entire framework reference:

<FrameworkReference Remove="Microsoft.Windows.SDK.NET.Ref" />
bh-sijtnic commented 4 days ago

I tried to disable the AoTOptimizer, but it does not allow me it seems.

<CsWinRTAotOptimizerEnabled>false</CsWinRTAotOptimizerEnabled>
CS8785  Generator 'WinRTAotSourceGenerator' failed to generate source. It will not contribute to the output and compilation errors may occur as a result. Exception was of type 'IndexOutOfRangeException' with message 'Index was outside the bounds of the array.

Above error is still reported, when using the default SDK, if i manually change it to 10.0.19041.52 it does allow me to disable it. So it seems above exception is hit even before the optimizer is enabled in the old SDK, which is interesting as well.