From b680d3c0b6cb863cb93c3b43feecce652c9b323e Mon Sep 17 00:00:00 2001 From: Tomas Grosup Date: Wed, 2 Aug 2023 16:46:48 +0200 Subject: [PATCH] List.contains - change in order to inline + typespecialize (#15726) --- src/FSharp.Core/list.fs | 5 +- .../EmittedIL/Inlining/Inlining.fs | 53 +++++++++++++++++++ .../ListModule.fs | 12 +++++ 3 files changed, 69 insertions(+), 1 deletion(-) diff --git a/src/FSharp.Core/list.fs b/src/FSharp.Core/list.fs index e0dff3d7adb..8dcc7512b53 100644 --- a/src/FSharp.Core/list.fs +++ b/src/FSharp.Core/list.fs @@ -453,10 +453,13 @@ module List = [] let inline contains value source = + let equalityCheck listElement = + value = listElement + let rec contains e xs1 = match xs1 with | [] -> false - | h1 :: t1 -> e = h1 || contains e t1 + | h1 :: t1 -> equalityCheck h1 || contains e t1 contains value source diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Inlining/Inlining.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Inlining/Inlining.fs index 65f2fa37485..ea0d10857ff 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Inlining/Inlining.fs +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Inlining/Inlining.fs @@ -33,3 +33,56 @@ module Inlining = let ``StructUnion01_fs`` compilation = compilation |> verifyCompilation + + + [] + let ``List contains inlining`` () = + Fsx """module Test +let data = [nanf |> float;5.0;infinity] +let found = data |> List.contains nan + """ + |> asExe + |> compile + (* This is the essential aspect of the IL we are interested in - doing a direct specialized 'ceq' on primitive values, and not going via a GenericEqualityIntrinsic call*) + |> verifyIL [""" + .method assembly static bool contains@1(!!a e, + class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 xs1) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 4 + .locals init (class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 V_0, + class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 V_1, + float64 V_2) + IL_0000: ldarg.1 + IL_0001: call instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_TailOrNull() + IL_0006: brfalse.s IL_000a + + IL_0008: br.s IL_000c + + IL_000a: ldc.i4.0 + IL_000b: ret + + IL_000c: ldarg.1 + IL_000d: stloc.0 + IL_000e: ldloc.0 + IL_000f: call instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_TailOrNull() + IL_0014: stloc.1 + IL_0015: ldloc.0 + IL_0016: call instance !0 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_HeadOrDefault() + IL_001b: stloc.2 + IL_001c: ldc.r8 (00 00 00 00 00 00 F8 FF) + IL_0025: ldloc.2 + IL_0026: ceq + IL_0028: brfalse.s IL_002c + + IL_002a: ldc.i4.1 + IL_002b: ret + + IL_002c: ldarg.0 + IL_002d: ldloc.1 + IL_002e: starg.s xs1 + IL_0030: starg.s e + IL_0032: br.s IL_0000 + }"""] + diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/ListModule.fs b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/ListModule.fs index 0447dc741e0..fa245c76c87 100644 --- a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/ListModule.fs +++ b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/ListModule.fs @@ -1020,6 +1020,18 @@ type ListModule() = let resultStr = List.contains "....." strList Assert.False(resultStr) + // float List + let flList = [nan;infinity;5.0;-0.] + Assert.False(List.contains nan flList) + Assert.False(List.contains 4.99 flList) + Assert.True(List.contains infinity flList) + Assert.True(List.contains 0. flList) + + let flTupleList = [(nan,"text");(5.0,"wait")] + Assert.False(List.contains (nan,"text") flTupleList) + Assert.False(List.contains (5.0,"text") flTupleList) + Assert.True(List.contains (5.0,"wait") flTupleList) + // empty List let emptyList:int list = [ ] let resultEpt = List.contains 4 emptyList