From baa13576174af7fb94641591954580e481875199 Mon Sep 17 00:00:00 2001 From: gusty <1261319+gusty@users.noreply.github.com> Date: Sat, 28 Oct 2023 18:45:08 +0200 Subject: [PATCH 1/4] + Failing test --- .../IWSAMsAndSRTPs/IWSAMsAndSRTPsTests.fs | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/Types/TypeConstraints/IWSAMsAndSRTPs/IWSAMsAndSRTPsTests.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/Types/TypeConstraints/IWSAMsAndSRTPs/IWSAMsAndSRTPsTests.fs index 63c78877f81..5547b5b11c3 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/Types/TypeConstraints/IWSAMsAndSRTPs/IWSAMsAndSRTPsTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/Types/TypeConstraints/IWSAMsAndSRTPs/IWSAMsAndSRTPsTests.fs @@ -831,3 +831,30 @@ let main _ = |> compile |> shouldFail |> withErrorMessage $"The type 'float' is not compatible with the type '{potatoType}'" + + [] + let ``Interface A with static abstracts can be inherited in interface B and then implemented in type C which inherits B in lang version70`` () = + Fsx """ + type IParseable<'T when 'T :> IParseable<'T>> = + static abstract member Parse : string -> 'T + + type IAction<'T when 'T :> IAction<'T>> = + inherit IParseable<'T> + + type SomeAction = A | B with + interface IAction with + static member Parse (s: string) : SomeAction = + match s with + | "A" -> A + | "B" -> B + | _ -> failwith "can't parse" + + let parse<'T when 'T :> IParseable<'T>> (x: string) : 'T = 'T.Parse x + + if parse "A" <> A then + failwith "failed" + """ + |> withNoWarn 3535 + |> withLangVersion70 + |> compile + |> shouldSucceed From 769710e94b28d94153687c2189496609ba56f794 Mon Sep 17 00:00:00 2001 From: gusty <1261319+gusty@users.noreply.github.com> Date: Sat, 28 Oct 2023 18:49:44 +0200 Subject: [PATCH 2/4] Generate fixups for static abstracts --- src/Compiler/CodeGen/IlxGen.fs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Compiler/CodeGen/IlxGen.fs b/src/Compiler/CodeGen/IlxGen.fs index 33b39ce7f73..a987b78abc3 100644 --- a/src/Compiler/CodeGen/IlxGen.fs +++ b/src/Compiler/CodeGen/IlxGen.fs @@ -9212,7 +9212,13 @@ and GenMethodForBinding if not memberInfo.MemberFlags.IsOverrideOrExplicitImpl then mkILStaticMethod (ilMethTypars, mspec.Name, access, ilParams, ilReturn, ilMethodBody) else // We want to get potential fixups and hidebysig for abstract statics: - let flagFixups = [ fixupStaticAbstractSlotFlags ] + let flagFixups = + [ + fixupStaticAbstractSlotFlags + match ComputeMethodImplNameFixupForMemberBinding cenv v with + | Some nm -> renameMethodDef nm + | None -> () + ] let mdef = mkILStaticMethod (ilMethTypars, mspec.Name, access, ilParams, ilReturn, ilMethodBody) From cbcbf5cc5adf3d0a744a4d95e491325db8368b9f Mon Sep 17 00:00:00 2001 From: gusty <1261319+gusty@users.noreply.github.com> Date: Sat, 28 Oct 2023 18:50:12 +0200 Subject: [PATCH 3/4] + Multilevel test --- .../IWSAMsAndSRTPs/IWSAMsAndSRTPsTests.fs | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/Types/TypeConstraints/IWSAMsAndSRTPs/IWSAMsAndSRTPsTests.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/Types/TypeConstraints/IWSAMsAndSRTPs/IWSAMsAndSRTPsTests.fs index 5547b5b11c3..22cc77d75ae 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/Types/TypeConstraints/IWSAMsAndSRTPs/IWSAMsAndSRTPsTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/Types/TypeConstraints/IWSAMsAndSRTPs/IWSAMsAndSRTPsTests.fs @@ -858,3 +858,42 @@ let main _ = |> withLangVersion70 |> compile |> shouldSucceed + + [] + let ``Static abstracts can be inherited through multiple levels in lang version70`` () = + Fsx """ + type IParseable<'T when 'T :> IParseable<'T>> = + static abstract member Parse : string -> 'T + + type IAction1<'T when 'T :> IAction1<'T>> = + inherit IParseable<'T> + + type IAction2<'T when 'T :> IAction2<'T>> = + inherit IAction1<'T> + static abstract member AltParse : string -> 'T + + type IAction3<'T when 'T :> IAction3<'T>> = + inherit IAction2<'T> + + type SomeAction = A | B with + interface IAction3 with + static member AltParse (s: string) : SomeAction = A + static member Parse (s: string) : SomeAction = + match s with + | "A" -> A + | "B" -> B + | _ -> failwith "can't parse" + + let parse<'T when 'T :> IParseable<'T>> (x: string) : 'T = 'T.Parse x + let altParse<'T when 'T :> IAction3<'T>> (x: string) : 'T = 'T.AltParse x + + let x: SomeAction = parse "A" + let y: SomeAction = altParse "A" + + if x <> A || y <> A then + failwith "failed" + """ + |> withNoWarn 3535 + |> withLangVersion70 + |> compile + |> shouldSucceed From 526d65c9b0b7f7a58e6f15abef31afe1f669fb77 Mon Sep 17 00:00:00 2001 From: gusty <1261319+gusty@users.noreply.github.com> Date: Mon, 30 Oct 2023 07:33:56 +0100 Subject: [PATCH 4/4] + Test with BCL interface --- .../IWSAMsAndSRTPs/IWSAMsAndSRTPsTests.fs | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/Types/TypeConstraints/IWSAMsAndSRTPs/IWSAMsAndSRTPsTests.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/Types/TypeConstraints/IWSAMsAndSRTPs/IWSAMsAndSRTPsTests.fs index 22cc77d75ae..77787d5a256 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/Types/TypeConstraints/IWSAMsAndSRTPs/IWSAMsAndSRTPsTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/Types/TypeConstraints/IWSAMsAndSRTPs/IWSAMsAndSRTPsTests.fs @@ -897,3 +897,28 @@ let main _ = |> withLangVersion70 |> compile |> shouldSucceed + + [] + let ``Static abstracts from BCL can be inherited through multiple levels in lang version70`` () = + Fsx """ + open System + open System.Globalization + + type Person = Person with + interface ISpanParsable with + static member Parse(_x: string, _provider: IFormatProvider) = Person + static member TryParse(_x: string, _provider: IFormatProvider, _result: byref) = true + + static member Parse(_x: ReadOnlySpan, _provider: IFormatProvider) = Person + static member TryParse(_x: ReadOnlySpan, _provider: IFormatProvider, _result: byref) = true + + let parse<'T when 'T :> IParsable<'T>> (x: string) : 'T = 'T.Parse (x, CultureInfo.InvariantCulture) + + let x: Person = parse "Something" + if x <> Person then + failwith "failed" + """ + |> withNoWarn 3535 + |> withLangVersion70 + |> compile + |> shouldSucceed