[Code review] Compiler changes for extension members on typeless receivers#83407
Draft
CyrusNajmabadi wants to merge 7 commits intodotnet:mainfrom
Draft
Conversation
…view-only)
Combines the production code from all stacked support PRs into a single
commit for end-to-end review. Excludes the new test files added by the
test PRs in the stack; only the binder, feature-flag, and necessary
obsolete-test expectation updates are here.
Files in scope:
- Binder_Expressions.cs: TryBindMemberAccessOnTypelessReceiver helper +
inclusion list, GetExtensionMemberAccess relaxation, BindInstanceMember
Access typeless-leftType branch, ResolveExtension assertion / pruning
relaxations.
- Binder_Invocation.cs: skip ReplaceTypeOrValueReceiver for typeless
extension receivers (covers both classic and modern extension paths).
- ConversionsBase.cs: classic-extension this-arg conversion fallback to
ClassifyImplicitConversionFromExpression for typeless source.
- OverloadResolution.cs: skip strict identity/reference/boxing whitelist
when the extension this-arg has no type.
- MessageID + resx + 13 xlf: IDS_FeatureExtensionMembersOnTypelessReceivers
feature flag.
- CollectionExpressionTests.cs: 8 obsolete pre-feature error expectations
updated to match the new feature behavior.
Co-authored-by: Isaac
289aae3 to
87da92e
Compare
added 6 commits
April 26, 2026 02:19
Aligns the typeless-extension feature gate with GetMethodGroupDelegateType so we treat the same set of method groups as "valid receiver" in both places, and excludes inaccessible / ambiguous lookups that the previous LookupError-only check let through. Co-authored-by: Isaac
… feature gate
Previously, every member access on a supported typeless form
(`[expr].M`, `(() => {}).M`, etc.) routed through the new feature path,
which meant any unrelated typo on a typeless receiver got the misleading
"feature is in Preview, upgrade to use it" diagnostic on older language
versions even when no extension would have applied.
Now the helper first checks whether at least one extension member named
`M` is in scope. If not, it returns null and lets the existing
kind-specific rejections produce their pre-feature diagnostics. If a
candidate exists, the feature gate fires and binding proceeds - even
when the call ultimately fails on argument matching, the user did write
a typeless-extension call and should be told why it requires a
language-version upgrade.
Co-authored-by: Isaac
…GroupReceiver doc - Move typeArgumentsSyntax / typeArgumentsWithAnnotations past the speculative HasExtensionMemberCandidateInScope check so we don't pay BindTypeArguments when speculation returns null. - Collapse the type-args conditionals onto single lines using property-pattern matching. - Clarify IsValidMethodGroupReceiver doc comment - it's the same conceptual ResultKind == Viable gate that GetUniqueSignatureFromMethodGroup applies inline, not a shared helper. Co-authored-by: Isaac
The helper was a single boolean expression; inlining it as a property
pattern (`when boundLeft is BoundMethodGroup { ResultKind: Viable,
Methods.Length: > 0 }`) keeps the switch self-contained and removes
indirection. The reasoning that previously lived in the helper's doc
comment moves to a comment above the case.
Co-authored-by: Isaac
For the new code in TryBindMemberAccessOnTypelessReceiver and HasExtensionMemberCandidateInScope: - Single-line condition + single-line body if-statements no longer wrap the body in braces. - Block-like statements are followed by a blank line unless they are the last statement before a closing brace. Co-authored-by: Isaac
…s receiver BindMethodGroupInvocation's dynamic-extension error path asserted that methodGroup.ReceiverOpt.Type was non-null when emitting CS1973 (ERR_BadArgTypeDynamicExtension). For typeless receivers that's never true, so debug builds tripped the assert before the diagnostic was emitted. Fall back to the receiver's Display string when Type is null and force the receiver through BindToNaturalType so flow analysis doesn't trip on an unconverted child. Co-authored-by: Isaac
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Championed issue: TBD
Speclet: TBD
Test plan: TBD
Summary
Internal review aid. Combines the production code changes from the entire stack of upstream draft PRs into a single self-contained commit so the binder + feature flag changes can be reviewed end-to-end without sifting through test additions. Will be closed once the code is approved; the upstream stack remains intact.
Scope (20 files, no new test files):
Mirrors the union of the code in:
Microsoft Reviewers: Open in CodeFlow