diff --git a/docs/release-notes/.FSharp.Compiler.Service/11.0.0.md b/docs/release-notes/.FSharp.Compiler.Service/11.0.0.md index e1488ad72c1..6a2048ef27a 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/11.0.0.md +++ b/docs/release-notes/.FSharp.Compiler.Service/11.0.0.md @@ -2,6 +2,7 @@ * Scripts: Fix resolving the dotnet host path when an SDK directory is specified. ([PR #18960](https://github.com/dotnet/fsharp/pull/18960)) * Fix excessive StackGuard thread jumping ([PR #18971](https://github.com/dotnet/fsharp/pull/18971)) +* Adjust conservative method-overload duplicate detection rules for nativeptr types ([PR #18911](https://github.com/dotnet/fsharp/pull/18911)) * Checking: Fix checking nested fields for records and anonymous ([PR #18964](https://github.com/dotnet/fsharp/pull/18964)) * Fix name is bound multiple times is not reported in 'as' pattern ([PR #18984](https://github.com/dotnet/fsharp/pull/18984)) * Fix: warn FS0049 on upper union case label. ([PR #19003](https://github.com/dotnet/fsharp/pull/19003)) diff --git a/docs/release-notes/.Language/preview.md b/docs/release-notes/.Language/preview.md index fcec4b8170e..e5c2b65704f 100644 --- a/docs/release-notes/.Language/preview.md +++ b/docs/release-notes/.Language/preview.md @@ -16,5 +16,6 @@ * Warn on uppercase identifiers in patterns. ([PR #15816](https://github.com/dotnet/fsharp/pull/15816)) * Error on invalid declarations in type definitions.([Issue #10066](https://github.com/dotnet/fsharp/issues/10066), [PR #18813](https://github.com/dotnet/fsharp/pull/18813)) +* Fix type erasure logic for `nativeptr<'T>` overloads to properly preserve element type differences during duplicate member checking. ([Issue #](https://github.com/dotnet/fsharp/issues/), [PR #](https://github.com/dotnet/fsharp/pull/)) ### Changed diff --git a/src/Compiler/TypedTree/TypedTreeOps.fs b/src/Compiler/TypedTree/TypedTreeOps.fs index 15debb7621a..b50c5153886 100644 --- a/src/Compiler/TypedTree/TypedTreeOps.fs +++ b/src/Compiler/TypedTree/TypedTreeOps.fs @@ -799,7 +799,8 @@ let rec stripTyEqnsAndErase eraseFuncAndTuple (g: TcGlobals) ty = let reducedTy2 = addNullnessToTy nullness reducedTy stripTyEqnsAndErase eraseFuncAndTuple g reducedTy2 elif tyconRefEq g tcref g.nativeptr_tcr && eraseFuncAndTuple then - stripTyEqnsAndErase eraseFuncAndTuple g g.nativeint_ty + // Regression fix (issue #7428): nativeptr<'T> erases to ilsigptr<'T>, not nativeint + stripTyEqnsAndErase eraseFuncAndTuple g (TType_app(g.ilsigptr_tcr, args, nullness)) else ty diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/MemberDefinitions/OverloadingMembers/NativePtrOverloads01.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/MemberDefinitions/OverloadingMembers/NativePtrOverloads01.fs new file mode 100644 index 00000000000..d3274d2ac21 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/MemberDefinitions/OverloadingMembers/NativePtrOverloads01.fs @@ -0,0 +1,9 @@ +module NativePtrOverloads01 +open Microsoft.FSharp.NativeInterop +#nowarn "9" + +type P = + static member Do(p: nativeptr) = 1 + static member Do(p: nativeptr) = 2 + +let _invoke (pi: nativeptr) (pl: nativeptr) = P.Do pi + P.Do pl \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/MemberDefinitions/OverloadingMembers/NativePtrOverloads02.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/MemberDefinitions/OverloadingMembers/NativePtrOverloads02.fs new file mode 100644 index 00000000000..df9396e7381 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/MemberDefinitions/OverloadingMembers/NativePtrOverloads02.fs @@ -0,0 +1,7 @@ +module NativePtrOverloads02 +open Microsoft.FSharp.NativeInterop +#nowarn "9" + +type Q = + static member M(p: nativeptr) = 0 + static member M(p: nativeptr) = 1 // expect duplicate member error \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/MemberDefinitions/OverloadingMembers/NativePtrOverloads03.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/MemberDefinitions/OverloadingMembers/NativePtrOverloads03.fs new file mode 100644 index 00000000000..c0c43f4c4d9 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/MemberDefinitions/OverloadingMembers/NativePtrOverloads03.fs @@ -0,0 +1,8 @@ +module NativePtrOverloads03 +open Microsoft.FSharp.NativeInterop +#nowarn "9" +// Regression test for issue #7428 + +type R = + static member F(p: nativeptr) = 0us + static member F(p: nativeptr) = 0L \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/MemberDefinitions/OverloadingMembers/NativePtrOverloads04.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/MemberDefinitions/OverloadingMembers/NativePtrOverloads04.fs new file mode 100644 index 00000000000..75ed6354cc0 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/MemberDefinitions/OverloadingMembers/NativePtrOverloads04.fs @@ -0,0 +1,9 @@ +module NativePtrOverloads04 +open Microsoft.FSharp.NativeInterop +#nowarn "9" +[] type kg +[] type m + +type S = + static member H(p: nativeptr>) = 1 + static member H(p: nativeptr>) = 2 // expect duplicate member error \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/MemberDefinitions/OverloadingMembers/OverloadingMembers.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/MemberDefinitions/OverloadingMembers/OverloadingMembers.fs index e0b4c824187..bba418a78ee 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/MemberDefinitions/OverloadingMembers/OverloadingMembers.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/MemberDefinitions/OverloadingMembers/OverloadingMembers.fs @@ -235,3 +235,49 @@ module MemberDefinitions_OverloadingMembers = compilation |> verifyCompileAndRun |> shouldSucceed + + // Native pointer overload tests for regression fix + + // NativePtrOverloads01.fs - distinct native pointer element types should compile + [] + let ``NativePtrOverloads01_fs`` compilation = + compilation + |> asLibrary + |> withOptions ["--nowarn:9"] + |> compile + |> shouldSucceed + + // NativePtrOverloads02.fs - duplicate exact signatures should fail + [] + let ``NativePtrOverloads02_fs`` compilation = + compilation + |> asLibrary + |> withOptions ["--nowarn:9"] + |> compile + |> shouldFail + |> withDiagnostics [ + (Error 438, Line 7, Col 19, Line 7, Col 20, "Duplicate method. The method 'M' has the same name and signature as another method in type 'Q'.") + (Error 438, Line 6, Col 19, Line 6, Col 20, "Duplicate method. The method 'M' has the same name and signature as another method in type 'Q'.") + ] + + // NativePtrOverloads03.fs - regression test, previously failing overloads should now compile + [] + let ``NativePtrOverloads03_fs`` compilation = + compilation + |> asLibrary + |> withOptions ["--nowarn:9"] + |> compile + |> shouldSucceed + + // NativePtrOverloads04.fs - erased differences via measures should still fail + [] + let ``NativePtrOverloads04_fs`` compilation = + compilation + |> asLibrary + |> withOptions ["--nowarn:9"] + |> compile + |> shouldFail + |> withDiagnostics [ + (Error 438, Line 9, Col 19, Line 9, Col 20, "Duplicate method. The method 'H' has the same name and signature as another method in type 'S' once tuples, functions, units of measure and/or provided types are erased.") + (Error 438, Line 8, Col 19, Line 8, Col 20, "Duplicate method. The method 'H' has the same name and signature as another method in type 'S' once tuples, functions, units of measure and/or provided types are erased.") + ] diff --git a/tests/fsharp/typecheck/sigs/neg23.bsl b/tests/fsharp/typecheck/sigs/neg23.bsl index 8ed0fb67bff..906db67b8d2 100644 --- a/tests/fsharp/typecheck/sigs/neg23.bsl +++ b/tests/fsharp/typecheck/sigs/neg23.bsl @@ -11,14 +11,6 @@ neg23.fs(28,21,28,24): typecheck error FS0438: Duplicate method. The method 'Foo neg23.fs(26,21,26,24): typecheck error FS0438: Duplicate method. The method 'Foo' has the same name and signature as another method in type 'DuplicateOverloadUpToErasure3.SomeClass'. -neg23.fs(55,21,55,24): typecheck error FS0438: Duplicate method. The method 'Foo' has the same name and signature as another method in type 'DuplicateOverloadUpToErasure6.SomeClass' once tuples, functions, units of measure and/or provided types are erased. - -neg23.fs(53,21,53,24): typecheck error FS0438: Duplicate method. The method 'Foo' has the same name and signature as another method in type 'DuplicateOverloadUpToErasure6.SomeClass' once tuples, functions, units of measure and/or provided types are erased. - -neg23.fs(64,21,64,24): typecheck error FS0438: Duplicate method. The method 'Foo' has the same name and signature as another method in type 'DuplicateOverloadUpToErasure7.SomeClass' once tuples, functions, units of measure and/or provided types are erased. - -neg23.fs(62,21,62,24): typecheck error FS0438: Duplicate method. The method 'Foo' has the same name and signature as another method in type 'DuplicateOverloadUpToErasure7.SomeClass' once tuples, functions, units of measure and/or provided types are erased. - neg23.fs(76,9,76,11): typecheck error FS0410: The type 'IA' is less accessible than the value, member or type 'IB' it is used in. neg23.fs(83,18,83,20): typecheck error FS0439: The method 'X0' has curried arguments but has the same name as another method in type 'TestCurriedMemberRestrictions.C'. Methods with curried arguments cannot be overloaded. Consider using a method taking tupled arguments. diff --git a/tests/fsharp/typecheck/sigs/neg23.fs b/tests/fsharp/typecheck/sigs/neg23.fs index 94d66832ed4..1ec74e6163e 100644 --- a/tests/fsharp/typecheck/sigs/neg23.fs +++ b/tests/fsharp/typecheck/sigs/neg23.fs @@ -46,8 +46,8 @@ module DuplicateOverloadUpToErasure5 = begin member this.Foo (x:System.Tuple>) = printfn "method 2" end -module DuplicateOverloadUpToErasure6 = begin - +module NotAnyMoreDuplicateOverloadUpToErasure6 = begin + // This is not the same IL type, not a duplicate type SomeClass() = member this.Foo (x:nativeptr) = printfn "method 1" @@ -55,8 +55,8 @@ module DuplicateOverloadUpToErasure6 = begin member this.Foo (x:nativeint) = printfn "method 2" end -module DuplicateOverloadUpToErasure7 = begin - +module NotAnyMoreDuplicateOverloadUpToErasure7 = begin + // This is not the same IL type, not a duplicate type SomeClass() = member this.Foo (x:(int*int)*int*(int*nativeptr)*int*int) = printfn "method 1"