Skip to content

osprey: Pin LangVersion to 14, which the tree already requires - #4594

Closed
maccoss wants to merge 1 commit into
masterfrom
Skyline/work/20260820_osprey_scoring_linq_build_fix
Closed

osprey: Pin LangVersion to 14, which the tree already requires#4594
maccoss wants to merge 1 commit into
masterfrom
Skyline/work/20260820_osprey_scoring_linq_build_fix

Conversation

@maccoss

@maccoss maccoss commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

What changed since the first version of this PR

The original premise was wrong, and Brendan was right to push back: master is not
broken.
It builds and tests green on TeamCity, in VS 2026, and on his machine. The
failure was mine, from building with the .NET 9 SDK.

This PR is now a one-property change that makes the real requirement explicit.

Diagnosis

Osprey.Scoring/PickLdaModel.cs validates a pick model's feature list:

if (dto.Features == null || dto.Features.Length != N ||
    !dto.Features.SequenceEqual(ExpectedFeatures))

Both operands are string[], and the file imports System but not System.Linq.

  • Under C# 14, string[] implicitly converts to ReadOnlySpan<string> in extension
    receiver position (the "first-class span types" feature), so this binds to
    System.MemoryExtensions.SequenceEqual, already covered by using System;. Adding
    using System.Linq; is redundant, which is why ReSharper flags it.
  • Under C# 13 and earlier, that conversion does not exist. The only candidate is
    System.Linq.Enumerable.SequenceEqual, which the file does not import, so it fails.

So Osprey has required C# 14, and therefore the .NET 10 SDK, since dd9e845 introduced
the file. <LangVersion>latest</LangVersion> concealed that: it means "whatever this SDK
supports", so the requirement was never stated and never checked.

Reproduced both directions on a clean origin/master worktree, no other change:

SDK latest resolves to Result
10.0.400 C# 14 builds clean, net472 and net8.0
9.0.315 C# 13 CS1061: 'string[]' does not contain a definition for 'SequenceEqual'

The diagnostic is the real problem here. It points at source that looks correct and says
nothing about language versions, so it reads as "master is broken" rather than "your SDK
is too old". That is exactly the wrong conclusion to hand a new contributor, or an agent.

The change

pwiz_tools/Osprey/Directory.Build.props: <LangVersion>latest</LangVersion> becomes
<LangVersion>14</LangVersion>, with a comment recording what requires it.

Now an SDK that cannot build Osprey says so directly:

error CS1617: Invalid option '14' for /langversion. Use '/langversion:?' to list supported values.

This also matches how the rest of the tree declares it. pwiz_tools/Directory.Build.props
pins 8.0; CommonFileDialogs, CommonMsData, PanoramaClient and BullseyeSharp pin
8.0 or 7.3. Osprey was the outlier in tracking whatever SDK was installed.

I have upgraded to the .NET 10.0.400 SDK, and everything below was re-verified on it.

Verification

  • .NET 10.0.400 SDK: Osprey.sln builds clean, 0 warnings, 0 errors
  • .NET 10.0.400 SDK: Osprey.Test 586/586 on net8.0, 586/586 on net472
  • .NET 9.0.315 SDK: build stops at CS1617, naming the actual cause

Not done here, worth deciding separately

  • A repo-root global.json would state the SDK floor once instead of leaving each project
    to imply it through LangVersion. That is a repo-wide call, not an Osprey one.
  • The other <LangVersion>latest</LangVersion> users (PortableUtil, the DevTools
    projects) may have picked up C# 13/14 dependencies the same way, without anyone
    choosing to. Worth an audit.

#4595 is stacked on this branch and has been rebased onto it.

See ai/todos/active/TODO-20260820_osprey_scoring_linq_build_fix.md.

@maccoss maccoss added the osprey Osprey / OspreySharp DIA proteomics search tool label Aug 20, 2026
Copilot AI lite review requested due to automatic review settings August 20, 2026 07:33

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes a build break in pwiz_tools/Osprey/Osprey.Scoring by restoring the missing LINQ import needed for SequenceEqual on string[] in PickLdaModel.LoadFromFile.

Changes:

  • Add using System.Linq; to enable dto.Features.SequenceEqual(ExpectedFeatures) to compile.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

* Osprey.Scoring/PickLdaModel.cs calls string[].SequenceEqual(string[]) with only
  "using System;" imported. That binds to System.MemoryExtensions.SequenceEqual through
  the C# 14 implicit span conversion in extension receiver position; under C# 13 and
  earlier the only candidate is System.Linq.Enumerable.SequenceEqual, which the file does
  not import. Osprey has therefore required C# 14, and the .NET 10 SDK, since dd9e845
* <LangVersion>latest</LangVersion> hid that: it resolves to whatever the installed SDK
  offers, so the same source built on VS 2026 and failed on a .NET 9 SDK with
  "CS1061: 'string[]' does not contain a definition for 'SequenceEqual'" pointing at
  unrelated-looking source. Naming the version fails instead as
  "CS1617: Invalid option '14' for /langversion", which says what is actually wrong
* Matches how the rest of pwiz_tools declares this: Directory.Build.props pins 8.0 and
  several csproj files pin 7.3 or 8.0, rather than tracking the SDK

