-
Notifications
You must be signed in to change notification settings - Fork 803
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
32b9db1
commit 400a8fa
Showing
4 changed files
with
525 additions
and
0 deletions.
There are no files selected for viewing
133 changes: 133 additions & 0 deletions
133
...iler.ComponentTests/Conformance/BasicGrammarElements/MethodResolution/MethodResolution.fs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. | ||
|
||
namespace Conformance.BasicGrammarElements | ||
|
||
open FSharp.Test | ||
open FSharp.Test.Compiler | ||
open Xunit | ||
|
||
module MethodResolution = | ||
|
||
[<Fact>] | ||
let ``Method with optional and out parameters resolves correctly (sanity test)`` () = | ||
FSharp """ | ||
open System.Runtime.InteropServices | ||
type Thing = | ||
static member Do(o: outref<int>, [<Optional; DefaultParameterValue(7)>]i: int) = | ||
o <- i | ||
i = 7 | ||
// We expect return value to be false, and out value to be 42 here. | ||
let returnvalue1, value1 = Thing.Do(i = 42) | ||
// Have explicit boolean check for readability here: | ||
if returnvalue1 <> false && value1 <> 42 then | ||
failwith "Mismatch: Return value should be false, and out value should be 42" | ||
// Here, we expect return value to be true, and out value to be 7 | ||
let returnvalue2, value2 = Thing.Do() | ||
// Have explicit boolean check for readability here: | ||
if returnvalue2<> true && value2 <> 7 then | ||
failwith "Mismatch: Return value should be true, and out value should be 7" | ||
""" | ||
|> typecheck | ||
|> shouldSucceed | ||
|> ignore | ||
|
||
[<Theory; FileInlineData("OptionalAndOutParameters.fs", Realsig=BooleanOptions.Both)>] | ||
let ``OptionalAndOutParameters_fs`` compilation = | ||
compilation | ||
|> getCompilation | ||
|> ignoreWarnings | ||
|> verifyILBaseline | ||
|
||
[<Fact>] | ||
let ``Method with optional and out parameters resolves correctly (examples from original issue: https://github.com/dotnet/fsharp/issues/12515)`` () = | ||
Fsx """ | ||
open System.Runtime.InteropServices; | ||
// Define a member with both outref and default parameters. The compiler's implicit outref handling can handle this | ||
// if required and optional parameters are provided, but not if the default parameters are left out | ||
type Thing = | ||
static member Do(x: int, | ||
fast: outref<bool>, | ||
think: outref<float>, | ||
[<Optional; | ||
DefaultParameterValue(System.Threading.CancellationToken())>] | ||
token: System.Threading.CancellationToken | ||
) : bool = | ||
true | ||
static member Also(x: int, | ||
[<Optional; | ||
DefaultParameterValue(System.Threading.CancellationToken())>] | ||
token: System.Threading.CancellationToken, | ||
fast: outref<bool>, | ||
think: outref<float> | ||
) : bool = true | ||
// Works, was error because we can't strip the default `token` parameter for some reason | ||
let ok, fast, think = Thing.Do(1) | ||
// works because the outrefs are detected and provided by the compiler | ||
let ok2, fast2, think2 = Thing.Do(1, token = System.Threading.CancellationToken.None) | ||
// Works, was error because we can't strip the default `token` parameter for some reason | ||
let ok3, fast3, think3 = Thing.Also(1) | ||
// works because the outrefs are detected and provided by the compiler | ||
let ok4, fast4, think4 = Thing.Also(1, token = System.Threading.CancellationToken.None) | ||
// works but requires a lot of work for the user | ||
let mutable fast5 = Unchecked.defaultof<bool> | ||
let mutable think5 = Unchecked.defaultof<float> | ||
let ok5 = Thing.Do(1, &fast5, &think5) | ||
""" | ||
|
||
[<Fact>] | ||
let ``Method with same optional and out parameter does not resolve`` () = | ||
Fsx """ | ||
open System.Runtime.InteropServices | ||
type Thing = | ||
static member Do([<Optional>]i: outref<bool>) = true | ||
let _, _ = Thing.Do() | ||
""" | ||
|> typecheck | ||
|> shouldFail | ||
|> withDiagnostics [ | ||
(Error 501, Line 6, Col 12, Line 6, Col 22, "The member or object constructor 'Do' takes 1 argument(s) but is here given 0. The required signature is 'static member Thing.Do: [<Optional>] i: outref<bool> -> bool'.") | ||
] | ||
|
||
[<Fact>] | ||
let ``optional and ParamArray parameter resolves correctly `` () = | ||
Fsx """ | ||
open System.Runtime.InteropServices | ||
type Thing = | ||
static member Do( | ||
[<Optional; DefaultParameterValue "">] something: string, | ||
[<System.ParamArray>] args: obj[]) = something, args | ||
static member Do2( | ||
[<Optional; DefaultParameterValue "">] something: string, | ||
outvar: outref<int>, | ||
[<System.ParamArray>] args: obj[]) = | ||
outvar <- 1 | ||
something, args | ||
let _, _ = Thing.Do() | ||
let _, _ = Thing.Do("123") | ||
let _, _ = Thing.Do("123", 1, 2, 3, 4) | ||
let _, _ = Thing.Do2() | ||
let _, _ = Thing.Do2("123") | ||
let _ = | ||
let mutable x = 0 | ||
Thing.Do2("123", &x) | ||
let _ = | ||
let mutable x = 0 | ||
Thing.Do2("123", &x, 1, 2, 3, 4) | ||
""" | ||
|> typecheck | ||
|> shouldSucceed |
9 changes: 9 additions & 0 deletions
9
...ponentTests/Conformance/BasicGrammarElements/MethodResolution/OptionalAndOutParameters.fs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
module OutOptionalTests | ||
open System.Runtime.InteropServices | ||
|
||
type Thing = | ||
static member Do(o: outref<int>, [<Optional; DefaultParameterValue(1)>]i: int) = | ||
o <- i | ||
i = 7 | ||
let (_:bool), (_:int) = Thing.Do(i = 42) | ||
let (_:bool), (_:int) = Thing.Do() |
182 changes: 182 additions & 0 deletions
182
...mmarElements/MethodResolution/OptionalAndOutParameters.fs.RealInternalSignatureOff.il.bsl
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,182 @@ | ||
|
||
|
||
|
||
|
||
|
||
.assembly extern runtime { } | ||
.assembly extern FSharp.Core { } | ||
.assembly assembly | ||
{ | ||
.custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, | ||
int32, | ||
int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) | ||
.hash algorithm 0x00008004 | ||
.ver 0:0:0:0 | ||
} | ||
.module assembly.dll | ||
|
||
.imagebase {value} | ||
.file alignment 0x00000200 | ||
.stackreserve 0x00100000 | ||
.subsystem 0x0003 | ||
.corflags 0x00000001 | ||
|
||
|
||
|
||
|
||
|
||
.class public abstract auto ansi sealed OutOptionalTests | ||
extends [runtime]System.Object | ||
{ | ||
.custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) | ||
.class auto ansi serializable nested public Thing | ||
extends [runtime]System.Object | ||
{ | ||
.custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) | ||
.method public static bool Do([out] int32& o, | ||
[opt] int32 i) cil managed | ||
{ | ||
.param [2] = int32(0x00000001) | ||
|
||
.maxstack 8 | ||
IL_0000: ldarg.0 | ||
IL_0001: ldarg.1 | ||
IL_0002: stobj [runtime]System.Int32 | ||
IL_0007: ldarg.1 | ||
IL_0008: ldc.i4.7 | ||
IL_0009: ceq | ||
IL_000b: ret | ||
} | ||
|
||
} | ||
|
||
.method assembly specialname static class [runtime]System.Tuple`2<bool,int32> get_patternInput@8() cil managed | ||
{ | ||
|
||
.maxstack 8 | ||
IL_0000: ldsfld class [runtime]System.Tuple`2<bool,int32> '<StartupCode$assembly>'.$OutOptionalTests::patternInput@8 | ||
IL_0005: ret | ||
} | ||
|
||
.method assembly specialname static int32 get_outArg@8() cil managed | ||
{ | ||
|
||
.maxstack 8 | ||
IL_0000: ldsfld int32 '<StartupCode$assembly>'.$OutOptionalTests::outArg@8 | ||
IL_0005: ret | ||
} | ||
|
||
.method assembly specialname static void set_outArg@8(int32 'value') cil managed | ||
{ | ||
|
||
.maxstack 8 | ||
IL_0000: ldarg.0 | ||
IL_0001: stsfld int32 '<StartupCode$assembly>'.$OutOptionalTests::outArg@8 | ||
IL_0006: ret | ||
} | ||
|
||
.method assembly specialname static class [runtime]System.Tuple`2<bool,int32> 'get_patternInput@9-1'() cil managed | ||
{ | ||
|
||
.maxstack 8 | ||
IL_0000: ldsfld class [runtime]System.Tuple`2<bool,int32> '<StartupCode$assembly>'.$OutOptionalTests::'patternInput@9-1' | ||
IL_0005: ret | ||
} | ||
|
||
.method assembly specialname static int32 'get_outArg@9-1'() cil managed | ||
{ | ||
|
||
.maxstack 8 | ||
IL_0000: ldsfld int32 '<StartupCode$assembly>'.$OutOptionalTests::'outArg@9-1' | ||
IL_0005: ret | ||
} | ||
|
||
.method assembly specialname static void 'set_outArg@9-1'(int32 'value') cil managed | ||
{ | ||
|
||
.maxstack 8 | ||
IL_0000: ldarg.0 | ||
IL_0001: stsfld int32 '<StartupCode$assembly>'.$OutOptionalTests::'outArg@9-1' | ||
IL_0006: ret | ||
} | ||
|
||
.property class [runtime]System.Tuple`2<bool,int32> | ||
patternInput@8() | ||
{ | ||
.custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 09 00 00 00 00 00 ) | ||
.get class [runtime]System.Tuple`2<bool,int32> OutOptionalTests::get_patternInput@8() | ||
} | ||
.property int32 outArg@8() | ||
{ | ||
.custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 09 00 00 00 00 00 ) | ||
.set void OutOptionalTests::set_outArg@8(int32) | ||
.get int32 OutOptionalTests::get_outArg@8() | ||
} | ||
.property class [runtime]System.Tuple`2<bool,int32> | ||
'patternInput@9-1'() | ||
{ | ||
.custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 09 00 00 00 00 00 ) | ||
.get class [runtime]System.Tuple`2<bool,int32> OutOptionalTests::'get_patternInput@9-1'() | ||
} | ||
.property int32 'outArg@9-1'() | ||
{ | ||
.custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 09 00 00 00 00 00 ) | ||
.set void OutOptionalTests::'set_outArg@9-1'(int32) | ||
.get int32 OutOptionalTests::'get_outArg@9-1'() | ||
} | ||
} | ||
|
||
.class private abstract auto ansi sealed '<StartupCode$assembly>'.$OutOptionalTests | ||
extends [runtime]System.Object | ||
{ | ||
.field static assembly initonly class [runtime]System.Tuple`2<bool,int32> patternInput@8 | ||
.custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) | ||
.field static assembly int32 outArg@8 | ||
.custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) | ||
.field static assembly initonly class [runtime]System.Tuple`2<bool,int32> 'patternInput@9-1' | ||
.custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) | ||
.field static assembly int32 'outArg@9-1' | ||
.custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) | ||
.field static assembly int32 init@ | ||
.custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) | ||
.custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) | ||
.custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) | ||
.method private specialname rtspecialname static void .cctor() cil managed | ||
{ | ||
|
||
.maxstack 4 | ||
.locals init (int32& V_0) | ||
IL_0000: ldc.i4.0 | ||
IL_0001: stsfld int32 '<StartupCode$assembly>'.$OutOptionalTests::outArg@8 | ||
IL_0006: ldsflda int32 '<StartupCode$assembly>'.$OutOptionalTests::outArg@8 | ||
IL_000b: stloc.0 | ||
IL_000c: ldloc.0 | ||
IL_000d: ldc.i4.s 42 | ||
IL_000f: stobj [runtime]System.Int32 | ||
IL_0014: ldc.i4.0 | ||
IL_0015: call int32 OutOptionalTests::get_outArg@8() | ||
IL_001a: newobj instance void class [runtime]System.Tuple`2<bool,int32>::.ctor(!0, | ||
!1) | ||
IL_001f: stsfld class [runtime]System.Tuple`2<bool,int32> '<StartupCode$assembly>'.$OutOptionalTests::patternInput@8 | ||
IL_0024: ldc.i4.0 | ||
IL_0025: stsfld int32 '<StartupCode$assembly>'.$OutOptionalTests::'outArg@9-1' | ||
IL_002a: ldsflda int32 '<StartupCode$assembly>'.$OutOptionalTests::'outArg@9-1' | ||
IL_002f: stloc.0 | ||
IL_0030: ldloc.0 | ||
IL_0031: ldc.i4.1 | ||
IL_0032: stobj [runtime]System.Int32 | ||
IL_0037: ldc.i4.0 | ||
IL_0038: call int32 OutOptionalTests::'get_outArg@9-1'() | ||
IL_003d: newobj instance void class [runtime]System.Tuple`2<bool,int32>::.ctor(!0, | ||
!1) | ||
IL_0042: stsfld class [runtime]System.Tuple`2<bool,int32> '<StartupCode$assembly>'.$OutOptionalTests::'patternInput@9-1' | ||
IL_0047: ret | ||
} | ||
|
||
} | ||
|
||
|
||
|
||
|
||
|
||
|
Oops, something went wrong.