Fix accessibility and type-matching for generic extension method lookups#19536
Conversation
❗ Release notes required
|
…d extension lookups (CE, Dispose, etc.)
3f7dd89 to
170baf1
Compare
|
It seems that my changes broke FSharp.Core. I suppose that we have to adjust type equality check to work with the core code. |
… the new test case
T-Gro
left a comment
There was a problem hiding this comment.
⚠️ Automated Copilot Review — AI-assisted initial review. Feedback welcome.
[Breaking Changes] IsExtensionMethCompatibleWithTy has a logic gap in the TType_var branch: when the extension method's this parameter is a type variable with no CoercesTo constraint (unconstrained generic, or constrained only by struct/member/equality), the current code returns false and the method is silently excluded. This affects C# extensions like public static T Run<T>(this T x) and F# extensions with (this: 'T) or (this: 'T when 'T : struct). A type variable with no CoercesTo bounds should match any target type — the [] -> true fallback is missing.
[Test Coverage] All CE extension method tests use #SomeType (which always has a CoercesTo constraint). A test with a genuinely unconstrained 'T on the this parameter would catch the above bug.
…onstrains. Add test. Minor refactoring.
…9936) - Move IsExtensionMethCompatibleWithTy above ExtensionMethInfosOfTypeInScope. - Pass FormalMethodInst (not []) to GetObjArgTypes so IL method-typar this-args import successfully. Wrap in narrow try/with that rethrows OperationCanceledException for cancellable IDE paths. - Confine the AtMostOneResult short-circuit so dangling unindexed extensions only mask hierarchy-indexed candidates when at least one is compatible with the target type. AllResults branch preserved byte-identically. Regression from PR #19536 (issue #19349 fix). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Fixes #19349
-> Fix accessibility and type-matching for pattern-based extension lookups (CE, Dispose, etc.)
Summary
This PR fixes an issue where pattern-based extension method lookups (specifically for Computation Expressions and use bindings) would incorrectly resolve methods that are either inaccessible (private/internal) or belong to incompatible types.
Problem
Previously, the compiler's name resolution for CE-specific methods (like Bind, Delay, Run, etc.) and the Dispose pattern for resource cleanup was overly optimistic. It often bypassed accessibility checks, leading to incorrect method resolution or even compilation of calls to private extension methods from outside their scope.
Checklist