Error: ModuleInitializerAttribute is inaccessible due to its protection level in .NET Framework
The automatic Polyfill reference for legacy frameworks seems to have internal visibility, and TUnit can't access it.
$ dotnet run
/workspaces/repro/MyTests/obj/Debug/net481/TUnit.Core.SourceGenerator/TUnit.Core.SourceGenerator.CodeGenerators.DisableReflectionScannerGenerator/DisableReflectionScanner.g.cs(7,46): error CS0122: 'ModuleInitializerAttribute' is inaccessible due to its protection level
/workspaces/repro/MyTests/obj/Debug/net481/TUnit.Core.SourceGenerator/TUnit.Core.SourceGenerator.CodeGenerators.AssemblyLoaderGenerator/AssemblyLoader.g.cs(7,46): error CS0122: 'ModuleInitializerAttribute' is inaccessible due to its protection level
Repro steps (tested in WSL2 with Mono 6.12 / .NET 10 RC2 CLI for bootstrapping the project):
dotnet new console -o MyTests -f net10.0
dotnet add MyTests package TUnit
sed -i 's/net10.0/net481/g' MyTests/MyTests.csproj
sed -i '/<Nullable>enable<\/Nullable>/a \ <LangVersion>14</LangVersion>' MyTests/MyTests.csproj
rm MyTests/Program.cs
cat << 'EOF' > MyTests/MyTests.cs
namespace MyTests;
public class MyTests
{
[Test]
public async Task MyTest()
{
await Assert.That(true).IsTrue();
}
}
EOF
dotnet run --project MyTests
As a workaround, I disabled the automatic polyfills and installed it manually:
sed -i '/<LangVersion>14<\/LangVersion>/a \ <EnableTUnitPolyfills>false</EnableTUnitPolyfills>' MyTests/MyTests.csproj
dotnet add MyTests package Polyfill
dotnet run --project MyTests
I think it will be easier to solve this with Polyfill 9.0.0 which adds support for Microsoft.CodeAnalysis.EmbeddedAttribute since https://github.com/SimonCropp/Polyfill/pull/388
I think you can embed Polyfill 9.0.0 in TUnit.Core.SourceGenerator with <PolyUseEmbeddedAttribute>true</PolyUseEmbeddedAttribute> and the result should be a better experience that doesn't rely on workarounds with EnableTUnitPolyfills.
https://github.com/SimonCropp/Polyfill/blob/main/consuming.md#recommended-consuming-pattern
Thanks for that tip @sliekens !
Does this work better for you in v1.1.0?
Unfortunately no, the error persists. It appears that the implicitly added polyfills are not being added to the compilation.
I compared the msbuild.binlog (generated via dotnet build -bl) for implicit and for explicit polyfills.
Implicit: only MyTest.cs is added to the compilation.
Explicit: all files provided by Polyfill are also added to the compilation.
I think the reason is that dotnet build is not seeing the implicitly added PackageReference
Compare with explicit reference
@thomhurst if you want a look for yourself, here are the binlogs.zip, you can view them with MSBuild Log Viewer
@thomhurst I have some bad news, this looks like it works this way by design:
Guidance for the content of MSBuild props and targets
NuGet does not limit how you author .props and .targets as they will vary based on the need of the package author and the target projects themselves.
There are a few things that must not be done in packages' .props and .targets, such as not specifying properties and items that affect restore, as those will be automatically excluded.
Some examples of properties that must not be added or updated: TargetFramework, TargetFrameworkMoniker, TargetPlatformMoniker, AssetTargetFallback etc.
Some examples of items that must not be added or updated: PackageReference, PackageVersion, PackageDownload, etc. https://learn.microsoft.com/en-us/nuget/concepts/msbuild-props-and-targets#guidance-for-the-content-of-msbuild-props-and-targets
Sounds like the PackageReference items added by TUnit.Core.targets are automatically excluded again 🫤.
Dang. I guess this'll just have to be a manual step then for .NET framework users
Or would the Poly EmbeddedAttribute + PolyPublic + Standard package reference approach work for non .NET core apps 🤔
Sounds crazy enough to work. My first instinct was that PolyPublic would introduce ambiguous type references, but then I guess the EmbeddedAttribute could solve that. But this some serious off road shit 😄.
@SimonCropp Can you share any wisdom? 😅
actually @Youssef1313 is the subject matter expert here
is there a repro solution i can play with?
I haven't played with the repro but I think TUnit users will have to add the Polyfill package reference themselves and enable the use of embedded attribute.
Alternatively, if TUnit wants to really add the package ref automatically, this is only possible via an MSBuild SDK, similar to MSTest.Sdk.
Damn, an Sdk just for that seems a bit overkill. Might just have to rely on users doing this manually then
FWIW I am totally fine with this being a manual step for Framework targets. I think they broadly fall into one of two categories :
- Enterprise legacy maintainers who have no need or want for modern approaches with source generators, they will stay on what they are already using (MSTest, NUnit...)
- Library authors who are already Polyfill ing their legacy targets for other reasons