.NET SDK 10.0.1xx design-time builds of net8.0-targeted projects resolve zero framework references (silent skeleton compilations under MSBuildWorkspace)
BugArea-Analyzers
## Description
When a project targeting `net8.0` is loaded through `Microsoft.CodeAnalysis.MSBuild.MSBuildWorkspace` (Roslyn 5.6.0) and the target's `global.json` resolves a **10.0.1xx-band** SDK, the design-time build produces a compilation with **no framework references at all** — only explicit `PackageReference` assemblies survive. `System.String` does not resolve; every cross-assembly type binds as an error type; generated `AssemblyInfo` content (version stamp, `InternalsVisibleTo` attributes from msbuild items) is absent. The load reports **zero `WorkspaceFailed` events**, so consumers receive silently corrupt semantics.
The same projects, with the same restored assets, load correctly when the target resolves a **10.0.2xx** SDK.
## Repro (6 files)
`global.json`:
```json
{ "sdk": { "version": "10.0.109", "rollForward": "patch" } }
```
`LibMulti/LibMulti.csproj`:
```xml
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net8.0;net10.0</TargetFrameworks>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<InternalsVisibleTo Include="ConsumerMini" />
</ItemGroup>
</Project>
```
`LibMulti/Secret.cs`:
```csharp
namespace LibMulti;
internal sealed class Secret
{
public string Name { get; init; } = "";
}
```
`LibSingle8/LibSingle8.csproj` (single-TFM — shows it is not specific to multi-TFM inner builds):
```xml
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>
```
`ConsumerMini/ConsumerMini.csproj`:
```xml
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\LibMulti\LibMulti.csproj" />
</ItemGroup>
</Project>
```
`ConsumerMini/Program.cs`:
```csharp
var secret = new LibMulti.Secret { Name = "x" };
System.Console.WriteLine(secret.Name);
```
Loader (net10.0 console app referencing `Microsoft.Build.Locator` 1.11.2, `Microsoft.CodeAnalysis.CSharp.Workspaces` 5.6.0, `Microsoft.CodeAnalysis.Workspaces.MSBuild` 5.6.0, MSBuild refs `ExcludeAssets="runtime"`):
```csharp
MSBuildLocator.RegisterDefaults();
using var ws = MSBuildWorkspace.Create();
ws.WorkspaceFailed += (_, e) => Console.WriteLine($"FAILED: {e.Diagnostic}");
var consumer = await ws.OpenProjectAsync(@"...\ConsumerMini\ConsumerMini.csproj");
await ws.OpenProjectAsync(@"...\LibSingle8\LibSingle8.csproj");
foreach (var p in ws.CurrentSolution.Projects)
{
var comp = await p.GetCompilationAsync();
Console.WriteLine($"{p.Name}: refs={p.MetadataReferences.Count} " +
$"String={comp!.GetTypeByMetadataName("System.String") is not null} " +
$"version={comp.Assembly.Identity.Version}");
}
```
Steps: `dotnet restore` both leaf projects, run the loader.
## Observed (A/B/A — same projects, same restored assets, only global.json toggled)
| Target-resolved SDK | net8.0 flavors | net10.0 flavors |
|---|---|---|
| 10.0.109 | **0 metadata refs**, assembly version 0.0.0.0, `System.String` unresolvable, IVT attribute constructor args bind as null | healthy |
| 10.0.204 | healthy (163 refs) | healthy |
| 10.0.109 (re-pinned) | broken again | healthy |
Also reproduced with SDK 10.0.106 (an Arcade-bootstrapped copy). Both the multi-TFM net8.0 flavor and the single-TFM net8.0 project show the same skeleton.
## Expected
Either the net8.0 design-time build resolves its framework references (as 10.0.2xx does), or the load surfaces a `WorkspaceFailed` diagnostic. A reference-less compilation with zero failure events is the worst of both.
## What it is not
- Not a missing targeting pack: `Microsoft.NETCore.App.Ref` 8.0.20 and 8.0.27 are installed under `C:\Program Files\dotnet\packs` (8.0.26 in the NuGet cache).
- Not a build break: `dotnet build -f net8.0 --no-restore` of the same project with the same 10.0.1xx SDK succeeds with 0 warnings / 0 errors. Only the design-time load path is affected.
## Real-world impact
Loading dotnet/roslyn's own `Roslyn.slnx` (whose `global.json` pins 10.0.106 + `rollForward: patch`, and whose `Workspaces.MSBuild.Contracts` targets `{net8.0, net472}`) manufactures error types in `Microsoft.CodeAnalysis.LanguageServer`'s compilation — its `InternalsVisibleTo`-granted internals become inaccessible (CS0122 ×20) — which in turn triggers the NullableWalker NRE reported in dotnet/roslyn#84398. With the identical tree resolving a 10.0.2xx SDK, the load is clean (declaration errors 21 → 0) and analysis completes.
## Environment
Windows 11 Pro (10.0.26200); SDKs installed: 9.0.305, 10.0.109, 10.0.204; `Microsoft.CodeAnalysis.Workspaces.MSBuild` 5.6.0; `Microsoft.Build.Locator` 1.11.2.
2 条评论