Skip to content

Commit a3e7ffa

Browse files
committed
Apply new F# null check guidelines and pin signatures
1 parent fd2c3cf commit a3e7ffa

File tree

16 files changed

+388
-294
lines changed

16 files changed

+388
-294
lines changed

docsrc/tools/doclib.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ module DocLib
44
// Copyright 2010 Steffen Forkmann
55
// Apache license
66

7-
7+
#nowarn "49"
88
open System.IO
99

1010
module String =

src/FSharpPlus/Extensions/Array.fs

Lines changed: 69 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,22 @@ module Array =
88

99
open System
1010
open FSharp.Core.CompilerServices
11-
open FSharpPlus.Internals.Errors
1211

1312
/// <summary>Adds an element to the beginning of the given array</summary>
1413
/// <param name="value">The element to add</param>
1514
/// <param name="array">The array to add to</param>
1615
/// <returns>A new array with the element added to the beginning.</returns>
17-
let cons value array =
18-
raiseIfNull (nameof(array)) array
16+
let cons value (array: 'T []) =
17+
let array = nullArgCheck (nameof array) array
1918
Array.insertAt 0 value array
2019

2120
/// <summary>Splits the array in head and tail.</summary>
2221
/// <param name="array">The input array.</param>
2322
/// <returns>A tuple with the head and the tail of the original array.</returns>
2423
/// <exception cref="T:System.ArgumentException">Thrown when the input array is empty.</exception>
25-
let uncons array =
26-
raiseIfNull (nameof(array)) array
27-
if Array.isEmpty array then invalidArg (nameof(array)) LanguagePrimitives.ErrorStrings.InputSequenceEmptyString
24+
let uncons (array: 'T []) =
25+
let array = nullArgCheck (nameof array) array
26+
if Array.isEmpty array then invalidArg (nameof array) LanguagePrimitives.ErrorStrings.InputSequenceEmptyString
2827
else array[0], array[1..]
2928

3029
/// <summary>Applies an array of functions to an array of values and concatenates them.</summary>
@@ -38,42 +37,48 @@ module Array =
3837
/// val it : int [] = [|2; 4; 6; 3; 6; 9|]
3938
/// </code>
4039
/// </example>
41-
let apply f x =
42-
raiseIfNull (nameof(x)) x
40+
let apply (f: ('T -> 'U) []) (x: 'T []) : 'U [] =
41+
let x = nullArgCheck (nameof x) x
4342

4443
let lenf, lenx = Array.length f, Array.length x
4544
Array.init (lenf * lenx) (fun i -> let (d, r) = Math.DivRem (i, lenx) in f.[d] x.[r])
4645

47-
/// Combines all values from the first array with the second, using the supplied mapping function.
48-
let lift2 f x y =
49-
raiseIfNull (nameof(x)) x
50-
raiseIfNull (nameof(y)) y
46+
/// <summary>Combines all values from three arrays and calls a mapping function on this combination.</summary>
47+
/// <param name="mapping">Mapping function taking three element combination as input.</param>
48+
/// <param name="array1">First array.</param>
49+
/// <param name="array2">Second array.</param>
50+
///
51+
/// <returns>Array with values returned from mapping function.</returns>
52+
let lift2 (mapping: 'T1 -> 'T2 -> 'U) (array1: 'T1 []) (array2: 'T2 []) : 'U [] =
53+
let array1 = nullArgCheck (nameof array1) array1
54+
let array2 = nullArgCheck (nameof array2) array2
5155

52-
let lenx, leny = Array.length x, Array.length y
53-
Array.init (lenx * leny) (fun i -> let (d, r) = Math.DivRem (i, leny) in f x.[d] y.[r])
56+
let lenx, leny = Array.length array1, Array.length array2
57+
Array.init (lenx * leny) (fun i -> let (d, r) = Math.DivRem (i, leny) in mapping array1.[d] array2.[r])
5458

5559

5660
/// <summary>Combines all values from three arrays and calls a mapping function on this combination.</summary>
5761
/// <param name="mapping">Mapping function taking three element combination as input.</param>
58-
/// <param name="list1">First array.</param>
59-
/// <param name="list2">Second array.</param>
60-
/// <param name="list3">Third array.</param>
62+
/// <param name="array1">First array.</param>
63+
/// <param name="array2">Second array.</param>
64+
/// <param name="array3">Third array.</param>
6165
///
6266
/// <returns>Array with values returned from mapping function.</returns>
63-
let lift3 mapping list1 list2 list3 =
64-
raiseIfNull (nameof(list1)) list1
65-
raiseIfNull (nameof(list2)) list2
66-
raiseIfNull (nameof(list3)) list3
67+
let lift3 (mapping: 'T1 -> 'T2 -> 'T3 -> 'U) (array1: 'T1 []) (array2: 'T2 []) (array3: 'T3 []) : 'U [] =
68+
let array1 = nullArgCheck (nameof array1) array1
69+
let array2 = nullArgCheck (nameof array2) array2
70+
let array3 = nullArgCheck (nameof array3) array3
6771

68-
let lenx, leny, lenz = Array.length list1, Array.length list2, Array.length list3
69-
let combinedFirstTwo = Array.init (lenx * leny) (fun i -> let (d, r) = Math.DivRem (i, leny) in (list1.[d], list2.[r]))
72+
let lenx, leny, lenz = Array.length array1, Array.length array2, Array.length array3
73+
let combinedFirstTwo = Array.init (lenx * leny) (fun i -> let (d, r) = Math.DivRem (i, leny) in (array1.[d], array2.[r]))
7074

71-
Array.init (lenx * leny * lenz) (fun i -> let (d, r) = Math.DivRem (i, lenz) in combinedFirstTwo.[d], list3.[r])
75+
Array.init (lenx * leny * lenz) (fun i -> let (d, r) = Math.DivRem (i, lenz) in combinedFirstTwo.[d], array3.[r])
7276
|> Array.map (fun x -> mapping (fst (fst x)) (snd (fst x)) (snd x))
7377

7478
/// Concatenates all elements, using the specified separator between each element.
75-
let intercalate (separator: 'T []) (source: seq<'T []>) =
76-
raiseIfNull (nameof(source)) source
79+
let intercalate (separator: 'T []) (source: seq<'T []>) : 'T [] =
80+
let separator = nullArgCheck (nameof separator) separator
81+
let source = nullArgCheck (nameof source) source
7782

7883
#if FABLE_COMPILER
7984
source |> Seq.intercalate separator |> Seq.toArray
@@ -88,8 +93,8 @@ module Array =
8893
#endif
8994

9095
/// Inserts a separator element between each element in the source array.
91-
let intersperse element (source: 'T []) =
92-
raiseIfNull (nameof(source)) source
96+
let intersperse element (source: 'T []) : 'T [] =
97+
let source = nullArgCheck (nameof source) source
9398

9499
match source with
95100
| [||] -> [||]
@@ -101,17 +106,17 @@ module Array =
101106
| _ -> element)
102107

103108
/// Creates a sequence of arrays by splitting the source array on any of the given separators.
104-
let split (separators: seq<_ []>) (source: _ []) =
105-
raiseIfNull (nameof(separators)) separators
106-
raiseIfNull (nameof(source)) source
109+
let split (separators: seq<'T []>) (source: 'T []) : seq<'T []> =
110+
let separators = nullArgCheck (nameof separators) separators
111+
let source = nullArgCheck (nameof source) source
107112

108113
source |> Array.toSeq |> Seq.split separators |> Seq.map Seq.toArray
109114

110115
/// Replaces a subsequence of the source array with the given replacement array.
111116
let replace (oldValue: 'T []) (newValue: 'T []) (source: 'T[]) : 'T[] =
112-
raiseIfNull (nameof(oldValue)) oldValue
113-
raiseIfNull (nameof(newValue)) newValue
114-
raiseIfNull (nameof(source)) source
117+
let oldValue = nullArgCheck (nameof oldValue) oldValue
118+
let newValue = nullArgCheck (nameof newValue) newValue
119+
let source = nullArgCheck (nameof source) source
115120

116121
#if FABLE_COMPILER
117122
source |> Array.toSeq |> Seq.replace oldValue newValue |> Seq.toArray: 'T []
@@ -178,9 +183,9 @@ module Array =
178183
/// <returns>
179184
/// The index of the slice or <c>None</c>.
180185
/// </returns>
181-
let findSliceIndex (slice: _ []) (source: _ []) =
182-
raiseIfNull (nameof(slice)) slice
183-
raiseIfNull (nameof(source)) source
186+
let findSliceIndex (slice: 'T []) (source: 'T []) : int =
187+
let slice = nullArgCheck (nameof slice) slice
188+
let source = nullArgCheck (nameof source) source
184189

185190
let index = Internals.FindSliceIndex.arrayImpl slice source
186191
if index = -1 then
@@ -195,9 +200,9 @@ module Array =
195200
/// <returns>
196201
/// The index of the slice or <c>None</c>.
197202
/// </returns>
198-
let tryFindSliceIndex (slice: _ []) (source: _ []) =
199-
raiseIfNull (nameof(slice)) slice
200-
raiseIfNull (nameof(source)) source
203+
let tryFindSliceIndex (slice: 'T []) (source: 'T []) : int option =
204+
let slice = nullArgCheck (nameof slice) slice
205+
let source = nullArgCheck (nameof source) source
201206

202207
let index = Internals.FindSliceIndex.arrayImpl slice source
203208
if index = -1 then None else Some index
@@ -209,9 +214,9 @@ module Array =
209214
/// <returns>
210215
/// The index of the slice or <c>None</c>.
211216
/// </returns>
212-
let findLastSliceIndex (slice: _ []) (source: _ []) =
213-
raiseIfNull (nameof(slice)) slice
214-
raiseIfNull (nameof(source)) source
217+
let findLastSliceIndex (slice: _ []) (source: _ []) : int =
218+
let slice = nullArgCheck (nameof slice) slice
219+
let source = nullArgCheck (nameof source) source
215220

216221
let index = Internals.FindLastSliceIndex.arrayImpl slice source
217222
if index = -1 then
@@ -226,9 +231,9 @@ module Array =
226231
/// <returns>
227232
/// The index of the slice or <c>None</c>.
228233
/// </returns>
229-
let tryFindLastSliceIndex (slice: _ []) (source: _ []) =
230-
raiseIfNull (nameof(slice)) slice
231-
raiseIfNull (nameof(source)) source
234+
let tryFindLastSliceIndex (slice: 'T []) (source: 'T []) : int option =
235+
let slice = nullArgCheck (nameof slice) slice
236+
let source = nullArgCheck (nameof source) source
232237

233238
let index = Internals.FindLastSliceIndex.arrayImpl slice source
234239
if index = -1 then None else Some index
@@ -241,8 +246,8 @@ module Array =
241246
/// <returns>
242247
/// A tuple with both resulting arrays.
243248
/// </returns>
244-
let partitionMap (mapper: 'T -> Choice<'T1,'T2>) (source: array<'T>) =
245-
raiseIfNull (nameof(source)) source
249+
let partitionMap (mapper: 'T -> Choice<'T1, 'T2>) (source: array<'T>) : array<'T1> * array<'T2> =
250+
let source = nullArgCheck (nameof source) source
246251

247252
let (x, y) = ResizeArray (), ResizeArray ()
248253
Array.iter (mapper >> function Choice1Of2 e -> x.Add e | Choice2Of2 e -> y.Add e) source
@@ -251,19 +256,19 @@ module Array =
251256
/// <summary>Safely build a new array whose elements are the results of applying the given function
252257
/// to each of the elements of the two arrays pairwise.</summary>
253258
/// <remark>If one array is shorter, excess elements are discarded from the right end of the longer array.</remark>
254-
let map2Shortest f (a1: 'T []) (a2: 'U []) =
255-
raiseIfNull (nameof(a1)) a1
256-
raiseIfNull (nameof(a2)) a2
259+
let map2Shortest (f: 'T1 -> 'T2 -> 'U) (a1: 'T1 []) (a2: 'T2 []) : 'U [] =
260+
let a1 = nullArgCheck (nameof a1) a1
261+
let a2 = nullArgCheck (nameof a2) a2
257262

258263
Array.init (min a1.Length a2.Length) (fun i -> f a1.[i] a2.[i])
259264

260265
/// <summary>Safely build a new array whose elements are the results of applying the given function
261266
/// to each of the elements of the three arrays pairwise.</summary>
262267
/// <remark>If one array is shorter, excess elements are discarded from the right end of the longer array.</remark>
263-
let map3Shortest f (a1: 'T1 []) (a2: 'T2 []) (a3: 'T3 []) =
264-
raiseIfNull (nameof a1) a1
265-
raiseIfNull (nameof a2) a2
266-
raiseIfNull (nameof a3) a3
268+
let map3Shortest (f: 'T1 -> 'T2 -> 'T3 -> 'U) (a1: 'T1 []) (a2: 'T2 []) (a3: 'T3 []) : 'U [] =
269+
let a1 = nullArgCheck (nameof a1) a1
270+
let a2 = nullArgCheck (nameof a2) a2
271+
let a3 = nullArgCheck (nameof a3) a3
267272
Array.init (min a1.Length a2.Length |> min a3.Length) (fun i -> f a1.[i] a2.[i] a3.[i])
268273

269274
/// <summary>
@@ -272,9 +277,9 @@ module Array =
272277
/// <param name="a1">First input array.</param>
273278
/// <param name="a2">Second input array.</param>
274279
/// <returns>Array with corresponding pairs of input arrays.</returns>
275-
let zipShortest (a1: array<'T1>) (a2: array<'T2>) =
276-
raiseIfNull (nameof(a1)) a1
277-
raiseIfNull (nameof(a2)) a2
280+
let zipShortest (a1: array<'T1>) (a2: array<'T2>) : array<'T1 * 'T2> =
281+
let a1 = nullArgCheck (nameof a1) a1
282+
let a2 = nullArgCheck (nameof a2) a2
278283

279284
Array.init (min a1.Length a2.Length) (fun i -> a1.[i], a2.[i])
280285

@@ -285,19 +290,19 @@ module Array =
285290
/// <param name="a2">Second input array.</param>
286291
/// <param name="a3">Third input array.</param>
287292
/// <returns>Array with corresponding tuple of input arrays.</returns>
288-
let zip3Shortest (a1: array<'T1>) (a2: array<'T2>) (a3: array<'T3>) =
289-
raiseIfNull (nameof a1) a1
290-
raiseIfNull (nameof a2) a2
291-
raiseIfNull (nameof a3) a3
293+
let zip3Shortest (a1: array<'T1>) (a2: array<'T2>) (a3: array<'T3>) : array<'T1 * 'T2 * 'T3> =
294+
let a1 = nullArgCheck (nameof a1) a1
295+
let a2 = nullArgCheck (nameof a2) a2
296+
let a3 = nullArgCheck (nameof a3) a3
292297
Array.init (min a1.Length a2.Length |> min a3.Length) (fun i -> a1.[i], a2.[i], a3.[i])
293298

294299
/// <summary>Same as choose but with access to the index.</summary>
295300
/// <param name="mapping">The mapping function, taking index and element as parameters.</param>
296301
/// <param name="source">The input array.</param>
297302
///
298303
/// <returns>Array with values x for each Array value where the function returns Some(x).</returns>
299-
let choosei mapping source =
300-
raiseIfNull (nameof(source)) source
304+
let choosei (mapping: int -> 'T -> 'U option) (source: array<'T>) : array<'U> =
305+
let source = nullArgCheck (nameof source) source
301306

302307
let mutable i = ref -1
303308
let fi x =

src/FSharpPlus/Extensions/Dict.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ module Dict =
1515

1616
/// <summary>Creates an empty dictionary.</summary>
1717
[<GeneralizableValue>]
18-
let empty<'Key, 'U when 'Key : equality> = printfn "creating"; Dictionary<'Key, 'U> () :> IDictionary<_,_>
18+
let empty<'Key, 'U when 'Key : equality and 'Key : not null> = printfn "creating"; Dictionary<'Key, 'U> () :> IDictionary<_,_>
1919

2020
/// <summary>Tries to get the value of the given key.</summary>
2121
/// <remarks>This is a function wrapper for the IDictionary.TryGetValue method,

src/FSharpPlus/Extensions/Dictionary.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ module Dictionary =
1616

1717
/// <summary>Creates an empty dictionary.</summary>
1818
[<GeneralizableValue>]
19-
let empty<'Key, 'U when 'Key : equality> = Dictionary<'Key, 'U> ()
19+
let empty<'Key, 'U when 'Key : equality and 'Key : not null> = Dictionary<'Key, 'U> ()
2020

2121
/// <summary>Tries to get the value of the given key.</summary>
2222
/// <remarks>Note: this is a function wrapper for the Dictionary.TryGetValue method,

src/FSharpPlus/Extensions/Enumerator.fs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
namespace FSharpPlus
22

3+
#nowarn "3261" // nullness checks
34
#if !FABLE_COMPILER
45

56
/// Additional operations on IEnumerator

src/FSharpPlus/Extensions/Exception.fs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,20 @@
55
module Exception =
66
open System
77
open System.Runtime.ExceptionServices
8-
open FSharpPlus.Internals.Errors
98

109
#if !FABLE_COMPILER
1110

1211
/// Throws the given exception with its original stacktrace.
1312
let inline rethrow<'T> (exn: exn) =
14-
raiseIfNull (nameof exn) exn
13+
let exn = nullArgCheck (nameof exn) exn
1514
(ExceptionDispatchInfo.Capture exn).Throw ()
1615
Unchecked.defaultof<'T>
1716

1817
/// Combines exceptions from 2 exceptions into a single AggregateException.
1918
/// Exceptions already present in the first argument won't be added.
2019
let add (exn1: exn) (exn2: exn) =
21-
raiseIfNull (nameof exn1) exn1
22-
raiseIfNull (nameof exn2) exn2
20+
let exn1 = nullArgCheck (nameof exn1) exn1
21+
let exn2 = nullArgCheck (nameof exn2) exn2
2322
let f (e: exn) =
2423
match e with
2524
:? AggregateException as a -> a.InnerExceptions :> seq<_>

src/FSharpPlus/Extensions/Extensions.fs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ module Extensions =
3939

4040
let private (|Canceled|Faulted|Completed|) (t: Task<'a>) =
4141
if t.IsCanceled then Canceled
42-
else if t.IsFaulted then Faulted t.Exception
42+
else if t.IsFaulted then Faulted (Unchecked.nonNull t.Exception)
4343
else Completed t.Result
4444

4545
type Task<'t> with
@@ -158,7 +158,7 @@ module Extensions =
158158
Async.FromContinuations (fun (sc, ec, cc) ->
159159
task.ContinueWith (fun (task: Task<'T>) ->
160160
if task.IsFaulted then
161-
let e = task.Exception
161+
let e = Unchecked.nonNull task.Exception
162162
if e.InnerExceptions.Count = 1 then ec e.InnerExceptions[0]
163163
else ec e
164164
elif task.IsCanceled then cc (TaskCanceledException ())
@@ -185,7 +185,7 @@ module Extensions =
185185
Async.FromContinuations (fun (sc, ec, cc) ->
186186
task.ContinueWith (fun (task: Task) ->
187187
if task.IsFaulted then
188-
let e = task.Exception
188+
let e = Unchecked.nonNull task.Exception
189189
if e.InnerExceptions.Count = 1 then ec e.InnerExceptions[0]
190190
else ec e
191191
elif task.IsCanceled then cc (TaskCanceledException ())

src/FSharpPlus/Extensions/HashSet.fs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
[<RequireQualifiedAccess>]
55
module HashSet =
66
open System.Collections.Generic
7-
open FSharpPlus.Internals.Errors
87

98
/// <summary>The empty set for the type 'T.</summary>
109
[<GeneralizableValue>]
@@ -31,8 +30,8 @@ module HashSet =
3130
/// <returns>The union of <c>set1</c> and <c>set2</c>.</returns>
3231
[<CompiledName("Union")>]
3332
let union (source1: HashSet<'T>) (source2: HashSet<'T>) : HashSet<'T> =
34-
raiseIfNull (nameof source1) source1
35-
raiseIfNull (nameof source2) source2
33+
let source1 = nullArgCheck (nameof source1) source1
34+
let source2 = nullArgCheck (nameof source2) source2
3635
let union =
3736
#if FABLE_COMPILER
3837
HashSet<'T> ()
@@ -50,7 +49,7 @@ module HashSet =
5049
/// <returns>A set containing the transformed elements.</returns>
5150
[<CompiledName("Map")>]
5251
let map (mapping: 'T -> 'U) (source: HashSet<'T>) : HashSet<'U> =
53-
raiseIfNull (nameof source) source
52+
let source = nullArgCheck (nameof source) source
5453
let result = empty<'U>
5554
for item in source do
5655
result.Add (mapping item) |> ignore
@@ -62,7 +61,7 @@ module HashSet =
6261
/// <returns><c>true</c> if the set contains <c>value</c>; otherwise, <c>false</c>.</returns>
6362
[<CompiledName("Contains")>]
6463
let contains (value: 'T) (source: HashSet<'T>) : bool =
65-
raiseIfNull (nameof source) source
64+
let source = nullArgCheck (nameof source) source
6665
source.Contains value
6766

6867
/// <summary>Determines whether the first set is a subset of the second set.</summary>
@@ -71,6 +70,6 @@ module HashSet =
7170
/// <returns><c>true</c> if <c>source1</c> is a subset of <c>source2</c>; otherwise, <c>false</c>.</returns>
7271
[<CompiledName("IsSubset")>]
7372
let isSubset (source1: HashSet<'T>) (source2: HashSet<'T>) : bool =
74-
raiseIfNull (nameof source1) source1
75-
raiseIfNull (nameof source2) source2
73+
let source1 = nullArgCheck (nameof source1) source1
74+
let source2 = nullArgCheck (nameof source2) source2
7675
source1.IsSubsetOf source2

0 commit comments

Comments
 (0)