From 41cd736130f83ed9c11c6d2669ea5b199b8c6e3d Mon Sep 17 00:00:00 2001 From: Petr Date: Tue, 25 Jun 2024 16:24:44 +0200 Subject: [PATCH 1/3] Fix an exception check in the tests (#17326) * Fix an exception check in the tests * Fix tests --------- Co-authored-by: Kevin Ransom (msft) --- .../ArrayModule.fs | 6 +- .../Microsoft.FSharp.Collections/SeqModule.fs | 2 +- .../FSharpReflection.fs | 56 +++++++++---------- 3 files changed, 32 insertions(+), 32 deletions(-) diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/ArrayModule.fs b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/ArrayModule.fs index 0f9931e0e6a..aa112e0b98b 100644 --- a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/ArrayModule.fs +++ b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/ArrayModule.fs @@ -372,9 +372,9 @@ type ArrayModule() = CheckThrowsArgumentNullException (fun () -> Array.blit nullArr 1 strDes 2 3 |> ignore) // bounds check - CheckThrowsArgumentException (fun () -> Array.blit intSrc -1 intDes 1 3 |> ignore) - CheckThrowsArgumentException (fun () -> Array.blit intSrc 1 intDes -1 3 |> ignore) - CheckThrowsArgumentException (fun () -> Array.blit intSrc 1 intDes 1 -3 |> ignore) + CheckThrowsArgumentOutOfRangeException (fun () -> Array.blit intSrc -1 intDes 1 3 |> ignore) + CheckThrowsArgumentOutOfRangeException (fun () -> Array.blit intSrc 1 intDes -1 3 |> ignore) + CheckThrowsArgumentOutOfRangeException (fun () -> Array.blit intSrc 1 intDes 1 -3 |> ignore) CheckThrowsArgumentException (fun () -> Array.blit intSrc 1 intDes 1 300 |> ignore) CheckThrowsArgumentException (fun () -> Array.blit intSrc 1 intDes 5 8 |> ignore) diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/SeqModule.fs b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/SeqModule.fs index 749203601fe..d80f5404a53 100644 --- a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/SeqModule.fs +++ b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Collections/SeqModule.fs @@ -141,7 +141,7 @@ type SeqModule() = Assert.AreEqual(null, Seq.head <| Seq.replicate 1 null) Assert.AreEqual(["1";"1"],Seq.replicate 2 "1" |> Seq.toList) - CheckThrowsArgumentException (fun () -> Seq.replicate -1 null |> ignore) + CheckThrowsArgumentOutOfRangeException (fun () -> Seq.replicate -1 null |> ignore) [] diff --git a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Reflection/FSharpReflection.fs b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Reflection/FSharpReflection.fs index 987b779df17..be9894bc22e 100644 --- a/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Reflection/FSharpReflection.fs +++ b/tests/FSharp.Core.UnitTests/FSharp.Core/Microsoft.FSharp.Reflection/FSharpReflection.fs @@ -221,13 +221,13 @@ type FSharpValueTests() = // invalid type CheckThrowsArgumentException(fun () -> FSharpValue.GetExceptionFields(1) |> ignore) - CheckThrowsArgumentException(fun () -> FSharpValue.GetExceptionFields( () ) |> ignore) + CheckThrowsArgumentNullException(fun () -> FSharpValue.GetExceptionFields( () ) |> ignore) // System Exception CheckThrowsArgumentException(fun () -> FSharpValue.GetExceptionFields(new System.Exception("ex message")) |> ignore) // null - CheckThrowsArgumentException(fun () -> FSharpValue.GetExceptionFields(null) |> ignore) + CheckThrowsArgumentNullException(fun () -> FSharpValue.GetExceptionFields(null) |> ignore) [] member _.GetRecordField() = @@ -241,15 +241,15 @@ type FSharpValueTests() = Assert.AreEqual((FSharpValue.GetRecordField(genericRecordType1, propertyinfo2)), 1) // null value - CheckThrowsArgumentException(fun () ->FSharpValue.GetRecordField(null, propertyinfo1)|> ignore) - CheckThrowsArgumentException(fun () ->FSharpValue.GetRecordField( () , propertyinfo1)|> ignore) + CheckThrowsArgumentNullException(fun () ->FSharpValue.GetRecordField(null, propertyinfo1)|> ignore) + CheckThrowsArgumentNullException(fun () ->FSharpValue.GetRecordField( () , propertyinfo1)|> ignore) // invalid value CheckThrowsArgumentException(fun () -> FSharpValue.GetRecordField("invalid", propertyinfo1) |> ignore) // invalid property info - let propertyinfoint = (typeof).GetProperty("fieldstring") - CheckThrowsArgumentException(fun () -> FSharpValue.GetRecordField("invalid", propertyinfoint) |> ignore) + let propertyinfoint = (typeof).GetProperty("fieldstring") // null + CheckThrowsArgumentNullException(fun () -> FSharpValue.GetRecordField("invalid", propertyinfoint) |> ignore) [] member _.GetStructRecordField() = @@ -259,15 +259,15 @@ type FSharpValueTests() = Assert.AreEqual((FSharpValue.GetRecordField(structRecord1, propertyinfo1)), "field1") // null value - CheckThrowsArgumentException(fun () ->FSharpValue.GetRecordField(null, propertyinfo1)|> ignore) - CheckThrowsArgumentException(fun () ->FSharpValue.GetRecordField( () , propertyinfo1)|> ignore) + CheckThrowsArgumentNullException(fun () ->FSharpValue.GetRecordField(null, propertyinfo1)|> ignore) + CheckThrowsArgumentNullException(fun () ->FSharpValue.GetRecordField( () , propertyinfo1)|> ignore) // invalid value CheckThrowsArgumentException(fun () -> FSharpValue.GetRecordField("invalid", propertyinfo1) |> ignore) // invalid property info - let propertyinfoint = (typeof).GetProperty("fieldstring") - CheckThrowsArgumentException(fun () -> FSharpValue.GetRecordField("invalid", propertyinfoint) |> ignore) + let propertyinfoint = (typeof).GetProperty("fieldstring") // null + CheckThrowsArgumentNullException(fun () -> FSharpValue.GetRecordField("invalid", propertyinfoint) |> ignore) [] member _.GetRecordFields() = @@ -280,8 +280,8 @@ type FSharpValueTests() = Assert.AreEqual((FSharpValue.GetRecordFields(genericRecordType1)).[0], "field1") // null value - CheckThrowsArgumentException(fun () -> FSharpValue.GetRecordFields(null)|> ignore) - CheckThrowsArgumentException(fun () -> FSharpValue.GetRecordFields( () )|> ignore) + CheckThrowsArgumentNullException(fun () -> FSharpValue.GetRecordFields(null)|> ignore) + CheckThrowsArgumentNullException(fun () -> FSharpValue.GetRecordFields( () )|> ignore) // invalid value CheckThrowsArgumentException(fun () -> FSharpValue.GetRecordFields("invalid") |> ignore) @@ -300,8 +300,8 @@ type FSharpValueTests() = Assert.AreEqual( FSharpValue.GetTupleField(tuple2, 1), "tuple2") // null value - CheckThrowsArgumentException(fun () -> FSharpValue.GetTupleField(null, 3)|> ignore) - CheckThrowsArgumentException(fun () -> FSharpValue.GetTupleField( () , 3)|> ignore) + CheckThrowsArgumentNullException(fun () -> FSharpValue.GetTupleField(null, 3)|> ignore) + CheckThrowsArgumentNullException(fun () -> FSharpValue.GetTupleField( () , 3)|> ignore) // invalid value CheckThrowsArgumentException(fun () -> FSharpValue.GetTupleField("Invalid", 3)|> ignore) @@ -329,8 +329,8 @@ type FSharpValueTests() = Assert.AreEqual( (FSharpValue.GetTupleFields(tuple2)).[1], "tuple2") // null value - CheckThrowsArgumentException(fun () -> FSharpValue.GetTupleFields(null)|> ignore) - CheckThrowsArgumentException(fun () -> FSharpValue.GetTupleFields( () )|> ignore) + CheckThrowsArgumentNullException(fun () -> FSharpValue.GetTupleFields(null)|> ignore) + CheckThrowsArgumentNullException(fun () -> FSharpValue.GetTupleFields( () )|> ignore) // invalid value CheckThrowsArgumentException(fun () -> FSharpValue.GetTupleFields("Invalid")|> ignore) @@ -393,7 +393,7 @@ type FSharpValueTests() = Assert.AreEqual(FSharpValue.GetRecordFields(makeRecordGeneric).[0], "field1") // null value - CheckThrowsArgumentException(fun () ->FSharpValue.MakeRecord(null, null)|> ignore) + CheckThrowsArgumentNullException(fun () ->FSharpValue.MakeRecord(null, null)|> ignore) // invalid value CheckThrowsArgumentException(fun () -> FSharpValue.MakeRecord(typeof>, [| box 1; box("invalid param"); box("invalid param") |])|> ignore) @@ -471,7 +471,7 @@ type FSharpValueTests() = Assert.AreEqual( (unbox>(resultGenericRecordType)).field1, genericRecordType1.field1) // null value - CheckThrowsArgumentException(fun () ->FSharpValue.PreComputeRecordConstructor(null)|> ignore) + CheckThrowsArgumentNullException(fun () ->FSharpValue.PreComputeRecordConstructor(null)|> ignore) // invalid value CheckThrowsArgumentException(fun () -> FSharpValue.PreComputeRecordConstructor(typeof>) |> ignore) @@ -495,7 +495,7 @@ type FSharpValueTests() = Assert.AreEqual(genericrecordCtorInfo.ReflectedType, typeof>) // null value - CheckThrowsArgumentException(fun () ->FSharpValue.PreComputeRecordConstructorInfo(null)|> ignore) + CheckThrowsArgumentNullException(fun () ->FSharpValue.PreComputeRecordConstructorInfo(null)|> ignore) // invalid value CheckThrowsArgumentException(fun () -> FSharpValue.PreComputeRecordConstructorInfo(typeof>) |> ignore) @@ -517,7 +517,7 @@ type FSharpValueTests() = Assert.AreEqual(recordFieldReader(genericRecordType1), box("field1")) // null value - CheckThrowsArgumentException(fun () -> FSharpValue.PreComputeRecordFieldReader(null)|> ignore) + CheckThrowsArgumentNullException(fun () -> FSharpValue.PreComputeRecordFieldReader(null)|> ignore) [] member _.PreComputeStructRecordFieldReader() = @@ -536,7 +536,7 @@ type FSharpValueTests() = Assert.AreEqual( (genericrecordReader(genericRecordType1)).[0], "field1") // null value - CheckThrowsArgumentException(fun () ->FSharpValue.PreComputeRecordReader(null)|> ignore) + CheckThrowsArgumentNullException(fun () ->FSharpValue.PreComputeRecordReader(null)|> ignore) // invalid value CheckThrowsArgumentException(fun () -> FSharpValue.PreComputeRecordReader(typeof>) |> ignore) @@ -566,7 +566,7 @@ type FSharpValueTests() = Assert.AreEqual( tupleNestedCtor([| box 1; box(2, "tuple") |] ), box(tuple3)) // null value - CheckThrowsArgumentException(fun () -> FSharpValue.PreComputeTupleConstructor(null)|> ignore) + CheckThrowsArgumentNullException(fun () -> FSharpValue.PreComputeTupleConstructor(null)|> ignore) // invalid value CheckThrowsArgumentException(fun () -> FSharpValue.PreComputeTupleConstructor(typeof>) |> ignore) @@ -604,7 +604,7 @@ type FSharpValueTests() = Assert.AreEqual(nestedTupleCtorInfo.ReflectedType, typeof>>) // null value - CheckThrowsArgumentException(fun () ->FSharpValue.PreComputeTupleConstructorInfo(null)|> ignore) + CheckThrowsArgumentNullException(fun () ->FSharpValue.PreComputeTupleConstructorInfo(null)|> ignore) // invalid value CheckThrowsArgumentException(fun () -> FSharpValue.PreComputeTupleConstructorInfo(typeof) |> ignore) @@ -634,7 +634,7 @@ type FSharpValueTests() = Assert.AreEqual(tupleNestedPropInfo.PropertyType, typeof>) // null value - CheckThrowsArgumentException(fun () ->FSharpValue.PreComputeTuplePropertyInfo(null, 0)|> ignore) + CheckThrowsArgumentNullException(fun () ->FSharpValue.PreComputeTuplePropertyInfo(null, 0)|> ignore) // invalid value CheckThrowsArgumentException(fun () -> FSharpValue.PreComputeTuplePropertyInfo(typeof, 0) |> ignore) @@ -670,7 +670,7 @@ type FSharpValueTests() = Assert.AreEqual (longTupleReader longTuple, [| box ("yup", 1s); box 2; box 3; box 4; box 5; box 6; box 7; box 8; box 9; box 10; box 11; box (Some 12); box 13; box "nope"; box (struct (15, 16)); box 17; box 18; box (ValueSome 19) |]) // null value - CheckThrowsArgumentException(fun () ->FSharpValue.PreComputeTupleReader(null)|> ignore) + CheckThrowsArgumentNullException(fun () ->FSharpValue.PreComputeTupleReader(null)|> ignore) // invalid value CheckThrowsArgumentException(fun () -> FSharpValue.PreComputeTupleReader(typeof) |> ignore) @@ -813,7 +813,7 @@ type FSharpValueTests() = Assert.AreEqual(discUnionMemberInfo.ReflectedType, typeof>) // null value - CheckThrowsArgumentException(fun () ->FSharpValue.PreComputeUnionTagMemberInfo(null)|> ignore) + CheckThrowsArgumentNullException(fun () ->FSharpValue.PreComputeUnionTagMemberInfo(null)|> ignore) // invalid value CheckThrowsArgumentException(fun () -> FSharpValue.PreComputeUnionTagMemberInfo(typeof) |> ignore) @@ -851,7 +851,7 @@ type FSharpValueTests() = Assert.AreEqual(voptionTagReader(box(voptionNone)), 0) // null value - CheckThrowsArgumentException(fun () ->FSharpValue.PreComputeUnionTagReader(null)|> ignore) + CheckThrowsArgumentNullException(fun () ->FSharpValue.PreComputeUnionTagReader(null)|> ignore) // invalid value CheckThrowsArgumentException(fun () -> FSharpValue.PreComputeUnionTagReader(typeof) |> ignore) @@ -1179,7 +1179,7 @@ type FSharpTypeTests() = // invalid cases CheckThrowsArgumentException(fun () ->FSharpType.MakeStructTupleType( [|null;null|]) |> ignore ) - CheckThrowsArgumentException(fun () ->FSharpType.MakeStructTupleType( null) |> ignore ) + CheckThrowsArgumentNullException(fun () ->FSharpType.MakeStructTupleType( null) |> ignore ) CheckThrowsArgumentException(fun () ->FSharpType.MakeStructTupleType( [| |]) |> ignore ) type UnionCaseInfoTests() = From b25b4263edc9e848dd69440643777b2027c68474 Mon Sep 17 00:00:00 2001 From: Petr Date: Tue, 25 Jun 2024 17:08:57 +0200 Subject: [PATCH 2/3] Fix exception throwing inconsistency (#17328) * Fix exception throwing inconsitency * release notes * Update 8.0.400.md --- docs/release-notes/.FSharp.Core/8.0.400.md | 4 ++++ src/FSharp.Core/local.fs | 10 +++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/docs/release-notes/.FSharp.Core/8.0.400.md b/docs/release-notes/.FSharp.Core/8.0.400.md index ee24d8d0a53..9c01378c5ef 100644 --- a/docs/release-notes/.FSharp.Core/8.0.400.md +++ b/docs/release-notes/.FSharp.Core/8.0.400.md @@ -6,3 +6,7 @@ * Cache delegate in query extensions. ([PR #17130](https://github.com/dotnet/fsharp/pull/17130)) * Update `AllowNullLiteralAttribute` to also use `AttributeTargets.Interface` ([PR #17173](https://github.com/dotnet/fsharp/pull/17173)) + +### Breaking Changes + +* Fixed argument exception throwing inconsistency - accessing an out-of-bounds collection index will now throw `ArgumentOutOfRangeException` instead of `ArgumentException` ([#17328](https://github.com/dotnet/fsharp/pull/17328)) diff --git a/src/FSharp.Core/local.fs b/src/FSharp.Core/local.fs index a57621c651f..063feb4b243 100644 --- a/src/FSharp.Core/local.fs +++ b/src/FSharp.Core/local.fs @@ -14,6 +14,11 @@ module internal DetailedExceptions = let msg = String.Format (format, paramArray) raise (new ArgumentException (msg, arg)) + /// takes an argument, a formatting string, a param array to splice into the formatting string + let inline invalidArgOutOfRangeFmt (arg:string) (format:string) paramArray = + let msg = String.Format (format, paramArray) + raise (new ArgumentOutOfRangeException (arg, msg)) + /// takes a formatting string and a param array to splice into the formatting string let inline invalidOpFmt (format:string) paramArray = let msg = String.Format (format, paramArray) @@ -38,7 +43,6 @@ module internal DetailedExceptions = "{0}\nThe list was {1} {2} shorter than the index" [|SR.GetString SR.notEnoughElements; index; (if index=1 then "element" else "elements")|] - /// eg. tried to {skip} {2} {elements} past the end of the seq. Seq.Length = {10} let invalidOpExceededSeqLength (fnName:string) (diff:int) (len:int) = invalidOpFmt "{0}\ntried to {1} {2} {3} past the end of the seq\nSeq.Length = {4}" @@ -52,11 +56,11 @@ module internal DetailedExceptions = let inline invalidArgInputMustBePositive (arg:string) (count:int) = invalidArgFmt arg "{0}\n{1} = {2}" [|SR.GetString SR.inputMustBePositive; arg; count|] - /// throws an invalid argument exception and returns the out of range index, + /// throws an invalid argument out of range exception and returns the out of range index, /// a text description of the range, and the bound of the range /// e.g. sourceIndex = -4, source axis-0 lower bound = 0" let invalidArgOutOfRange (arg:string) (index:int) (text:string) (bound:int) = - invalidArgFmt arg + invalidArgOutOfRangeFmt arg "{0}\n{1} = {2}, {3} = {4}" [|SR.GetString SR.outOfRange; arg; index; text; bound|] From e94b941853db8b2995df34d1912c821943bcda4e Mon Sep 17 00:00:00 2001 From: Petr Date: Tue, 25 Jun 2024 17:15:05 +0200 Subject: [PATCH 3/3] Skip another flaky transparent compiler test (#17347) --- .../FSharpChecker/TransparentCompiler.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs index cbc0c8a34e8..cb3f9cece44 100644 --- a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs +++ b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs @@ -1013,7 +1013,7 @@ printfn "Hello from F#" checkFile "As 01" expectTwoWarnings } -[] +[] let ``Transparent Compiler ScriptClosure cache is populated after GetProjectOptionsFromScript`` () = async { let transparentChecker = FSharpChecker.Create(useTransparentCompiler = true)