ITADN

.NET SDK 10.0.1xx design-time builds of net8.0-targeted projects resolve zero framework references (silent skeleton compilations under MSBuildWorkspace)

#84510Openbriansboyd 创建于 2026-07-09
BugArea-Analyzers
B
briansboydcommented
## 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 条评论