Skip to content

Commit e4c53b4

Browse files
authored
Use nullArgCheck and pin signatures (#653)
1 parent fd2c3cf commit e4c53b4

File tree

13 files changed

+397
-284
lines changed

13 files changed

+397
-284
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 & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,17 @@ module Array =
1414
/// <param name="value">The element to add</param>
1515
/// <param name="array">The array to add to</param>
1616
/// <returns>A new array with the element added to the beginning.</returns>
17-
let cons value array =
18-
raiseIfNull (nameof(array)) array
17+
let cons value (array: 'T []) =
18+
let array = nullArgCheck (nameof array) array
1919
Array.insertAt 0 value array
2020

2121
/// <summary>Splits the array in head and tail.</summary>
2222
/// <param name="array">The input array.</param>
2323
/// <returns>A tuple with the head and the tail of the original array.</returns>
2424
/// <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
25+
let uncons (array: 'T []) =
26+
let array = nullArgCheck (nameof array) array
27+
if Array.isEmpty array then invalidArg (nameof array) LanguagePrimitives.ErrorStrings.InputSequenceEmptyString
2828
else array[0], array[1..]
2929

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

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

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
47+
/// <summary>Combines all values from three arrays and calls a mapping function on this combination.</summary>
48+
/// <param name="mapping">Mapping function taking three element combination as input.</param>
49+
/// <param name="array1">First array.</param>
50+
/// <param name="array2">Second array.</param>
51+
///
52+
/// <returns>Array with values returned from mapping function.</returns>
53+
let lift2 (mapping: 'T1 -> 'T2 -> 'U) (array1: 'T1 []) (array2: 'T2 []) : 'U [] =
54+
let array1 = nullArgCheck (nameof array1) array1
55+
let array2 = nullArgCheck (nameof array2) array2
5156

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])
57+
let lenx, leny = Array.length array1, Array.length array2
58+
Array.init (lenx * leny) (fun i -> let (d, r) = Math.DivRem (i, leny) in mapping array1.[d] array2.[r])
5459

5560

5661
/// <summary>Combines all values from three arrays and calls a mapping function on this combination.</summary>
5762
/// <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>
63+
/// <param name="array1">First array.</param>
64+
/// <param name="array2">Second array.</param>
65+
/// <param name="array3">Third array.</param>
6166
///
6267
/// <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
68+
let lift3 (mapping: 'T1 -> 'T2 -> 'T3 -> 'U) (array1: 'T1 []) (array2: 'T2 []) (array3: 'T3 []) : 'U [] =
69+
let array1 = nullArgCheck (nameof array1) array1
70+
let array2 = nullArgCheck (nameof array2) array2
71+
let array3 = nullArgCheck (nameof array3) array3
6772

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]))
73+
let lenx, leny, lenz = Array.length array1, Array.length array2, Array.length array3
74+
let combinedFirstTwo = Array.init (lenx * leny) (fun i -> let (d, r) = Math.DivRem (i, leny) in (array1.[d], array2.[r]))
7075

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

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

7884
#if FABLE_COMPILER
7985
source |> Seq.intercalate separator |> Seq.toArray
@@ -88,8 +94,8 @@ module Array =
8894
#endif
8995

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

94100
match source with
95101
| [||] -> [||]
@@ -101,17 +107,17 @@ module Array =
101107
| _ -> element)
102108

103109
/// 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
110+
let split (separators: seq<'T []>) (source: 'T []) : seq<'T []> =
111+
let separators = nullArgCheck (nameof separators) separators
112+
let source = nullArgCheck (nameof source) source
107113

108114
source |> Array.toSeq |> Seq.split separators |> Seq.map Seq.toArray
109115

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

