From 967b80cb8127a55f3b7aad9067428b63007cbf75 Mon Sep 17 00:00:00 2001 From: evgTSV Date: Thu, 7 May 2026 00:13:37 +0500 Subject: [PATCH 1/5] Fix #19664: Extension static methods are resolved if similar intrisic methods exist --- src/Compiler/Checking/NameResolution.fs | 8 ++--- .../StaticMethodResolution.fs | 32 +++++++++++++++++++ .../FSharp.Compiler.ComponentTests.fsproj | 1 + 3 files changed, 35 insertions(+), 6 deletions(-) create mode 100644 tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/MethodResolution/StaticMethodResolution.fs diff --git a/src/Compiler/Checking/NameResolution.fs b/src/Compiler/Checking/NameResolution.fs index de5dcff43ad..7363309ec92 100644 --- a/src/Compiler/Checking/NameResolution.fs +++ b/src/Compiler/Checking/NameResolution.fs @@ -4165,7 +4165,7 @@ let ResolveNestedField sink (ncenv: NameResolver) nenv ad recdTy lid = // // QUERY (instantiationGenerator cleanup): it would be really nice not to flow instantiationGenerator to here. let private ResolveExprDotLongIdent (ncenv: NameResolver) m ad nenv ty (id: Ident) rest (typeNameResInfo: TypeNameResolutionInfo) findFlag maybeArgExpr = - let lookupKind = LookupKind.Expr LookupIsInstance.Yes + let lookupKind = LookupKind.Expr LookupIsInstance.Ambivalent let adhocDotSearchAccessible = AtMostOneResult m (ResolveLongIdentInTypePrim ncenv nenv lookupKind ResolutionInfo.Empty 1 m ad id rest findFlag typeNameResInfo ty maybeArgExpr) match adhocDotSearchAccessible with | Exception _ -> @@ -4184,11 +4184,7 @@ let private ResolveExprDotLongIdent (ncenv: NameResolver) m ad nenv ty (id: Iden OneSuccess (ResolutionInfo.Empty, item, rest) | _ -> NoResultsOrUsefulErrors - let adhocDotSearchAll () = - let lookupKind = LookupKind.Expr LookupIsInstance.Ambivalent - ResolveLongIdentInTypePrim ncenv nenv lookupKind ResolutionInfo.Empty 1 m AccessibleFromSomeFSharpCode id rest findFlag typeNameResInfo ty None - - dotFieldIdSearch +++ adhocDotSearchAll + dotFieldIdSearch |> AtMostOneResult m |> ForceRaise | _ -> diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/MethodResolution/StaticMethodResolution.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/MethodResolution/StaticMethodResolution.fs new file mode 100644 index 00000000000..4d0b0b41390 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/MethodResolution/StaticMethodResolution.fs @@ -0,0 +1,32 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace Conformance.BasicGrammarElements + +open FSharp.Test.Compiler +open Xunit + +module StaticMethodResolution = + + // So that the compiler doesn't treat an extension method as intrisic + // we place a method to another module. + [] + let ``Extension static method is resolved correctly when one or many intrisic candidates are found``() = + Fsx """ +module Extensions = + + type StaticGeneric<'T>() = + static member Bar() = () + + [] + module StaticGenericExtensions = + type StaticGeneric<'T> with + static member Bar(_: int) = () + +module Program = + open Extensions + + StaticGeneric.Bar(42) // StaticGeneric is just an ident + StaticGeneric.Bar(42) // StaticGeneric is an expression + """ + |> typecheck + |> shouldSucceed \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj index aa5a5cc11f2..5e7285236d6 100644 --- a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj +++ b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj @@ -64,6 +64,7 @@ + From 24e7b57a13c8d933f419ed71539b53e7c7e74397 Mon Sep 17 00:00:00 2001 From: evgTSV Date: Thu, 7 May 2026 00:37:48 +0500 Subject: [PATCH 2/5] Fix typos --- .../MethodResolution/StaticMethodResolution.fs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/MethodResolution/StaticMethodResolution.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/MethodResolution/StaticMethodResolution.fs index 4d0b0b41390..2627400d2d4 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/MethodResolution/StaticMethodResolution.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/MethodResolution/StaticMethodResolution.fs @@ -7,10 +7,10 @@ open Xunit module StaticMethodResolution = - // So that the compiler doesn't treat an extension method as intrisic + // So that the compiler doesn't treat an extension method as intrinsic // we place a method to another module. [] - let ``Extension static method is resolved correctly when one or many intrisic candidates are found``() = + let ``Extension static method is resolved correctly when one or many intrinsic candidates are found``() = Fsx """ module Extensions = From 2e1d15671cf6e5ab044d5f5d257f7039fb09a759 Mon Sep 17 00:00:00 2001 From: evgTSV Date: Thu, 7 May 2026 00:46:45 +0500 Subject: [PATCH 3/5] Add a record to the release notes --- docs/release-notes/.FSharp.Compiler.Service/11.0.100.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md index c4750e59e1f..a58b2c0b598 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md +++ b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md @@ -47,6 +47,7 @@ * Fix signature generation: SRTP constraints use postfix syntax that fails conformance, now uses explicit type param declarations. ([Issue #19594](https://github.com/dotnet/fsharp/issues/19594), [PR #19609](https://github.com/dotnet/fsharp/pull/19609)) * Fix signature generation: type params with special characters missing backtick escaping. ([Issue #19595](https://github.com/dotnet/fsharp/issues/19595), [PR #19609](https://github.com/dotnet/fsharp/pull/19609)) * Fix internal error when using custom attribute with `[]` value type parameter and no `[]`. ([Issue #8353](https://github.com/dotnet/fsharp/issues/8353), [PR #19484](https://github.com/dotnet/fsharp/pull/19484)) +* Fix overload resolution of static member extension if one or more intrinsics candidates exist ([Issue #19664](https://github.com/dotnet/fsharp/issues/19664), [PR #19698](https://github.com/dotnet/fsharp/pull/19698)) ### Added From 8095590f3928897ab421b244473d1735f1d16e95 Mon Sep 17 00:00:00 2001 From: evgTSV Date: Sun, 10 May 2026 16:17:01 +0500 Subject: [PATCH 4/5] Make isInstanceFilter ambivalent if either static meth when Yes or instance meth when No is found --- src/Compiler/Checking/NameResolution.fs | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/Compiler/Checking/NameResolution.fs b/src/Compiler/Checking/NameResolution.fs index 7363309ec92..9357299f0bd 100644 --- a/src/Compiler/Checking/NameResolution.fs +++ b/src/Compiler/Checking/NameResolution.fs @@ -2874,6 +2874,20 @@ let rec ResolveLongIdentInTypePrim (ncenv: NameResolver) nenv lookupKind (resInf | Some(MethodItem msets) when isLookUpExpr -> let minfos = msets |> ExcludeHiddenOfMethInfos g ncenv.amap m + let isAmbivalent = + minfos + |> List.exists (fun minfo -> + match isInstanceFilter with + | LookupIsInstance.Yes -> not minfo.IsInstance + | LookupIsInstance.No -> minfo.IsInstance + | LookupIsInstance.Ambivalent -> true) + + let isInstanceFilter = + if isAmbivalent then + LookupIsInstance.Ambivalent + else + isInstanceFilter + // fold the available extension members into the overload resolution let extensionMethInfos = ExtensionMethInfosOfTypeInScope ResultCollectionSettings.AllResults ncenv.InfoReader nenv ad optFilter isInstanceFilter m ty @@ -4165,7 +4179,7 @@ let ResolveNestedField sink (ncenv: NameResolver) nenv ad recdTy lid = // // QUERY (instantiationGenerator cleanup): it would be really nice not to flow instantiationGenerator to here. let private ResolveExprDotLongIdent (ncenv: NameResolver) m ad nenv ty (id: Ident) rest (typeNameResInfo: TypeNameResolutionInfo) findFlag maybeArgExpr = - let lookupKind = LookupKind.Expr LookupIsInstance.Ambivalent + let lookupKind = LookupKind.Expr LookupIsInstance.Yes let adhocDotSearchAccessible = AtMostOneResult m (ResolveLongIdentInTypePrim ncenv nenv lookupKind ResolutionInfo.Empty 1 m ad id rest findFlag typeNameResInfo ty maybeArgExpr) match adhocDotSearchAccessible with | Exception _ -> @@ -4184,7 +4198,11 @@ let private ResolveExprDotLongIdent (ncenv: NameResolver) m ad nenv ty (id: Iden OneSuccess (ResolutionInfo.Empty, item, rest) | _ -> NoResultsOrUsefulErrors - dotFieldIdSearch + let adhocDotSearchAll () = + let lookupKind = LookupKind.Expr LookupIsInstance.Ambivalent + ResolveLongIdentInTypePrim ncenv nenv lookupKind ResolutionInfo.Empty 1 m AccessibleFromSomeFSharpCode id rest findFlag typeNameResInfo ty None + + dotFieldIdSearch +++ adhocDotSearchAll |> AtMostOneResult m |> ForceRaise | _ -> From 403cb8275ff789da347107672a38a54ddf93193a Mon Sep 17 00:00:00 2001 From: evgTSV Date: Sun, 10 May 2026 16:55:15 +0500 Subject: [PATCH 5/5] Fix tests --- .../MethodResolution/StaticMethodResolution.fs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/MethodResolution/StaticMethodResolution.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/MethodResolution/StaticMethodResolution.fs index 2627400d2d4..6f2f48f209a 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/MethodResolution/StaticMethodResolution.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/MethodResolution/StaticMethodResolution.fs @@ -28,5 +28,6 @@ module Program = StaticGeneric.Bar(42) // StaticGeneric is just an ident StaticGeneric.Bar(42) // StaticGeneric is an expression """ + |> withOptions ["--nowarn:1125"] |> typecheck |> shouldSucceed \ No newline at end of file