diff --git a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj index 3cbbe3ef3c5..0509d424f8b 100644 --- a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj +++ b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj @@ -250,6 +250,8 @@ + + diff --git a/tests/FSharp.Compiler.ComponentTests/Interop/ParamArray.fs b/tests/FSharp.Compiler.ComponentTests/Interop/ParamArray.fs new file mode 100644 index 00000000000..3864857d969 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Interop/ParamArray.fs @@ -0,0 +1,107 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace Interop + +open Xunit +open FSharp.Test +open FSharp.Test.Compiler + +module ParamArray = + + [] + let ``C# 13 params enhancements`` () = + let csharp = + CSharp """ +using System; +using System.Collections.Generic; + +namespace CSharpAssembly; + +public class CS13ParamArray +{ + public static void WriteNames(params string[] names) + => Console.WriteLine("First: " + string.Join(" + ", names)); + + public static void WriteNames(params List names) + => Console.WriteLine("Second: " + string.Join(" + ", names)); + + public static void WriteNames(params IEnumerable names) + => Console.WriteLine("Third: " + string.Join(" + ", names)); +}""" + |> withCSharpLanguageVersionPreview + + FSharp """ +open System.Collections.Generic; +open CSharpAssembly + +CS13ParamArray.WriteNames("Petr", "Jana") +CS13ParamArray.WriteNames(List["Petr"; "Jana"]) +CS13ParamArray.WriteNames(["Petr"; "Jana"]) +""" + |> withReferences [csharp] + |> compileExeAndRun + |> shouldSucceed + |> withStdOutContainsAllInOrder [ + "First: Petr + Jana" + "Second: Petr + Jana" + "Third: Petr + Jana" + ] + + [] + let ``C# 13 params enhancements - ReadOnlySpan`` () = + let csharp = + CSharp """ +using System; + +namespace CSharpAssembly; + +public class CS13ParamArray +{ + public static void WriteNames(params ReadOnlySpan names) + => Console.WriteLine(string.Join(" + ", names)); +}""" + |> withCSharpLanguageVersionPreview + + FSharp """ +open System +open CSharpAssembly + +CS13ParamArray.WriteNames(ReadOnlySpan([|"Petr"; "Jana"|])) +""" + |> withReferences [csharp] + |> compileExeAndRun + |> shouldSucceed + |> withStdOutContainsAllInOrder [ "Petr + Jana" ] + + [] + let ``C# 13 params enhancements - error when no matching overload is available`` () = + let csharp = + CSharp """ +using System; +using System.Collections.Generic; + +namespace CSharpAssembly; + +public class CS13ParamArray +{ + public static void WriteNames(params List names) + => Console.WriteLine("Second: " + string.Join(" + ", names)); + + public static void WriteNames(params IEnumerable names) + => Console.WriteLine("Third: " + string.Join(" + ", names)); +}""" + |> withCSharpLanguageVersionPreview + + FSharp """ +open CSharpAssembly + +CS13ParamArray.WriteNames("Petr", "Jana") +""" + |> withReferences [csharp] + |> asExe + |> compile + |> shouldFail + |> withDiagnostics [ + (Error 503, Line 4, Col 1, Line 4, Col 42, + "A member or object constructor 'WriteNames' taking 2 arguments is not accessible from this code location. All accessible versions of method 'WriteNames' take 1 arguments.") + ] \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/Interop/ParamArrayMigrated.fs b/tests/FSharp.Compiler.ComponentTests/Interop/ParamArrayMigrated.fs new file mode 100644 index 00000000000..0906682d6d6 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/Interop/ParamArrayMigrated.fs @@ -0,0 +1,110 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace Interop + +open Xunit +open FSharp.Test.Compiler + +module ParamArrayMigrated = + + let csharp = + CSharp """ +using System; + +namespace CSharpAssembly +{ + [AttributeUsage(AttributeTargets.All)] + public class AttributeWithParamArray : Attribute + { + public object[] Parameters; + + public AttributeWithParamArray(params object[] x) + { + + Parameters = x; + } + } + + public class CSParamArray + { + public static int Method(params int[] allArgs) + { + int total = 0; + foreach (int i in allArgs) + total += i; + + return total; + } + + public static int Method(params T[] args) + { + return args.Length; + } + } +}""" + + [] + let ``Valid params call`` () = + FSharp """ +open System +open CSharpAssembly + +// Apply the attribute +[ obj) |])>] +type Foo() = + [ obj); ("bar" :> obj) |])>] + override this.ToString() = "Stuff" + +let callCSGenericMethod (a: 't[]) = CSParamArray.Method(a) + +[] +do + let getTestAttribute (t : Type) = + let tyAttributes = t.GetCustomAttributes(false) + let attrib = tyAttributes |> Array.find (fun attrib -> match attrib with :? AttributeWithParamArray -> true | _ -> false) + (attrib :?> AttributeWithParamArray) + + let tyFoo = typeof + let testAtt = getTestAttribute tyFoo + if testAtt.Parameters <> [| (0 :> obj) |] then + failwith "Attribute parameters not as expected" + + let directCallWorks = + CSParamArray.Method(9, 8, 7) + CSParamArray.Method(1, 2) + CSParamArray.Method() = (9 + 8 + 7) + (1 + 2) + if not directCallWorks then + failwith "Calling C# param array method gave unexpected result" + + let callParamArray (x : int array) = CSParamArray.Method(x) + let asArrayCallWorks = (callParamArray [| 9; 8; 7 |]) = (9 + 8 + 7) + if not asArrayCallWorks then + failwith "Calling C# param array method, passing args as an array, gave unexpected result" + + if callCSGenericMethod [|"1";"2";"3"|] <> 3 then + failwith "Calling C# generic param array method gave unexpected result" + + if CSParamArray.Method("1", "2", "3") <> CSParamArray.Method([|"1"; "2"; "3"|]) then + failwith "Calling C# generic param array in normal and expanded method gave unexpected result" +""" + |> withReferences [csharp] + |> compileExeAndRun + |> shouldSucceed + + [] + let ``Invalid params call`` () = + FSharp """ +open CSharpAssembly + +[] +type Foo() = + override this.ToString() = "Stuff" +""" + |> withReferences [csharp] + |> asExe + |> compile + |> shouldFail + |> withDiagnostics [ + (Error 13, Line 4, Col 29, Line 4, Col 37, + "The static coercion from type\n int \nto \n 'a \n involves an indeterminate type based on information prior to this program point. Static coercions are not allowed on some types. Further type annotations are needed.") + (Error 267, Line 4, Col 29, Line 4, Col 37, + "This is not a valid constant expression or custom attribute value") + ] diff --git a/tests/FSharp.Test.Utilities/Compiler.fs b/tests/FSharp.Test.Utilities/Compiler.fs index 9fb050b09df..1edd5ef5488 100644 --- a/tests/FSharp.Test.Utilities/Compiler.fs +++ b/tests/FSharp.Test.Utilities/Compiler.fs @@ -585,6 +585,9 @@ module rec Compiler = | CS cs -> CS { cs with LangVersion = ver } | _ -> failwith "Only supported in C#" + let withCSharpLanguageVersionPreview = + withCSharpLanguageVersion CSharpLanguageVersion.Preview + let withOutputType (outputType : CompileOutput) (cUnit: CompilationUnit) : CompilationUnit = match cUnit with | FS x -> FS { x with OutputType = outputType } diff --git a/tests/fsharpqa/Source/Misc/ConsumeParamArray.fsscript b/tests/fsharpqa/Source/Misc/ConsumeParamArray.fsscript deleted file mode 100644 index 188c6459f38..00000000000 --- a/tests/fsharpqa/Source/Misc/ConsumeParamArray.fsscript +++ /dev/null @@ -1,56 +0,0 @@ -// #Regression #Misc -#light - -// Test that F# can consume C# param arrays. (Can't use variable number of arguments, rather -// arguments will just be exposed as taking an array.) -// FSB 1105, params attributes not supported -// This is also regression test for FSHARP1.0:3817 -open System - -#r "ParamArray.dll" -open CSharpAssembly - -// Apply the attribute -[ obj) |])>] -type Foo() = - [ obj); ("bar" :> obj) |])>] - override this.ToString() = "Stuff" - -let callCSGenericMethod (a: 't[]) = CSParamArray.Method(a) - -[] -do - let getTestAttribute (t : Type) = - let tyAttributes = t.GetCustomAttributes(false) - let attrib = tyAttributes |> Array.find (fun attrib -> match attrib with :? AttributeWithParamArray -> true | _ -> false) - (attrib :?> AttributeWithParamArray) - - let tyFoo = typeof - let testAtt = getTestAttribute tyFoo - if testAtt.Parameters <> [| (0 :> obj) |] then - printfn "Attribute parameters not as expected" - exit 1 - - let directCallWorks = - CSParamArray.Method(9, 8, 7) + CSParamArray.Method(1, 2) + CSParamArray.Method() = (9 + 8 + 7) + (1 + 2) - if not directCallWorks then - printfn "Calling C# param array method gave unexpected result" - exit 1 - - let callParamArray (x : int array) = CSParamArray.Method(x) - let asArrayCallWorks = (callParamArray [| 9; 8; 7 |]) = (9 + 8 + 7) - if not asArrayCallWorks then - printfn "Calling C# param array method, passing args as an array, gave unexpected result" - exit 1 - - if callCSGenericMethod [|"1";"2";"3"|] <> 3 then - printfn "Calling C# generic param array method gave unexpected result" - exit 1 - - if CSParamArray.Method("1", "2", "3") <> CSParamArray.Method([|"1"; "2"; "3"|]) then - printfn "Calling C# generic param array in normal and expanded method gave unexpected result" - exit 1 - - exit 0 - - \ No newline at end of file diff --git a/tests/fsharpqa/Source/Misc/E_ConsumeParamArray.fsscript b/tests/fsharpqa/Source/Misc/E_ConsumeParamArray.fsscript deleted file mode 100644 index 8e6a7a1473d..00000000000 --- a/tests/fsharpqa/Source/Misc/E_ConsumeParamArray.fsscript +++ /dev/null @@ -1,35 +0,0 @@ -// #Regression #Misc -#light - -// This test used to be the regression test for FSHARP1.0:1105. -// This code is expected to fail compilation, yet it was able to detect FSHARP1.0:3817 -// so I am promoting it to negative testcases. -//The static coercion from type -open System - -#r "ParamArray.dll" -open CSharpAssembly - -// Apply the attribute -[] -type Foo() = - [] - override this.ToString() = "Stuff" - -[] -do - let testPassed = - let getTestAttribute (t : Type) = - let tyAttributes = t.GetCustomAttributes(false) - let attrib = tyAttributes |> Array.find (fun attrib -> match attrib with :? AttributeWithParamArray -> true | _ -> false) - (attrib :?> AttributeWithParamArray) - - let tyFoo = typeof - let testAtt = getTestAttribute tyFoo - if testAtt.Parameters <> [|upcast 0|] then - false - else - true - - if not testPassed then exit 1 - exit 0 diff --git a/tests/fsharpqa/Source/Misc/ParamArray.cs b/tests/fsharpqa/Source/Misc/ParamArray.cs deleted file mode 100644 index 6c7ae6108d7..00000000000 --- a/tests/fsharpqa/Source/Misc/ParamArray.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; - -namespace CSharpAssembly -{ - [AttributeUsage(AttributeTargets.All)] - public class AttributeWithParamArray : Attribute - { - public object[] Parameters; - - public AttributeWithParamArray(params object[] x) - { - - Parameters = x; - } - } - - public class CSParamArray - { - public static int Method(params int[] allArgs) - { - int total = 0; - foreach (int i in allArgs) - total += i; - - return total; - } - - public static int Method(params T[] args) - { - return args.Length; - } - } -} \ No newline at end of file diff --git a/tests/fsharpqa/Source/Misc/env.lst b/tests/fsharpqa/Source/Misc/env.lst index b2b236cb7f5..ada01d097f1 100644 --- a/tests/fsharpqa/Source/Misc/env.lst +++ b/tests/fsharpqa/Source/Misc/env.lst @@ -1,6 +1,3 @@ - PRECMD="\$CSC_PIPE /target:library ParamArray.cs" SOURCE=ConsumeParamArray.fsscript # ConsumeParamArray.fsscript - PRECMD="\$CSC_PIPE /target:library ParamArray.cs" SOURCE=E_ConsumeParamArray.fsscript # E_ConsumeParamArray.fsscript - SOURCE=E_productioncoverage01.fs # E_productioncoverage01.fs SOURCE=E_productioncoverage02.fs # E_productioncoverage02.fs SOURCE=E_productioncoverage03.fs SCFLAGS="--test:ErrorRanges" # E_productioncoverage03.fs