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 5c87eb88b88..0536119cfd6 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md +++ b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md @@ -48,6 +48,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)) * Fix parallel compilation of scripts ([PR #19649](https://github.com/dotnet/fsharp/pull/19649)) ### Added diff --git a/src/Compiler/Checking/NameResolution.fs b/src/Compiler/Checking/NameResolution.fs index de5dcff43ad..c380189f82a 100644 --- a/src/Compiler/Checking/NameResolution.fs +++ b/src/Compiler/Checking/NameResolution.fs @@ -4164,8 +4164,10 @@ let ResolveNestedField sink (ncenv: NameResolver) nenv ad recdTy lid = /// determine any valid members // // 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 private ResolveExprDotLongIdent (ncenv: NameResolver) m ad nenv ty (id: Ident) rest (typeNameResInfo: TypeNameResolutionInfo) findFlag staticOnly maybeArgExpr = + let lookupKind = + if staticOnly then LookupKind.Expr LookupIsInstance.No + else 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 _ -> @@ -4324,7 +4326,7 @@ let ResolveExprDotLongIdentAndComputeRange (sink: TcResultsSink) (ncenv: NameRes let resInfo, item, rest = match lid with | id :: rest -> - ResolveExprDotLongIdent ncenv wholem ad nenv ty id rest typeNameResInfo findFlag maybeAppliedArgExpr + ResolveExprDotLongIdent ncenv wholem ad nenv ty id rest typeNameResInfo findFlag staticOnly maybeAppliedArgExpr | _ -> error(InternalError("ResolveExprDotLongIdentAndComputeRange", wholem)) let itemRange = ComputeItemRange wholem lid rest resInfo, item, rest, itemRange 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..c6602a0f1be --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/MethodResolution/StaticMethodResolution.fs @@ -0,0 +1,41 @@ +// 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 = + + // Regression test for https://github.com/dotnet/fsharp/issues/19664 + // + // When a static extension method is defined in a *different* [] module than + // the generic type it extends, and shares its name with an intrinsic static member, + // resolving the call via the explicit-type-argument syntax `Type.Member(...)` + // previously failed with FS0505. The non-generic dotted form `Type.Member(...)` + // resolved correctly, so any regression test that omits the explicit type arguments + // does not actually exercise the bug. See the discussion at + // https://github.com/dotnet/fsharp/issues/19675#issuecomment-4373059900. + [] + let ``Static extension on generic type resolves with explicit type arguments``() = + Fsx """ +module Extensions = + + type StaticGeneric<'T> = + static member Bar() = () + static member Bar(_: int, _: int) = () + + [] + module StaticGenericExtensions = + type StaticGeneric<'T> with + static member Bar(_: int) = () + +module Program = + open Extensions + + StaticGeneric.Bar() // intrinsic, 0 args + StaticGeneric.Bar(42) // regressed: extension, 1 arg, see issue 19664 (FS0505) + StaticGeneric.Bar(42, 0) // intrinsic, 2 args + """ + |> typecheck + |> shouldSucceed \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/PropertyResolution/StaticPropertyResolution.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/PropertyResolution/StaticPropertyResolution.fs new file mode 100644 index 00000000000..33fe8740def --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/PropertyResolution/StaticPropertyResolution.fs @@ -0,0 +1,45 @@ +// 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 StaticPropertyResolution = + + // Regression test for static property accessors (getter/setter) resolution. + // Related to https://github.com/dotnet/fsharp/issues/19797 + // + // When a static extension 'set' or 'get' accessor is defined in a *different* module + // than the generic type it extends, and the corresponding property has the other intrinsic + // static accessor + // (i.e. the intrinsic property has a 'get' and the extension has a 'set', or vice versa) + // + // For instance, resolving the assignment via explicit-type-argument syntax, + // where the 'set' accessor is an extension and the 'get' accessor is intrinsic, + // Type.Property <- value previously failed with FS0810. + // + // The non-generic dotted form `Type.Member` + // resolved correctly, so any regression test that omits the explicit type arguments + // does not actually exercise the bug. See the discussion at + // https://github.com/dotnet/fsharp/issues/19675#issuecomment-4373059900. + [] + let ``Static property on generic type resolves the extension accessor when the other is intrinsic``() = + Fsx """ +module Lib = + + type Label<'T> = + static member Text with get() = "Static Intrinsic" + + [] + module Utils = + type Label<'T> with + static member Text with set (v) = printfn "Extension" + +module Program = + open Lib + + Label.Text <- "Text" // regressed: extension setter, see issue 19797 (FS0810) + """ + |> 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..9dcbc9c08b3 100644 --- a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj +++ b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj @@ -64,6 +64,8 @@ + +