116122
#if FABLE_COMPILER
117123
source |> Array.toSeq |> Seq.replace oldValue newValue |> Seq.toArray: 'T []
@@ -178,9 +184,9 @@ module Array =
178184
/// <returns>
179185
/// The index of the slice or <c>None</c>.
180186
/// </returns>
181-
let findSliceIndex (slice: _ []) (source: _ []) =
182-
raiseIfNull (nameof(slice)) slice
183-
raiseIfNull (nameof(source)) source
187+
let findSliceIndex (slice: 'T []) (source: 'T []) : int =
188+
let slice = nullArgCheck (nameof slice) slice
189+
let source = nullArgCheck (nameof source) source
184190

185191
let index = Internals.FindSliceIndex.arrayImpl slice source
186192
if index = -1 then
@@ -195,9 +201,9 @@ module Array =
195201
/// <returns>
196202
/// The index of the slice or <c>None</c>.
197203
/// </returns>
198-
let tryFindSliceIndex (slice: _ []) (source: _ []) =
199-
raiseIfNull (nameof(slice)) slice
200-
raiseIfNull (nameof(source)) source
204+
let tryFindSliceIndex (slice: 'T []) (source: 'T []) : int option =
205+
let slice = nullArgCheck (nameof slice) slice
206+
let source = nullArgCheck (nameof source) source
201207

202208
let index = Internals.FindSliceIndex.arrayImpl slice source
203209
if index = -1 then None else Some index
@@ -209,9 +215,9 @@ module Array =
209215
/// <returns>
210216
/// The index of the slice or <c>None</c>.
211217
/// </returns>
212-
let findLastSliceIndex (slice: _ []) (source: _ []) =
213-
raiseIfNull (nameof(slice)) slice
214-
raiseIfNull (nameof(source)) source
218+
let findLastSliceIndex (slice: _ []) (source: _ []) : int =
219+
let slice = nullArgCheck (nameof slice) slice
220+
let source = nullArgCheck (nameof source) source
215221

216222
let index = Internals.FindLastSliceIndex.arrayImpl slice source
217223
if index = -1 then
@@ -226,9 +232,9 @@ module Array =
226232
/// <returns>
227233
/// The index of the slice or <c>None</c>.
228234
/// </returns>
229-
let tryFindLastSliceIndex (slice: _ []) (source: _ []) =
230-
raiseIfNull (nameof(slice)) slice
231-
raiseIfNull (nameof(source)) source
235+
let tryFindLastSliceIndex (slice: 'T []) (source: 'T []) : int option =
236+
let slice = nullArgCheck (nameof slice) slice
237+
let source = nullArgCheck (nameof source) source
232238

233239
let index = Internals.FindLastSliceIndex.arrayImpl slice source
234240
if index = -1 then None else Some index
@@ -241,8 +247,8 @@ module Array =
241247
/// <returns>
242248
/// A tuple with both resulting arrays.
243249
/// </returns>
244-
let partitionMap (mapper: 'T -> Choice<'T1,'T2>) (source: array<'T>) =
245-
raiseIfNull (nameof(source)) source
250+
let partitionMap (mapper: 'T -> Choice<'T1, 'T2>) (source: array<'T>) : array<'T1> * array<'T2> =
251+
let source = nullArgCheck (nameof source) source
246252

247253
let (x, y) = ResizeArray (), ResizeArray ()
248254
Array.iter (mapper >> function Choice1Of2 e -> x.Add e | Choice2Of2 e -> y.Add e) source
@@ -251,19 +257,19 @@ module Array =
251257
/// <summary>Safely build a new array whose elements are the results of applying the given function
252258
/// to each of the elements of the two arrays pairwise.</summary>
253259
/// <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
260+
let map2Shortest (f: 'T1 -> 'T2 -> 'U) (a1: 'T1 []) (a2: 'T2 []) : 'U [] =
261+
let a1 = nullArgCheck (nameof a1) a1
262+
let a2 = nullArgCheck (nameof a2) a2
257263

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

260266
/// <summary>Safely build a new array whose elements are the results of applying the given function
261267
/// to each of the elements of the three arrays pairwise.</summary>
262268
/// <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
269+
let map3Shortest (f: 'T1 -> 'T2 -> 'T3 -> 'U) (a1: 'T1 []) (a2: 'T2 []) (a3: 'T3 []) : 'U [] =
270+
let a1 = nullArgCheck (nameof a1) a1
271+
let a2 = nullArgCheck (nameof a2) a2
272+
let a3 = nullArgCheck (nameof a3) a3
267273
Array.init (min a1.Length a2.Length |> min a3.Length) (fun i -> f a1.[i] a2.[i] a3.[i])
268274

269275
/// <summary>
@@ -272,9 +278,9 @@ module Array =
272278
/// <param name="a1">First input array.</param>
273279
/// <param name="a2">Second input array.</param>
274280
/// <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
281+
let zipShortest (a1: array<'T1>) (a2: array<'T2>) : array<'T1 * 'T2> =
282+
let a1 = nullArgCheck (nameof a1) a1
283+
let a2 = nullArgCheck (nameof a2) a2
278284

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

@@ -285,19 +291,19 @@ module Array =
285291
/// <param name="a2">Second input array.</param>
286292
/// <param name="a3">Third input array.</param>
287293
/// <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
294+
let zip3Shortest (a1: array<'T1>) (a2: array<'T2>) (a3: array<'T3>) : array<'T1 * 'T2 * 'T3> =
295+
let a1 = nullArgCheck (nameof a1) a1
296+
let a2 = nullArgCheck (nameof a2) a2
297+
let a3 = nullArgCheck (nameof a3) a3
292298
Array.init (min a1.Length a2.Length |> min a3.Length) (fun i -> a1.[i], a2.[i], a3.[i])
293299

294300
/// <summary>Same as choose but with access to the index.</summary>
295301
/// <param name="mapping">The mapping function, taking index and element as parameters.</param>
296302
/// <param name="source">The input array.</param>
297303
///
298304
/// <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
305+
let choosei (mapping: int -> 'T -> 'U option) (source: array<'T>) : array<'U> =
306+
let source = nullArgCheck (nameof source) source
301307

302308
let mutable i = ref -1
303309
let fi x =

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 & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@ module Exception =
1111

1212
/// Throws the given exception with its original stacktrace.
1313
let inline rethrow<'T> (exn: exn) =
14-
raiseIfNull (nameof exn) exn
14+
let exn = nullArgCheck (nameof exn) exn
1515
(ExceptionDispatchInfo.Capture exn).Throw ()
1616
Unchecked.defaultof<'T>
1717

1818
/// Combines exceptions from 2 exceptions into a single AggregateException.
1919
/// Exceptions already present in the first argument won't be added.
2020
let add (exn1: exn) (exn2: exn) =
21-
raiseIfNull (nameof exn1) exn1
22-
raiseIfNull (nameof exn2) exn2
21+
let exn1 = nullArgCheck (nameof exn1) exn1
22+
let exn2 = nullArgCheck (nameof exn2) exn2
2323
let f (e: exn) =
2424
match e with
2525
:? AggregateException as a -> a.InnerExceptions :> seq<_>

src/FSharpPlus/Extensions/Extensions.fs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ namespace FSharpPlus
44
module Extensions =
55

66
open System
7+
open FSharpPlus.Internals.Errors
78

89
type Collections.Generic.IEnumerable<'T> with
910
member this.GetSlice = function
@@ -39,7 +40,7 @@ module Extensions =
3940

4041
let private (|Canceled|Faulted|Completed|) (t: Task<'a>) =
4142
if t.IsCanceled then Canceled
42-
else if t.IsFaulted then Faulted t.Exception
43+
else if t.IsFaulted then Faulted (Unchecked.nonNull t.Exception)
4344
else Completed t.Result
4445

4546
type Task<'t> with
@@ -158,7 +159,7 @@ module Extensions =
158159
Async.FromContinuations (fun (sc, ec, cc) ->
159160
task.ContinueWith (fun (task: Task<'T>) ->
160161
if task.IsFaulted then
161-
let e = task.Exception
162+
let e = Unchecked.nonNull task.Exception
162163
if e.InnerExceptions.Count = 1 then ec e.InnerExceptions[0]
163164
else ec e
164165
elif task.IsCanceled then cc (TaskCanceledException ())
@@ -185,7 +186,7 @@ module Extensions =
185186
Async.FromContinuations (fun (sc, ec, cc) ->
186187
task.ContinueWith (fun (task: Task) ->
187188
if task.IsFaulted then
188-
let e = task.Exception
189+
let e = Unchecked.nonNull task.Exception
189190
if e.InnerExceptions.Count = 1 then ec e.InnerExceptions[0]
190191
else ec e
191192
elif task.IsCanceled then cc (TaskCanceledException ())

src/FSharpPlus/Extensions/HashSet.fs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ module HashSet =
3131
/// <returns>The union of <c>set1</c> and <c>set2</c>.</returns>
3232
[<CompiledName("Union")>]
3333
let union (source1: HashSet<'T>) (source2: HashSet<'T>) : HashSet<'T> =
34-
raiseIfNull (nameof source1) source1
35-
raiseIfNull (nameof source2) source2
34+
let source1 = nullArgCheck (nameof source1) source1
35+
let source2 = nullArgCheck (nameof source2) source2
3636
let union =
3737
#if FABLE_COMPILER
3838
HashSet<'T> ()
@@ -50,7 +50,7 @@ module HashSet =
5050
/// <returns>A set containing the transformed elements.</returns>
5151
[<CompiledName("Map")>]
5252
let map (mapping: 'T -> 'U) (source: HashSet<'T>) : HashSet<'U> =
53-
raiseIfNull (nameof source) source
53+
let source = nullArgCheck (nameof source) source
5454
let result = empty<'U>
5555
for item in source do
5656
result.Add (mapping item) |> ignore
@@ -62,7 +62,7 @@ module HashSet =
6262
/// <returns><c>true</c> if the set contains <c>value</c>; otherwise, <c>false</c>.</returns>
6363
[<CompiledName("Contains")>]
6464
let contains (value: 'T) (source: HashSet<'T>) : bool =
65-
raiseIfNull (nameof source) source
65+
let source = nullArgCheck (nameof source) source
6666
source.Contains value
6767

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

src/FSharpPlus/Extensions/List.fs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ module List =
88

99
open System
1010
open FSharp.Core.CompilerServices
11+
open FSharpPlus.Internals.Errors
1112

1213
/// <summary>Returns a list that contains one item only.</summary>
1314
///
@@ -475,7 +476,7 @@ module List =
475476
open System.Reflection
476477

477478
/// Creates an infinite list which cycles the element of the source.
478-
let cycle lst =
479+
let cycle (lst: 'T list) =
479480
let last = ref lst
480481
let rec copy = function
481482
| [] -> failwith "empty list"
@@ -486,7 +487,7 @@ module List =
486487
| x::xs -> x::copy xs
487488
let cycled = copy lst
488489
let strs = last.Value.GetType().GetFields(BindingFlags.NonPublic ||| BindingFlags.Instance) |> Array.map (fun field -> field.Name)
489-
let tailField = last.Value.GetType().GetField(Array.find(fun (s:string) -> s.ToLower().Contains("tail")) strs, BindingFlags.NonPublic ||| BindingFlags.Instance)
490+
let tailField = last.Value.GetType().GetField(Array.find(fun (s:string) -> s.ToLower().Contains("tail")) strs, BindingFlags.NonPublic ||| BindingFlags.Instance) |> Unchecked.nonNull
490491
tailField.SetValue(last.Value, cycled)
491492
cycled
492493
#else

0 commit comments

Comments
 (0)