manuelroemer / Nullable

A source code only package which allows you to use .NET's nullable attributes in older target frameworks like .NET Standard 2.0 or the "old" .NET Framework.
https://www.nuget.org/packages/Nullable
MIT License
186 stars 8 forks source link

CS0246 build errors on .NET 6.0.300 SDK #24

Closed mattjohnsonpint closed 2 years ago

mattjohnsonpint commented 2 years ago

After installing the .NET 6.0.300 SDK, doing dotnet build --no-incremental on a project using this library gives errors such as:

error CS0246: The type or namespace name 'NotNullWhen' could not be found

Minimal Reproduction

MyApp.csproj

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <LangVersion>8</LangVersion>
    <Nullable>annotations</Nullable>
    <TargetFrameworks>net6.0;net48</TargetFrameworks>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Nullable" Version="1.3.0" PrivateAssets="all" />
  </ItemGroup>

</Project>

Program.cs

using System;
using System.Diagnostics.CodeAnalysis;

namespace MyApp
{
    class Program
    {
        static void Main(string[] args)
        {
            if (Test(out var value))
            {
                Console.WriteLine(value);
            }
        }

        private static bool Test([NotNullWhen(true)] out string? value)
        {
            value = "Hello World!";
            return true;
        }
    }
}

Compile with dotnet build --no-incremental:

C:\Users\mattj\Code\MyApp>dotnet build --no-incremental
Microsoft (R) Build Engine version 17.2.0+41abc5629 for .NET
Copyright (C) Microsoft Corporation. All rights reserved.

  Determining projects to restore...
  All projects are up-to-date for restore.
C:\Users\mattj\Code\MyApp\Program.cs(16,35): error CS0246: The type or namespace name 'NotNullWhenAttribute' could not be found (are you m
issing a using directive or an assembly reference?) [C:\Users\mattj\Code\MyApp\MyApp.csproj]
C:\Users\mattj\Code\MyApp\Program.cs(16,35): error CS0246: The type or namespace name 'NotNullWhen' could not be found (are you missing a 
using directive or an assembly reference?) [C:\Users\mattj\Code\MyApp\MyApp.csproj]
  MyApp -> C:\Users\mattj\Code\MyApp\bin\Debug\net6.0\MyApp.dll

Build FAILED.

Workaround

Install the previous 6.0.203 SDK, and force the project to use it by adding a global.json file with the following:

{
  "sdk": {
    "version": "6.0.203"
  }
}

Then the project builds just fine with dotnet build --no-incremental.

This might be an upstream problem with .NET, but I haven't dug deep enough to figure out what it might be.

mattjohnsonpint commented 2 years ago

I also find it interesting that it only occurs with --no-incremental, even if this is the first build (no bin or obj folders). Maybe that will help your investigation.

shuebner commented 2 years ago

I just tried using this and IsExternalInit instead of importing the cs files myself and have the same problem.

For me it works with neither SDK 6.0.100 nor 6.0.202 nor 6.0.300.

Occasionally the CLI build will work, but VS 2022 is never able to build. I suspect a race condition in the nuget source transformation, because I did not have this problem when I imported my own cs files into all my projects to gain support for nullability and record types.

manuelroemer commented 2 years ago

Hey, I unfortunately had nowhere near enough time yet to thoroughly look into this, but I could also reproduce the error. The issue I'm having is that, from my point of view, the package itself is sound, i.e. the nuspec which is used to inject the files is, unless I'm missing something, looking the way it's supposed to. My guess is that the .NET tooling/Nuget/VS/... has some kind of regression somewhere such that it doesn't handle source code provided by packages well. I cannot prove it though, this is just a hunch on my side. If that does turn out to be true, there is unfortunately not much I could do on my side. The issue would have to be fixed at the root (and up until this point, everything did work properly, so something on the outside must have changed).

In any case, any help here investigating the issue is much appreciated :heart:! Maybe the issue is in this package/nuspec (in that case, any pointers as to what's wrong with the format will be very helpful). Or if you guys also believe that the issue is located on the outside, you might know where to raise an issue.

mattjohnsonpint commented 2 years ago

I agree, it's most likely something in the tooling. Once we figure out what that is, most likely the best repo to report it to Microsoft on would be here https://github.com/dotnet/sdk

mattjohnsonpint commented 2 years ago

Experimenting a bit. Turns out that it only fails when using <TargetFrameworks> instead of <TargetFramework>, unless you specify a framework on the command line with -f. I think for whatever reason, the build isn't passing along the <contentFiles> when it loops over <TargetFrameworks> to dispatch for each framework.

I'll open an issue on the SDK repo and link here.

shuebner commented 2 years ago

I observed the failure in another smaller and simpler repo. It built with 6.0.100, but not with 6.0.300. The projects were NOT multitargeting, but targeting netstandard2.0.

Also, only when using --no-incremental did the build fail. It was fine in both SDKs with the default command.

manuelroemer commented 2 years ago

Hey @mattjohnsonpint, I just want to quickly thank you for opening the issue on the .NET SDK repo and all the others for helping to provide additional information on this issue. I appreciate you guys a lot! Let's see what the outcome will be!

manuelroemer commented 2 years ago

I just merged #26 by @gtbuchanan and published the new package version 1.3.1 on NuGet. During my local tests the issue indeed seemed to be fixed (using .NET SDK 6.0.300). I will preemptively close this issue, but if someone still has any problems in this area even with the newer version, feel free to message me or simply reopen this issue. Many thanks to all people involved (so far 😉)!