Adding "using System.Linq;" was the other way to make the build work, but it is redundant
under C# 14 and ReSharper flags it, so it would not survive inspection.

Verified with the .NET 10.0.400 SDK: Osprey.sln builds clean, Osprey.Test passes 586/586
on net472 and net8.0. With the .NET 9.0.315 SDK the build now stops at CS1617.

See ai/todos/active/TODO-20260820_osprey_scoring_linq_build_fix.md

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@maccoss
maccoss force-pushed the Skyline/work/20260820_osprey_scoring_linq_build_fix branch from 928b319 to 8144386 Compare August 20, 2026 17:36
@maccoss maccoss changed the title osprey: Restore the using System.Linq that Osprey.Scoring needs to compile osprey: Pin LangVersion to 14, which the tree already requires Aug 20, 2026
@maccoss

maccoss commented Aug 20, 2026

Copy link
Copy Markdown
Contributor Author

Brendan is right - this was my machine, not master. I was building with the .NET 9 SDK.

Root cause, reproduced on a clean origin/master worktree with no other change: the
string[].SequenceEqual(string[]) call in PickLdaModel.cs binds to
System.MemoryExtensions.SequenceEqual under C# 14, through the first-class-spans
implicit conversion in extension receiver position, so using System; is enough. Under
C# 13 the only candidate is Enumerable.SequenceEqual and the file does not import
System.Linq, so it fails. SDK 10.0.400 builds it; SDK 9.0.315 gives CS1061.

That also explains the ReSharper warning - the using genuinely is redundant on your
toolchain, so adding it was the wrong fix.

I have dropped the using and repurposed this PR to pin <LangVersion>14</LangVersion> in
pwiz_tools/Osprey/Directory.Build.props, per Mike's suggestion. Osprey has required C# 14
since dd9e845; latest just meant nobody had to say so. With the pin, an old SDK fails
as CS1617: Invalid option '14' for /langversion instead of pointing at a line of source
that looks fine.

Re-verified on SDK 10.0.400: Osprey.sln clean, Osprey.Test 586/586 on net472 and
net8.0. #4595 has been rebased onto this.

Two things I did not do, in the PR description: a repo-root global.json, and an audit of
the other LangVersion=latest projects (PortableUtil, DevTools), which may have picked
up the same undeclared dependency.

Sorry for the noise - the branch name still says "linq_build_fix", which no longer
describes it. Happy to move this to a correctly named branch if you would rather.

@maccoss

maccoss commented Aug 20, 2026

Copy link
Copy Markdown
Contributor Author

Closing this - not needed.

The build requirement is already VS 2026 and the .NET 10 SDK, so latest resolves to C# 14
on every supported toolchain and pinning it declares nothing the team does not already
guarantee. The original failure was my machine running the .NET 9 SDK; I have upgraded to
10.0.400.

#4595 has been rebased off this branch and now targets master directly, so nothing
depends on it. Re-verified standalone on master with SDK 10.0.400: Osprey.sln builds
clean, Osprey.Test 589/589 on net472 and net8.0, and the gradient boosted trees remain
bit-identical to master's on the logistic path.

Recording the diagnosis here since it cost some time and will cost the next person the
same: Osprey.Scoring/PickLdaModel.cs calls string[].SequenceEqual(string[]) with only
using System; imported. Under C# 14 that binds to System.MemoryExtensions.SequenceEqual
via the first-class-spans implicit conversion in extension receiver position. Under C# 13
the only candidate is System.Linq.Enumerable.SequenceEqual, which the file does not
import, so an older SDK fails with

CS1061: 'string[]' does not contain a definition for 'SequenceEqual'

on a line that looks perfectly fine, naming neither the SDK nor the language version. So
Osprey has required C# 14 since dd9e845. Master is fine; the diagnostic is just
misleading if you show up with the wrong SDK.

Thanks Brendan for pushing back rather than letting the wrong fix through.

@maccoss maccoss closed this Aug 20, 2026
@maccoss
maccoss deleted the Skyline/work/20260820_osprey_scoring_linq_build_fix branch August 20, 2026 18:20
brendanx67 added a commit that referenced this pull request Aug 21, 2026
* The repo-root global.json pins the SDK to the 8.0.4xx band, whose compiler
  tops out at C# 12, while build.ps1 drives the VS toolset, which offers C# 14.
  LangVersion "latest" therefore meant a different language to each of Osprey's
  two build paths: the package.ps1 publish failed CS1061 on PickLdaModel.cs's
  string[].SequenceEqual, which binds to MemoryExtensions only under C# 14,
  seconds after the other path compiled the same file and passed 586 tests.
  That is why TeamCity fails here and never on master, which has no root
  global.json
* Added the using System.Linq that the C# 12 binding needs. Pinning is what
  makes it acceptable: ReSharper reports it redundant only while the language
  version is "latest", which is why PR #4594 dropped it and closed
* Verified both paths: Osprey.sln compiles, 586/586 tests pass, the win-x64
  publish succeeds, and the inspection reports nothing in PickLdaModel.cs

See ai/todos/active/TODO-20260818_commonutil_winforms_split.md

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TjTPKoE2UJrjnvwtqrQZsT
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

osprey Osprey / OspreySharp DIA proteomics search tool

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants