Skip to content

Support .Select().Where() expression hoisting in LINQ#4125

Merged
jeremydmiller merged 1 commit intomasterfrom
linq-hoisting
Feb 11, 2026
Merged

Support .Select().Where() expression hoisting in LINQ#4125
jeremydmiller merged 1 commit intomasterfrom
linq-hoisting

Conversation

@jeremydmiller
Copy link
Member

Summary

  • Fixes V7 Select before Where no longer working #3009: .Select(x => x.Inner).Where(x => x.Value < 50) silently dropped the Where clause
  • Detects post-Select Where expressions in SelectOperator and rewrites them to reference the original document type through the Select member path
  • Handles both different-type selects (e.g., TargetAddress) and same-type selects (e.g., Target.Inner is Target)

How it works

Due to outermost-to-innermost expression tree traversal, operators after Select in user code are processed before the Select operator. At the time SelectOperator.Apply() runs, any WhereExpressions on the current CollectionUsage are from post-Select operators and need hoisting. A PostSelectExpressionRewriter (ExpressionVisitor) replaces ParameterExpression references of the projected type with the Select body MemberExpression, e.g. y.Value > 5 becomes x.Inner.Value > 5.

Test plan

  • 9 new integration tests in LinqTests/Bugs/Bug_3009_select_before_where.cs covering:
    • Different-type Select().Where()
    • Equivalence with Where().Select() (normal order)
    • Same-type Select().Where() (Target.Inner)
    • Multiple Where clauses after Select
    • String comparison in post-Select Where
    • FirstOrDefault terminal after Select().Where()
    • Count terminal after Select().Where()
    • Combined pre-Select and post-Select Where
    • Deep nested member Select (Level1.Level2) before Where
  • All 1201 existing LinqTests pass (6 pre-existing failures unrelated to this change)

🤖 Generated with Claude Code

When .Select(x => x.Inner).Where(x => x.Value < 50) was used, the Where
clause was silently dropped. This fixes the issue by detecting post-Select
Where expressions and rewriting them to reference the original document
type through the Select member path.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

V7 Select before Where no longer working

1 participant