diff --git a/.gitignore b/.gitignore index f0dbae4d2f3..33c9666c14b 100644 --- a/.gitignore +++ b/.gitignore @@ -129,4 +129,9 @@ tests/FSharp.Compiler.Service.Tests/FSharp.CompilerService.SurfaceArea.netstanda /tests/AheadOfTime/Trimming/output.txt *.svclog micro.exe -positive.exe \ No newline at end of file +positive.exe +/tests/FSharp.Compiler.ComponentTests/FSharpChecker/StandardError.txt +/tests/FSharp.Compiler.ComponentTests/FSharpChecker/StandardOutput.txt + +# ilverify baseline result files +*.bsl.actual \ No newline at end of file diff --git a/DEVGUIDE.md b/DEVGUIDE.md index cf3a9419481..c178ee2b9c4 100644 --- a/DEVGUIDE.md +++ b/DEVGUIDE.md @@ -204,6 +204,33 @@ Linux/macOS: export TEST_UPDATE_BSL=1 ``` +## Retain Test run built artifacts + +When investigating tests issues it is sometimes usefull to examine the artifacts built whe running tests. Those built using the newer test framework are usually, +built in the %TEMP%\FSharp.Test.Utilities subdirectory. + +To tell the test framework to not cleanup these files use the: FSHARP_RETAIN_TESTBUILDS environment variable + +Windows: + +CMD: + +```shell +set FSHARP_RETAIN_TESTBUILDS=1 +``` + +PowerShell: + +```shell +$env:FSHARP_RETAIN_TESTBUILDS=1 +``` + +Linux/macOS: + +```shell +export FSHARP_RETAIN_TESTBUILDS=1 +``` + Next, run a build script build (debug or release, desktop or coreclr, depending which baselines you need to update), and test as described [above](#Testing-from-the-command-line). For example: `./Build.cmd -c Release -testCoreClr` to update Release CoreCLR baselines. diff --git a/docs/release-notes/.FSharp.Compiler.Service/9.0.200.md b/docs/release-notes/.FSharp.Compiler.Service/9.0.200.md index a67c88e5284..305f23564c5 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/9.0.200.md +++ b/docs/release-notes/.FSharp.Compiler.Service/9.0.200.md @@ -1,5 +1,6 @@ ### Fixed +* Fix Realsig+ generates nested closures with incorrect Generic ([Issue #17797](https://github.com/dotnet/fsharp/issues/17797), [PR #17877](https://github.com/dotnet/fsharp/pull/17877)) * Fix missing TailCall warning in Sequential in use scope ([PR #17927](https://github.com/dotnet/fsharp/pull/17927)) * Fix false negatives for passing null to "obj" arguments. Only "obj | null" can now subsume any type ([PR #17757](https://github.com/dotnet/fsharp/pull/17757)) * Fix internal error when calling 'AddSingleton' and other overloads only differing in generic arity ([PR #17804](https://github.com/dotnet/fsharp/pull/17804)) diff --git a/src/Compiler/CodeGen/IlxGen.fs b/src/Compiler/CodeGen/IlxGen.fs index 60a6f012976..861caeea4ab 100644 --- a/src/Compiler/CodeGen/IlxGen.fs +++ b/src/Compiler/CodeGen/IlxGen.fs @@ -521,7 +521,8 @@ let ComputeTypeAccess (tref: ILTypeRef) hidden (accessibility: Accessibility) re /// Indicates how type parameters are mapped to IL type variables [] -type TypeReprEnv(reprs: Map, count: int, templateReplacement: (TyconRef * ILTypeRef * Typars * TyparInstantiation) option) = +type TypeReprEnv + (reprs: Map, count: int, templateReplacement: (TyconRef * ILTypeRef * Typars * TyparInstantiation) option) = static let empty = TypeReprEnv(count = 0, reprs = Map.empty, templateReplacement = None) @@ -536,7 +537,7 @@ type TypeReprEnv(reprs: Map, count: int, templateReplacement: (Ty /// Lookup a type parameter member _.Item(tp: Typar, m: range) = try - reprs[tp.Stamp] + reprs[tp.Stamp] |> fst with :? KeyNotFoundException -> errorR (InternalError("Undefined or unsolved type variable: " + showL (typarL tp), m)) // Random value for post-hoc diagnostic analysis on generated tree * @@ -546,7 +547,7 @@ type TypeReprEnv(reprs: Map, count: int, templateReplacement: (Ty /// then it is ignored, since it doesn't correspond to a .NET type parameter. member tyenv.AddOne(tp: Typar) = if IsNonErasedTypar tp then - TypeReprEnv(reprs.Add(tp.Stamp, uint16 count), count + 1, templateReplacement) + TypeReprEnv(reprs.Add(tp.Stamp, (uint16 count, tp)), count + 1, templateReplacement) else tyenv @@ -573,6 +574,14 @@ type TypeReprEnv(reprs: Map, count: int, templateReplacement: (Ty /// Get the environment for generating a reference to items within a type definition member eenv.ForTyconRef(tcref: TyconRef) = eenv.ForTycon tcref.Deref + /// Get a list of the Typars in this environment + member eenv.AsUserProvidedTypars() = + reprs + |> Map.toList + |> List.map (fun (_, (_, tp)) -> tp) + |> List.filter (fun tp -> not tp.IsCompilerGenerated) + |> Zset.ofList typarOrder + //-------------------------------------------------------------------------- // Generate type references //-------------------------------------------------------------------------- @@ -6904,14 +6913,6 @@ and GenFreevar cenv m eenvouter tyenvinner (fv: Val) = and GetIlxClosureFreeVars cenv m (thisVars: ValRef list) boxity eenv takenNames expr = let g = cenv.g - // Choose a base name for the closure - let basename = - let boundv = eenv.letBoundVars |> List.tryFind (fun v -> not v.IsCompilerGenerated) - - match boundv with - | Some v -> v.CompiledName cenv.g.CompilerGlobalState - | None -> "clo" - // Get a unique stamp for the closure. This must be stable for things that can be part of a let rec. let uniq = match expr with @@ -6921,18 +6922,34 @@ and GetIlxClosureFreeVars cenv m (thisVars: ValRef list) boxity eenv takenNames | _ -> newUnique () // Choose a name for the closure - let ilCloTypeRef = + let ilCloTypeRef, initialFreeTyvars = + let boundvar = + eenv.letBoundVars |> List.tryFind (fun v -> not v.IsCompilerGenerated) + + let basename = + match boundvar with + | Some v -> v.CompiledName cenv.g.CompilerGlobalState + | None -> "clo" + // FSharp 1.0 bug 3404: System.Reflection doesn't like '.' and '`' in type names let basenameSafeForUseAsTypename = CleanUpGeneratedTypeName basename - let suffixmark = expr.Range - let cloName = // Ensure that we have an g.CompilerGlobalState assert (g.CompilerGlobalState |> Option.isSome) - g.CompilerGlobalState.Value.StableNameGenerator.GetUniqueCompilerGeneratedName(basenameSafeForUseAsTypename, suffixmark, uniq) + g.CompilerGlobalState.Value.StableNameGenerator.GetUniqueCompilerGeneratedName(basenameSafeForUseAsTypename, expr.Range, uniq) + + let ilCloTypeRef = NestedTypeRefForCompLoc eenv.cloc cloName - NestedTypeRefForCompLoc eenv.cloc cloName + let initialFreeTyvars = + match g.realsig with + | true -> + { emptyFreeTyvars with + FreeTypars = eenv.tyenv.AsUserProvidedTypars() + } + | false -> emptyFreeTyvars + + ilCloTypeRef, initialFreeTyvars // Collect the free variables of the closure let cloFreeVarResults = @@ -6943,7 +6960,12 @@ and GetIlxClosureFreeVars cenv m (thisVars: ValRef list) boxity eenv takenNames | None -> opts | Some(tcref, _, typars, _) -> opts.WithTemplateReplacement(tyconRefEq g tcref, typars) - freeInExpr opts expr + accFreeInExpr + opts + expr + { emptyFreeVars with + FreeTyvars = initialFreeTyvars + } // Partition the free variables when some can be accessed from places besides the immediate environment // Also filter out the current value being bound, if any, as it is available from the "this" diff --git a/src/Compiler/TypedTree/CompilerGlobalState.fs b/src/Compiler/TypedTree/CompilerGlobalState.fs index 72da3da4f58..12dda2b08d8 100644 --- a/src/Compiler/TypedTree/CompilerGlobalState.fs +++ b/src/Compiler/TypedTree/CompilerGlobalState.fs @@ -73,4 +73,6 @@ let newUnique() = System.Threading.Interlocked.Increment &uniqueCount /// Unique name generator for stamps attached to to val_specs, tycon_specs etc. //++GLOBAL MUTABLE STATE (concurrency-safe) let mutable private stampCount = 0L -let newStamp() = System.Threading.Interlocked.Increment &stampCount +let newStamp() = + let stamp = System.Threading.Interlocked.Increment &stampCount + stamp \ No newline at end of file diff --git a/src/Compiler/TypedTree/TypedTreeOps.fsi b/src/Compiler/TypedTree/TypedTreeOps.fsi index 8b2cf510ac9..375339ac2c6 100755 --- a/src/Compiler/TypedTree/TypedTreeOps.fsi +++ b/src/Compiler/TypedTree/TypedTreeOps.fsi @@ -1184,6 +1184,9 @@ val accFreeInDecisionTree: FreeVarOptions -> DecisionTree -> FreeVars -> FreeVar /// Get the free variables in a module definition. val freeInModuleOrNamespace: FreeVarOptions -> ModuleOrNamespaceContents -> FreeVars +/// Get the free variables in an expression with accumulator +val accFreeInExpr: FreeVarOptions -> Expr -> FreeVars -> FreeVars + /// Get the free variables in an expression. val freeInExpr: FreeVarOptions -> Expr -> FreeVars diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/LexicalAnalysis/SymbolicOperators.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/LexicalAnalysis/SymbolicOperators.fs index 331086d940a..73a94c080ec 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/LexicalAnalysis/SymbolicOperators.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/LexicalAnalysis/SymbolicOperators.fs @@ -31,11 +31,38 @@ module SymbolicOperators = // This test was automatically generated (moved from FSharpQA suite - Conformance/LexicalAnalysis/SymbolicOperators) //This code is not sufficiently generic\. The type variable \^T when \^T : \(static member \( \+ \) : \^T \* \^T -> \^a\) could not be generalized because it would escape its scope - [] - let ``SymbolicOperators - E_LessThanDotOpenParen001_fs - --flaterrors`` compilation = - compilation - |> asFsx + [] // RealSig + [] // Regular + [] + let ``SymbolicOperators_E_LessThanDotOpenParen001_fs`` (realsig) = + Fsx """ + +type public TestType<'T,'S>() = + + member public s.Value with get() = Unchecked.defaultof<'T> + static member public (+++) (a : TestType<'T,'S>, b : TestType<'T,'S>) = a.Value + static member public (+++) (a : TestType<'T,'S>, b : 'T) = b + static member public (+++) (a : 'T, b : TestType<'T,'S>) = a + static member public (+++) (a : TestType<'T,'S>, b : 'T -> 'S) = a.Value + static member public (+++) (a : 'S -> 'T, b : TestType<'T,'S>) = (a 17) + b.Value + +let inline (+++) (a : ^a) (b : ^b) = ((^a or ^b): (static member (+++): ^a * ^b -> ^c) (a,b) ) + +let tt0 = TestType() +let tt1 = TestType() + +let f (x : string) = 18 + +let a0 = tt0 +++ tt1 +let a1 = tt0 +++ 11 +let a2 = 12 +++ tt1 +let a3 = tt0 +++ (fun x -> "18") +let a4 = f +++ tt0 + +let a5 = TestType.(+++)(f, tt0) +let a6 = TestType.(+++)((fun (x : string) -> 18), tt0)""" |> withOptions ["--flaterrors"] + |> withRealInternalSignature realsig |> compile |> shouldFail |> withErrorCode 0670 diff --git a/tests/FSharp.Compiler.ComponentTests/Conformance/Types/TypeConstraints/IWSAMsAndSRTPs/IWSAMsAndSRTPsTests.fs b/tests/FSharp.Compiler.ComponentTests/Conformance/Types/TypeConstraints/IWSAMsAndSRTPs/IWSAMsAndSRTPsTests.fs index 942219ba172..f22a18f26c9 100644 --- a/tests/FSharp.Compiler.ComponentTests/Conformance/Types/TypeConstraints/IWSAMsAndSRTPs/IWSAMsAndSRTPsTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Conformance/Types/TypeConstraints/IWSAMsAndSRTPs/IWSAMsAndSRTPsTests.fs @@ -8,18 +8,20 @@ open FSharp.Test.Compiler module TypesAndTypeConstraints_IWSAMsAndSRTPs = - let typesModule = + let typesModule realsig = FSharp (loadSourceFromFile (Path.Combine(__SOURCE_DIRECTORY__, "Types.fs"))) |> withName "Types" |> withLangVersion70 + |> withRealInternalSignature realsig |> withOptions ["--nowarn:3535"] - let setupCompilation compilation = + let setupCompilation realsig compilation = compilation |> asExe |> withLangVersion70 - |> withReferences [typesModule] - + |> withRealInternalSignature realsig + |> withReferences [typesModule realsig] + let verifyCompile compilation = compilation |> asExe @@ -71,7 +73,7 @@ let main _ = #endif let ``IWSAM test files`` compilation = compilation - |> setupCompilation + |> setupCompilation false |> withLangVersionPreview |> compileAndRun |> shouldSucceed @@ -380,43 +382,57 @@ let main _ = |> withDiagnosticMessage errorMessage |> ignore - [] - let ``IWSAM warning`` () = - Fsx "let fExpectAWarning(x: Types.ISinOperator<'T>) = ()" - |> withReferences [typesModule] + [] // RealSig + [] // Regular + [] + let ``IWSAM warning`` (realsig) = + Fsx "let fExpectAWarning(x: Types.ISinOperator<'T>) = (realsig)" + |> withReferences [typesModule realsig] + |> withRealInternalSignature realsig |> compile |> shouldFail |> withWarningCode 3536 |> withDiagnosticMessage """'ISinOperator<_>' is normally used as a type constraint in generic code, e.g. "'T when ISomeInterface<'T>" or "let f (x: #ISomeInterface<_>)". See https://aka.ms/fsharp-iwsams for guidance. You can disable this warning by using '#nowarn "3536"' or '--nowarn:3536'.""" |> ignore - [] - let ``Multiple support types trait error`` () = + [] // RealSig + [] // Regular + [] + let ``Multiple support types trait error`` (realsig) = Fsx "let inline f5 (x: 'T when ('T or int) : (static member A: int) ) = 'T.A" + |> withRealInternalSignature realsig |> compile |> shouldFail |> withErrorCode 3537 |> withDiagnosticMessage "The trait 'A' invoked by this call has multiple support types. This invocation syntax is not permitted for such traits. See https://aka.ms/fsharp-srtp for guidance." |> ignore - [] - let ``SRTP Delegate conversion not supported`` () = + [] // RealSig + [] // Regular + [] + let ``SRTP Delegate conversion not supported`` (realsig) = Fsx "let inline f_TraitWithDelegate<'T when 'T : (static member StaticMethod: x: System.Func -> int) >() = 'T.StaticMethod(fun x -> x + 1)" + |> withRealInternalSignature realsig |> compile |> shouldFail |> withErrorMessage "This function takes too many arguments, or is used in a context where a function is not expected" - [] - let ``SRTP Expression conversion not supported`` () = + [] // RealSig + [] // Regular + [] + let ``SRTP Expression conversion not supported`` (realsig) = Fsx "let inline f_TraitWithExpression<'T when 'T : (static member StaticMethod: x: System.Linq.Expressions.Expression> -> int) >() = 'T.StaticMethod(fun x -> x + 1)" + |> withRealInternalSignature realsig |> compile |> shouldFail |> withErrorMessage "This function takes too many arguments, or is used in a context where a function is not expected" - [] - let ``IWSAM Delegate conversion works`` () = + [] // RealSig + [] // Regular + [] + let ``IWSAM Delegate conversion works`` (realsig) = Fsx """ open Types @@ -428,12 +444,14 @@ let main _ = failwith "Unexpected result" """ - |> setupCompilation + |> setupCompilation realsig |> compileAndRun |> shouldSucceed - [] - let ``IWSAM Expression conversion works`` () = + [] // RealSig + [] // Regular + [] + let ``IWSAM Expression conversion works`` (realsig) = Fsx """ open Types @@ -445,28 +463,36 @@ let main _ = failwith "Unexpected result" """ - |> setupCompilation + |> setupCompilation realsig |> compileAndRun |> shouldSucceed - [] - let ``SRTP Byref can be passed with old syntax`` () = + [] // RealSig + [] // Regular + [] + let ``SRTP Byref can be passed with old syntax`` (realsig) = Fsx "let inline f_TraitWithByref<'T when 'T : ( static member TryParse: string * byref -> bool) >() = let mutable result = 0 (^T : ( static member TryParse: x: string * byref -> bool) (\"42\", &result))" + |> withRealInternalSignature realsig |> compile |> shouldSucceed - [] - let ``SRTP Byref can be passed with new syntax`` () = + [] // RealSig + [] // Regular + [] + let ``SRTP Byref can be passed with new syntax`` (realsig) = Fsx "let inline f_TraitWithByref<'T when 'T : ( static member TryParse: string * byref -> bool) >() = let mutable result = 0 'T.TryParse(\"42\", &result)" + |> withRealInternalSignature realsig |> compile |> shouldSucceed - [] - let ``Call with old syntax`` () = + [] // RealSig + [] // Regular + [] + let ``Call with old syntax`` (realsig) = Fsx """ type C1() = static member X(p: C1 byref) = p @@ -479,11 +505,14 @@ let main _ = if g1 <> c1 then failwith "Unexpected result" """ + |> withRealInternalSignature realsig |> compileExeAndRun |> shouldSucceed - [] - let ``Call with new syntax`` () = + [] // RealSig + [] // Regular + [] + let ``Call with new syntax`` (realsig) = Fsx """ type C2() = static member X(p: C2 byref) = p @@ -495,11 +524,14 @@ let main _ = if g2 <> c2 then failwith "Unexpected result" """ + |> withRealInternalSignature realsig |> compileExeAndRun |> shouldSucceed - [] - let ``Call with tuple`` () = + [] // RealSig + [] // Regular + [] + let ``Call with tuple`` (realsig) = Fsx """ type C3() = @@ -512,11 +544,14 @@ let main _ = if g3 <> c3 then failwith "Unexpected result" """ + |> withRealInternalSignature realsig |> compileExeAndRun |> shouldSucceed - [] - let test4 () = + [] // RealSig + [] // Regular + [] + let test4 (realsig) = Fsx """ type C4() = static member X() = C4() @@ -527,14 +562,17 @@ let main _ = if g4.GetType() <> typeof then failwith "Unexpected result" """ + |> withRealInternalSignature realsig |> compileExeAndRun |> shouldSucceed // NOTE: Trait constraints that involve byref returns currently can never be satisfied by any method. No other warning is given. // This is a bug that may be fixed in the future. // These tests are pinning down current behavior. - [] - let ``Byref returns not allowed`` () = + [] // RealSig + [] // Regular + [] + let ``Byref returns not allowed`` (realsig) = Fsx """ type C5() = static member X(p: C5 byref) = &p @@ -543,12 +581,15 @@ let main _ = let mutable c5 = C5() let g5 () = callX5 &c5 """ + |> withRealInternalSignature realsig |> compile |> shouldFail |> withDiagnosticMessageMatches "This expression was expected to have type\\s+'byref'\\s+but here has type\\s+'C5'" - [] - let ``Byref returns not allowed pt 2`` () = + [] // RealSig + [] // Regular + [] + let ``Byref returns not allowed pt 2`` (realsig) = Fsx """ type C6() = static member X(p: C6 byref) = &p @@ -558,11 +599,12 @@ let main _ = let mutable c6 = C6() let g6 () = callX6 &c6 """ + |> withRealInternalSignature realsig |> compile |> shouldFail |> withDiagnosticMessageMatches "This expression was expected to have type\\s+'byref'\\s+but here has type\\s+'C6'" - let library = + let library realsig= FSharp """ module Lib @@ -580,65 +622,79 @@ let main _ = let add1 (x: int) = x + 1 """ + |> withRealInternalSignature realsig |> withLangVersion70 |> withOptions ["--nowarn:3535"] - [] - let ``Function implicit conversion not supported on constrained type`` () = + [] // RealSig + [] // Regular + [] + let ``Function implicit conversion not supported on constrained type`` (realsig) = Fsx """ open Lib let f_function_implicit_conversion<'T when ICanBeInt<'T>>(a: 'T) : int = add1(a) """ - |> withReferences [library] + |> withReferences [library realsig] |> withLangVersion70 + |> withRealInternalSignature realsig |> compile |> shouldFail |> withDiagnosticMessageMatches "This expression was expected to have type\\s+'int'\\s+but here has type\\s+''T'" - [] - let ``Method implicit conversion not supported on constrained type`` () = + [] // RealSig + [] // Regular + [] + let ``Method implicit conversion not supported on constrained type`` (realsig) = Fsx """ open Lib let f_method_implicit_conversion<'T when ICanBeInt<'T>>(a: 'T) : int = C.TakeInt(a) """ - |> withReferences [library] + |> withRealInternalSignature realsig + |> withReferences [library realsig] |> withLangVersion70 |> compile |> shouldFail |> withDiagnosticMessageMatches "This expression was expected to have type\\s+'int'\\s+but here has type\\s+''T'" - [] - let ``Function explicit conversion works on constrained type`` () = + [] // RealSig + [] // Regular + [] + let ``Function explicit conversion works on constrained type`` (realsig) = Fsx """ open Lib let f_function_explicit_conversion<'T when ICanBeInt<'T>>(a: 'T) : int = add1(int(a)) """ - |> withReferences [library] + |> withReferences [library realsig] |> withLangVersion70 |> compile |> shouldSucceed - [] - let ``Method explicit conversion works on constrained type`` () = + [] // RealSig + [] // Regular + [] + let ``Method explicit conversion works on constrained type`` (realsig) = Fsx """ open Lib let f_method_explicit_conversion<'T when ICanBeInt<'T>>(a: 'T) : int = C.TakeInt(int(a)) """ - |> withReferences [library] + |> withRealInternalSignature realsig + |> withReferences [library realsig] |> withLangVersion70 |> compile |> shouldSucceed - [] - let ``Nominal type can be used after or`` () = + [] // RealSig + [] // Regular + [] + let ``Nominal type can be used after or`` (realsig) = Fsx """ type C() = @@ -652,13 +708,16 @@ let main _ = if not (callX "A" (C()) = "A OK") then failwith "Unexpected result" """ + |> withRealInternalSignature realsig |> withLangVersion70 |> asExe |> compileAndRun |> shouldSucceed - [] - let ``Nominal type can't be used before or`` () = + [] // RealSig + [] // Regular + [] + let ``Nominal type can't be used before or`` (realsig) = Fsx """ type C() = @@ -666,13 +725,16 @@ let main _ = let inline callX (x: 'T) (y: C) = ((C or ^T): (static member X : 'T * C -> string) (x, y));; """ + |> withRealInternalSignature realsig |> withLangVersion70 |> compile |> shouldFail |> withDiagnosticMessageMatches "Unexpected keyword 'static' in binding" - [] - let ``Nominal type is preferred`` () = + [] // RealSig + [] // Regular + [] + let ``Nominal type is preferred`` (realsig) = Fsx """ type C() = @@ -691,12 +753,13 @@ let main _ = if not (callX2 (C()) (D()) = "C") then failwith "Unexpected result" """ + |> withRealInternalSignature realsig |> withLangVersion70 |> asExe |> compileAndRun |> shouldSucceed - let library2 = + let library2 realsig = FSharp """ module Potato.Lib type IPotato<'T when 'T :> IPotato<'T>> = @@ -713,12 +776,15 @@ let main _ = static member IsGood c = false static member op_Equality (a, b) = false """ + |> withRealInternalSignature realsig |> withLangVersion70 |> withName "Potato" |> withOptions ["--nowarn:3535"] - [] - let ``Active patterns- Using IWSAM in active pattern`` () = + [] // RealSig + [] // Regular + [] + let ``Active patterns- Using IWSAM in active pattern`` (realsig) = FSharp """ module Potato.Test @@ -729,7 +795,8 @@ let main _ = match Potato() with GoodPotato -> () | _ -> failwith "Unexpected result" match Rock() with GoodPotato -> failwith "Unexpected result" | _ -> () """ - |> withReferences [library2] + |> withReferences [library2 realsig] + |> withRealInternalSignature realsig |> withLangVersion70 |> compileExeAndRun |> shouldSucceed @@ -746,8 +813,10 @@ let main _ = """ ] - [] - let ``Active patterns - Using IWSAM equality in active pattern uses generic equality intrinsic`` () = + [] // RealSig + [] // Regular + [] + let ``Active patterns - Using IWSAM equality in active pattern uses generic equality intrinsic`` (realsig) = FSharp """ module Potato.Test @@ -762,7 +831,8 @@ let main _ = | IsEqual -> failwith "Unexpected result" | IsNonEqual -> () """ - |> withReferences [library2] + |> withReferences [library2 realsig] + |> withRealInternalSignature realsig |> withLangVersion70 |> asExe |> compileAndRun @@ -780,12 +850,15 @@ let main _ = """ ] - [] - let ``Suppression of System Numerics interfaces on unitized types`` () = + [] // RealSig + [] // Regular + [] + let ``Suppression of System Numerics interfaces on unitized types`` (realsig) = Fsx """ open System.Numerics let f (x: 'T when 'T :> IMultiplyOperators<'T,'T,'T>) = x;; f 3.0 |> ignore""" + |> withRealInternalSignature realsig |> withLangVersion70 |> compile |> shouldSucceed @@ -840,8 +913,10 @@ let main _ = |> shouldFail |> withErrorMessage $"The type 'float' is not compatible with the type '{potatoType}'" - [] - let ``Interface A with static abstracts can be inherited in interface B and then implemented in type C which inherits B in lang version70`` () = + [] // RealSig + [] // Regular + [] + let ``Interface A with static abstracts can be inherited in interface B and then implemented in type C which inherits B in lang version70`` (realsig) = Fsx """ type IParsable<'T when 'T :> IParsable<'T>> = static abstract member Parse : string -> 'T @@ -863,12 +938,15 @@ let main _ = failwith "failed" """ |> withNoWarn 3535 + |> withRealInternalSignature realsig |> withLangVersion70 |> compile |> shouldSucceed - [] - let ``Static abstracts can be inherited through multiple levels in lang version70`` () = + [] // RealSig + [] // Regular + [] + let ``Static abstracts can be inherited through multiple levels in lang version70`` (realsig) = Fsx """ type IParsable<'T when 'T :> IParsable<'T>> = static abstract member Parse : string -> 'T @@ -902,12 +980,15 @@ let main _ = failwith "failed" """ |> withNoWarn 3535 + |> withRealInternalSignature realsig |> withLangVersion70 |> compile |> shouldSucceed - [] - let ``Static abstracts from BCL can be inherited through multiple levels in lang version70`` () = + [] // RealSig + [] // Regular + [] + let ``Static abstracts from BCL can be inherited through multiple levels in lang version70`` (realsig) = Fsx """ open System open System.Globalization @@ -927,12 +1008,15 @@ let main _ = failwith "failed" """ |> withNoWarn 3535 + |> withRealInternalSignature realsig |> withLangVersion70 |> compile |> shouldSucceed - - [] - let ``Produce an error when one leaves out keyword "static" in an implementation of IWSAM`` () = + + [] // RealSig + [] // Regular + [] + let ``Produce an error when one leaves out keyword "static" in an implementation of IWSAM`` (realsig) = Fsx """ module StaticAbstractBug = type IOperation = @@ -951,19 +1035,22 @@ module StaticAbstractBug = member this.Property3 = 0 member this.Property3 with set value = () """ - |> withOptions [ "--nowarn:3535" ] - |> withLangVersion80 - |> compile - |> shouldFail - |> withDiagnostics [ + |> withOptions [ "--nowarn:3535" ] + |> withRealInternalSignature realsig + |> withLangVersion80 + |> compile + |> shouldFail + |> withDiagnostics [ (Error 855, Line 12, Col 22, Line 12, Col 29, "No abstract or interface member was found that corresponds to this override") (Error 859, Line 14, Col 25, Line 14, Col 33, "No abstract property was found that corresponds to this override") (Error 859, Line 16, Col 25, Line 16, Col 34, "No abstract property was found that corresponds to this override") (Error 859, Line 17, Col 25, Line 17, Col 34, "No abstract property was found that corresponds to this override") - ] - - [] - let ``Produce an error when one leaves out keyword "static" in an implementation of IWSAM with multiple overloads`` () = + ] + + [] // RealSig + [] // Regular + [] + let ``Produce an error when one leaves out keyword "static" in an implementation of IWSAM with multiple overloads`` (realsig) = Fsx """ module StaticAbstractBug = type IOperation = @@ -979,11 +1066,12 @@ module StaticAbstractBug = member this.Property = 0 member this.Property = false """ - |> withOptions [ "--nowarn:3535" ] - |> withLangVersion80 - |> compile - |> shouldFail - |> withDiagnostics [ + |> withOptions [ "--nowarn:3535" ] + |> withRealInternalSignature realsig + |> withLangVersion80 + |> compile + |> shouldFail + |> withDiagnostics [ (Error 1, Line 11, Col 34, Line 11, Col 36, "This expression was expected to have type 'bool' but here has type @@ -992,10 +1080,12 @@ but here has type 'int' but here has type 'bool' ") - ] - - [] - let ``Produce an error for interface with static abstract member that is implemented as instance member`` () = + ] + + [] // RealSig + [] // Regular + [] + let ``Produce an error for interface with static abstract member that is implemented as instance member`` (realsig) = Fsx """ module StaticAbstractBug = type IFoo<'T> = @@ -1015,19 +1105,22 @@ module StaticAbstractBug = member this.Property3 = 0 member this.Property3 with set value = () """ - |> withOptions [ "--nowarn:3535" ] - |> withLangVersion80 - |> compile - |> shouldFail - |> withDiagnostics [ + |> withOptions [ "--nowarn:3535" ] + |> withRealInternalSignature realsig + |> withLangVersion80 + |> compile + |> shouldFail + |> withDiagnostics [ (Error 855, Line 14, Col 18, Line 14, Col 23, "No abstract or interface member was found that corresponds to this override"); (Error 859, Line 15, Col 21, Line 15, Col 29, "No abstract property was found that corresponds to this override"); (Error 859, Line 17, Col 21, Line 17, Col 30, "No abstract property was found that corresponds to this override"); (Error 859, Line 18, Col 21, Line 18, Col 30, "No abstract property was found that corresponds to this override") - ] + ] - [] - let ``Produce an error for interface with static abstract member that is implemented as instance member with multiple overloads`` () = + [] // RealSig + [] // Regular + [] + let ``Produce an error for interface with static abstract member that is implemented as instance member with multiple overloads`` (realsig) = Fsx """ module StaticAbstractBug = type IFoo<'T> = @@ -1046,11 +1139,12 @@ module StaticAbstractBug = member this.Property = 0 member this.Property = false """ - |> withOptions [ "--nowarn:3535" ] - |> withLangVersion80 - |> compile - |> shouldFail - |> withDiagnostics [ + |> withOptions [ "--nowarn:3535" ] + |> withRealInternalSignature realsig + |> withLangVersion80 + |> compile + |> shouldFail + |> withDiagnostics [ (Error 1, Line 14, Col 41, Line 14, Col 42, "The type 'bool' does not match the type 'int'") (Error 1, Line 16, Col 32, Line 16, Col 33, "This expression was expected to have type 'bool' @@ -1058,8 +1152,10 @@ but here has type 'int' ") ] - [] - let ``Produce an error when one leaves out keyword "static" in multiple IWSAM implementations`` () = + [] // RealSig + [] // Regular + [] + let ``Produce an error when one leaves out keyword "static" in multiple IWSAM implementations`` (realsig) = Fsx """ module StaticAbstractBug = type IOperation = @@ -1079,17 +1175,20 @@ module StaticAbstractBug = member this.Execute() = 0 member this.Execute2() = () """ - |> withOptions [ "--nowarn:3535" ] - |> withLangVersion80 - |> compile - |> shouldFail - |> withDiagnostics [ + |> withOptions [ "--nowarn:3535" ] + |> withLangVersion80 + |> withRealInternalSignature realsig + |> compile + |> shouldFail + |> withDiagnostics [ (Error 855, Line 13, Col 25, Line 13, Col 32, "No abstract or interface member was found that corresponds to this override") (Error 855, Line 17, Col 25, Line 17, Col 32, "No abstract or interface member was found that corresponds to this override") - ] + ] - [] - let ``Produces errors when includes keyword "static" when implementing a generic interface in a type`` () = + [] // RealSig + [] // Regular + [] + let ``Produces errors when includes keyword "static" when implementing a generic interface in a type`` (realsig) = Fsx """ module StaticAbstractBug = type IFoo<'T> = @@ -1109,21 +1208,24 @@ module StaticAbstractBug = static member Property3 = 0 static member Property3 with set value = () """ - |> withOptions [ "--nowarn:3536" ; "--nowarn:3535" ] - |> withLangVersion80 - |> typecheck - |> shouldFail - |> withDiagnostics [ + |> withOptions [ "--nowarn:3536" ; "--nowarn:3535" ] + |> withRealInternalSignature realsig + |> withLangVersion80 + |> typecheck + |> shouldFail + |> withDiagnostics [ (Error 3855, Line 13, Col 23, Line 13, Col 27, "No static abstract member was found that corresponds to this override") (Error 3855, Line 14, Col 23, Line 14, Col 28, "No static abstract member was found that corresponds to this override") (Error 3859, Line 15, Col 23, Line 15, Col 31, "No static abstract property was found that corresponds to this override") (Error 3859, Line 16, Col 23, Line 16, Col 32, "No static abstract property was found that corresponds to this override") (Error 3859, Line 17, Col 23, Line 17, Col 32, "No static abstract property was found that corresponds to this override") (Error 3859, Line 18, Col 23, Line 18, Col 32, "No static abstract property was found that corresponds to this override") - ] - - [] - let ``Produces errors when includes keyword "static" when implementing an interface in a type`` () = + ] + + [] // RealSig + [] // Regular + [] + let ``Produces errors when includes keyword "static" when implementing an interface in a type`` (realsig) = Fsx """ module StaticAbstractBug = type IOperation = @@ -1139,19 +1241,22 @@ module StaticAbstractBug = static member Property = 0 static member Property = false """ - |> withOptions [ "--nowarn:3536" ; "--nowarn:3535" ] - |> withLangVersion80 - |> typecheck - |> shouldFail - |> withDiagnostics [ + |> withOptions [ "--nowarn:3536" ; "--nowarn:3535" ] + |> withRealInternalSignature realsig + |> withLangVersion80 + |> typecheck + |> shouldFail + |> withDiagnostics [ (Error 3855, Line 11, Col 27, Line 11, Col 34, "No static abstract member was found that corresponds to this override") (Error 3855, Line 12, Col 27, Line 12, Col 34, "No static abstract member was found that corresponds to this override") (Error 3859, Line 13, Col 27, Line 13, Col 35, "No static abstract property was found that corresponds to this override") (Error 3859, Line 14, Col 27, Line 14, Col 35, "No static abstract property was found that corresponds to this override") - ] - - [] - let ``No error when implementing interfaces with static members by using class types`` () = + ] + + [] // RealSig + [] // Regular + [] + let ``No error when implementing interfaces with static members by using class types`` (realsig) = Fsx """ type IPrintable = abstract member Print: unit -> unit @@ -1170,13 +1275,16 @@ let someClass1 = SomeClass1(1, 2.0) someClass.Print() someClass1.GetPrint() """ - |> withOptions [ "--nowarn:3536" ; "--nowarn:3535" ] - |> withLangVersion80 - |> typecheck - |> shouldSucceed - - [] - let ``No error when implementing interfaces with static members and IWSAM by using class types`` () = + |> withOptions [ "--nowarn:3536" ; "--nowarn:3535" ] + |> withRealInternalSignature realsig + |> withLangVersion80 + |> typecheck + |> shouldSucceed + + [] // RealSig + [] // Regular + [] + let ``No error when implementing interfaces with static members and IWSAM by using class types`` (realsig) = Fsx """ [] type IPrintable = @@ -1190,39 +1298,46 @@ type SomeClass1() = let someClass1 = SomeClass1() let execute = IPrintable.Say("hello") """ - |> withOptions [ "--nowarn:3536" ; "--nowarn:3535" ] - |> withLangVersion80 - |> typecheck - |> shouldSucceed + |> withOptions [ "--nowarn:3536" ; "--nowarn:3535" ] + |> withRealInternalSignature realsig + |> withLangVersion80 + |> typecheck + |> shouldSucceed - [] - let ``Accessing to IWSAM(System.Numerics non virtual) produces a compilation error`` () = + [] // RealSig + [] // Regular + [] + let ``Accessing to IWSAM(System.Numerics non virtual) produces a compilation error`` (realsig) = Fsx """ open System.Numerics IAdditionOperators.op_Addition (3, 6) - """ - |> withOptions [ "--nowarn:3536" ; "--nowarn:3535" ] - |> withLangVersion80 - |> compile - |> shouldFail - |> withSingleDiagnostic (Error 3866, Line 4, Col 1, Line 4, Col 38, "A static abstract non-virtual interface member should only be called via type parameter (for example: 'T.op_Addition).") - - [] - let ``Accessing to IWSAM(System.Numerics virtual member) compiles and runs`` () = + """ + |> withOptions [ "--nowarn:3536" ; "--nowarn:3535" ] + |> withRealInternalSignature realsig + |> withLangVersion80 + |> compile + |> shouldFail + |> withSingleDiagnostic (Error 3866, Line 4, Col 1, Line 4, Col 38, "A static abstract non-virtual interface member should only be called via type parameter (for example: 'T.op_Addition).") + + [] // RealSig + [] // Regular + [] + let ``Accessing to IWSAM(System.Numerics virtual member) compiles and runs`` (realsig) = Fsx """ open System.Numerics let res = IAdditionOperators.op_CheckedAddition (3, 6) printf "%A" res""" - |> withOptions [ "--nowarn:3536" ; "--nowarn:3535" ] - |> withLangVersion80 - |> asExe - |> compile - |> shouldSucceed - |> run - |> verifyOutput "9" + |> withOptions [ "--nowarn:3536" ; "--nowarn:3535" ] + |> withRealInternalSignature realsig + |> withLangVersion80 + |> asExe + |> compile + |> shouldSucceed + |> run + |> verifyOutput "9" #if !NETCOREAPP [] @@ -1241,35 +1356,43 @@ printf "%A" res""" (Error 3866, Line 15, Col 82, Line 15, Col 129, "A static abstract non-virtual interface member should only be called via type parameter (for example: 'T.Parse).") ] - [] - let ``Error message that explicitly disallows static abstract methods in abstract classes.`` () = + [] // RealSig + [] // Regular + [] + let ``Error message that explicitly disallows static abstract methods in abstract classes.`` (realsig) = Fsx """ [] type A () = static abstract M : unit -> unit """ |> withOptions [ "--nowarn:3536" ; "--nowarn:3535" ] + |> withRealInternalSignature realsig |> typecheck |> shouldFail |> withDiagnostics [ (Error 3867, Line 4, Col 21, Line 4, Col 22, "Classes cannot contain static abstract members.") ] - [] - let ``Error message that explicitly disallows static abstract methods in classes.`` () = + [] // RealSig + [] // Regular + [] + let ``Error message that explicitly disallows static abstract methods in classes.`` (realsig) = Fsx """ type A () = static abstract M : unit -> unit """ |> withOptions [ "--nowarn:3536" ; "--nowarn:3535" ] + |> withRealInternalSignature realsig |> typecheck |> shouldFail |> withDiagnostics [ (Error 3867, Line 3, Col 21, Line 3, Col 22, "Classes cannot contain static abstract members.") ] - - [] - let ``Access modifiers cannot be applied to an SRTP constraint in preview`` () = + + [] // RealSig + [] // Regular + [] + let ``Access modifiers cannot be applied to an SRTP constraint in preview`` (realsig) = FSharp """ let inline length (x: ^a when ^a: (member public Length: int)) = x.Length let inline length2 (x: ^a when ^a: (member Length: int with public get)) = x.Length @@ -1277,6 +1400,7 @@ let inline length3 (x: ^a when ^a: (member Length: int with public set)) = x.set let inline length4 (x: ^a when ^a: (member public get_Length: unit -> int)) = x.get_Length() """ |> withLangVersionPreview + |> withRealInternalSignature realsig |> typecheck |> shouldFail |> withDiagnostics [ @@ -1285,9 +1409,11 @@ let inline length4 (x: ^a when ^a: (member public get_Length: unit -> int)) = x. (Error 3871, Line 4, Col 61, Line 4, Col 67, "Access modifiers cannot be applied to an SRTP constraint.") (Error 3871, Line 5, Col 44, Line 5, Col 50, "Access modifiers cannot be applied to an SRTP constraint.") ] - - [] - let ``Access modifiers in an SRTP constraint generate warning in F# 8.0`` () = + + [] // RealSig + [] // Regular + [] + let ``Access modifiers in an SRTP constraint generate warning in F# 8.0`` (realsig) = FSharp """ let inline length (x: ^a when ^a: (member public Length: int)) = x.Length let inline length2 (x: ^a when ^a: (member Length: int with public get)) = x.Length @@ -1295,6 +1421,7 @@ let inline length3 (x: ^a when ^a: (member Length: int with public set)) = x.set let inline length4 (x: ^a when ^a: (member public get_Length: unit -> int)) = x.get_Length() """ |> withLangVersion80 + |> withRealInternalSignature realsig |> typecheck |> shouldFail |> withDiagnostics [ @@ -1304,8 +1431,10 @@ let inline length4 (x: ^a when ^a: (member public get_Length: unit -> int)) = x. (Warning 3871, Line 5, Col 44, Line 5, Col 50, "Access modifiers cannot be applied to an SRTP constraint.") ] - [] - let ``Error for partial implementation of interface with static abstract members`` () = + [] // RealSig + [] // Regular + [] + let ``Error for partial implementation of interface with static abstract members`` (realsig) = Fsx """ type IFace = static abstract P1 : int @@ -1317,14 +1446,17 @@ type T = """ |> withOptions [ "--nowarn:3536" ; "--nowarn:3535" ] + |> withRealInternalSignature realsig |> typecheck |> shouldFail |> withDiagnostics [ (Error 366, Line 7, Col 15, Line 7, Col 20, "No implementation was given for 'static abstract IFace.P2: int'. Note that all interface members must be implemented and listed under an appropriate 'interface' declaration, e.g. 'interface ... with member ...'.") ] - - [] - let ``Error for no implementation of interface with static abstract members`` () = + + [] // RealSig + [] // Regular + [] + let ``Error for no implementation of interface with static abstract members`` (realsig) = Fsx """ type IFace = static abstract P1 : int @@ -1334,6 +1466,7 @@ type T = interface IFace with """ |> withOptions [ "--nowarn:3536" ; "--nowarn:3535" ] + |> withRealInternalSignature realsig |> typecheck |> shouldFail |> withDiagnostics [ @@ -1343,8 +1476,10 @@ type T = Note that all interface members must be implemented and listed under an appropriate 'interface' declaration, e.g. 'interface ... with member ...'.") ] - [] - let ``Error for partial implementation of interface with static and non static abstract members`` () = + [] // RealSig + [] // Regular + [] + let ``Error for partial implementation of interface with static and non static abstract members`` (realsig) = Fsx """ type IFace = static abstract P1 : int @@ -1359,6 +1494,7 @@ type T = """ |> withOptions [ "--nowarn:3536" ; "--nowarn:3535" ] + |> withRealInternalSignature realsig |> typecheck |> shouldFail |> withDiagnostics [ @@ -1367,9 +1503,11 @@ type T = 'abstract IFace.P4: int' Note that all interface members must be implemented and listed under an appropriate 'interface' declaration, e.g. 'interface ... with member ...'.") ] - - [] - let ``Error for no implementation of interface with static and non static abstract members`` () = + + [] // RealSig + [] // Regular + [] + let ``Error for no implementation of interface with static and non static abstract members`` (realsig) = Fsx """ type IFace = static abstract P1 : int @@ -1379,9 +1517,10 @@ type IFace = type T = interface IFace with - + """ |> withOptions [ "--nowarn:3536" ; "--nowarn:3535" ] + |> withRealInternalSignature realsig |> typecheck |> shouldFail |> withDiagnostics [ @@ -1393,8 +1532,10 @@ type T = Note that all interface members must be implemented and listed under an appropriate 'interface' declaration, e.g. 'interface ... with member ...'.") ] - [] - let ``Error for partial implementation of interface with non static abstract members`` () = + [] // RealSig + [] // Regular + [] + let ``Error for partial implementation of interface with non static abstract members`` (realsig) = Fsx """ type IFace = abstract member P3 : int @@ -1403,17 +1544,20 @@ type IFace = type T = interface IFace with member this.P3 = 3 - + """ |> withOptions [ "--nowarn:3536" ; "--nowarn:3535" ] + |> withRealInternalSignature realsig |> typecheck |> shouldFail |> withDiagnostics [ (Error 366, Line 7, Col 15, Line 7, Col 20, "No implementation was given for 'abstract IFace.P4: int'. Note that all interface members must be implemented and listed under an appropriate 'interface' declaration, e.g. 'interface ... with member ...'.") ] - - [] - let ``Error for no implementation of interface with non static abstract members`` () = + + [] // RealSig + [] // Regular + [] + let ``Error for no implementation of interface with non static abstract members`` (realsig) = Fsx """ type IFace = abstract member P3 : int @@ -1424,6 +1568,7 @@ type T = """ |> withOptions [ "--nowarn:3536" ; "--nowarn:3535" ] + |> withRealInternalSignature realsig |> typecheck |> shouldFail |> withDiagnostics [ diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/ComputedCollections/ComputedCollections.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/ComputedCollections/ComputedCollections.fs index 6b4788a5103..53ef5aa0054 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/ComputedCollections/ComputedCollections.fs +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/ComputedCollections/ComputedCollections.fs @@ -5,9 +5,10 @@ open FSharp.Test.Compiler open Xunit module ComputedCollections = - let verifyCompilation compilation = + let verifyCompilation realsig compilation = compilation |> asExe + |> withRealInternalSignature realsig |> withOptimize |> withEmbeddedPdb |> withEmbedAllSource @@ -17,59 +18,59 @@ module ComputedCollections = [] let ``Int32RangeArrays_fs`` compilation = compilation - |> verifyCompilation + |> verifyCompilation false [] let ``Int32RangeLists_fs`` compilation = compilation - |> verifyCompilation + |> verifyCompilation false [] let ``UInt64RangeArrays_fs`` compilation = compilation - |> verifyCompilation + |> verifyCompilation false [] let ``UInt64RangeLists_fs`` compilation = compilation - |> verifyCompilation + |> verifyCompilation false [] let ``ForNInRangeArrays_fs`` compilation = compilation - |> verifyCompilation + |> verifyCompilation false [] let ``ForNInRangeLists_fs`` compilation = compilation - |> verifyCompilation + |> verifyCompilation false [] let ``ForXInArray_ToArray_fs`` compilation = compilation - |> verifyCompilation + |> verifyCompilation false [] let ``ForXInArray_ToList_fs`` compilation = compilation - |> verifyCompilation + |> verifyCompilation false [] let ``ForXInList_ToArray_fs`` compilation = compilation - |> verifyCompilation + |> verifyCompilation false [] let ``ForXInList_ToList_fs`` compilation = compilation - |> verifyCompilation + |> verifyCompilation false [] let ``ForXInSeq_ToArray_fs`` compilation = compilation - |> verifyCompilation + |> verifyCompilation false [] let ``ForXInSeq_ToList_fs`` compilation = compilation - |> verifyCompilation + |> verifyCompilation false diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/ComputedCollections/ForXInList_ToList.fs.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/ComputedCollections/ForXInList_ToList.fs.il.bsl index 614d86d0f56..1c4d00cee7e 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/ComputedCollections/ForXInList_ToList.fs.il.bsl +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/ComputedCollections/ForXInList_ToList.fs.il.bsl @@ -1274,7 +1274,7 @@ IL_0001: ldsfld class assembly/'for _ in List-groupBy id -- do ---@28' assembly/'for _ in List-groupBy id -- do ---@28'::@_instance IL_0006: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_Empty() IL_000b: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1>> [FSharp.Core]Microsoft.FSharp.Collections.ListModule::GroupBy(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2, - class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) + class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) IL_0010: stloc.1 IL_0011: ldloc.1 IL_0012: call instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1>>::get_TailOrNull() @@ -1313,7 +1313,7 @@ IL_0001: ldsfld class assembly/'for _ | _ in List-groupBy id -- do ---@29' assembly/'for _ | _ in List-groupBy id -- do ---@29'::@_instance IL_0006: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_Empty() IL_000b: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1>> [FSharp.Core]Microsoft.FSharp.Collections.ListModule::GroupBy(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2, - class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) + class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) IL_0010: stloc.1 IL_0011: ldloc.1 IL_0012: call instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1>>::get_TailOrNull() @@ -1352,7 +1352,7 @@ IL_0001: ldsfld class assembly/'for _ - _ in List-groupBy id -- do ---@30' assembly/'for _ - _ in List-groupBy id -- do ---@30'::@_instance IL_0006: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_Empty() IL_000b: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1>> [FSharp.Core]Microsoft.FSharp.Collections.ListModule::GroupBy(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2, - class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) + class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) IL_0010: stloc.1 IL_0011: ldloc.1 IL_0012: call instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1>>::get_TailOrNull() @@ -1391,7 +1391,7 @@ IL_0001: ldsfld class assembly/'for _, _group in List-groupBy id -- do ---@31' assembly/'for _, _group in List-groupBy id -- do ---@31'::@_instance IL_0006: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_Empty() IL_000b: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1>> [FSharp.Core]Microsoft.FSharp.Collections.ListModule::GroupBy(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2, - class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) + class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) IL_0010: stloc.1 IL_0011: ldloc.1 IL_0012: call instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1>>::get_TailOrNull() @@ -1431,7 +1431,7 @@ IL_0001: ldsfld class assembly/'for _, group in List-groupBy id -- do ---@32' assembly/'for _, group in List-groupBy id -- do ---@32'::@_instance IL_0006: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1::get_Empty() IL_000b: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1>> [FSharp.Core]Microsoft.FSharp.Collections.ListModule::GroupBy(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2, - class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) + class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1) IL_0010: stloc.1 IL_0011: ldloc.1 IL_0012: call instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1>>::get_TailOrNull() diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DoNotBoxStruct/DoNotBoxStruct.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DoNotBoxStruct/DoNotBoxStruct.fs index 883490978dc..d6aea77a5e2 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DoNotBoxStruct/DoNotBoxStruct.fs +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DoNotBoxStruct/DoNotBoxStruct.fs @@ -7,13 +7,16 @@ open FSharp.Test.Compiler module DoNotBoxStruct = - let computationExprLibrary = - FsxFromPath (Path.Combine(__SOURCE_DIRECTORY__, "DoNotBoxStruct_ArrayOfArray_FSInterface_NoExtMeth.fs")) - |> withName "DoNotBoxStruct_ArrayOfArray_FSInterface_NoExtMeth_fs" + let verifyCompilation realsig compilation = + + let computationExprLibrary = + FsxFromPath (Path.Combine(__SOURCE_DIRECTORY__, "DoNotBoxStruct_ArrayOfArray_FSInterface_NoExtMeth.fs")) + |> withRealInternalSignature realsig + |> withName "DoNotBoxStruct_ArrayOfArray_FSInterface_NoExtMeth_fs" - let verifyCompilation compilation = compilation |> asFs + |> withRealInternalSignature realsig |> withOptions ["--test:EmitFeeFeeAs100001"] |> asExe |> withReferences [computationExprLibrary] @@ -27,76 +30,76 @@ module DoNotBoxStruct = [] let ``DoNotBoxStruct_ArrayOfArray_FSInterface_NoExtMeth_fs`` compilation = compilation - |> verifyCompilation + |> verifyCompilation false //SOURCE=DoNotBoxStruct_Array_FSInterface_NoExtMeth.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd DoNotBoxStruct_Array_FSInterface_NoExtMeth.exe" # DoNotBoxStruct_Array_FSInterface_NoExtMeth.fs [] let ``DoNotBoxStruct_Array_FSInterface_NoExtMeth_fs`` compilation = compilation - |> verifyCompilation + |> verifyCompilation false //SOURCE=DoNotBoxStruct_MDArray_FSInterface_NoExtMeth.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd DoNotBoxStruct_MDArray_FSInterface_NoExtMeth.exe" # DoNotBoxStruct_MDArray_FSInterface_NoExtMeth.fs - [] let ``DoNotBoxStruct_MDArray_FSInterface_NoExtMeth_fs`` compilation = compilation - |> verifyCompilation + |> verifyCompilation false //SOURCE=DoNotBoxStruct_NoArray_FSInterface_NoExtMeth.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd DoNotBoxStruct_NoArray_FSInterface_NoExtMeth.exe" # DoNotBoxStruct_NoArray_FSInterface_NoExtMeth.fs - [] let ``DoNotBoxStruct_NoArray_FSInterface_NoExtMeth_fs`` compilation = compilation - |> verifyCompilation + |> verifyCompilation false //SOURCE=DoNotBoxStruct_ArrayOfArray_CSInterface.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd DoNotBoxStruct_ArrayOfArray_CSInterface.exe" # DoNotBoxStruct_ArrayOfArray_CSInterface.fs [] let ``DoNotBoxStruct_ArrayOfArray_CSInterface_fs`` compilation = compilation - |> verifyCompilation + |> verifyCompilation false //SOURCE=DoNotBoxStruct_ArrayOfArray_CSInterface.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd DoNotBoxStruct_ArrayOfArray_CSInterface.exe" # DoNotBoxStruct_ArrayOfArray_CSInterface.fs [] let ``DoNotBoxStruct_ArrayOfArray_FSInterface_fs`` compilation = compilation - |> verifyCompilation + |> verifyCompilation false //SOURCE=DoNotBoxStruct_Array_CSInterface.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd DoNotBoxStruct_Array_CSInterface.exe" # DoNotBoxStruct_Array_CSInterface.fs [] let ``DoNotBoxStruct_Array_CSInterface_fs`` compilation = compilation - |> verifyCompilation + |> verifyCompilation false //SOURCE=DoNotBoxStruct_Array_FSInterface.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd DoNotBoxStruct_Array_FSInterface.exe" # DoNotBoxStruct_Array_FSInterface.fs - [] let ``DoNotBoxStruct_Array_FSInterface_fs`` compilation = compilation - |> verifyCompilation + |> verifyCompilation false //SOURCE=DoNotBoxStruct_MDArray_CSInterface.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd DoNotBoxStruct_MDArray_CSInterface.exe" # DoNotBoxStruct_MDArray_CSInterface.fs - [] let ``DoNotBoxStruct_MDArray_CSInterface_fs`` compilation = compilation - |> verifyCompilation + |> verifyCompilation false //SOURCE=DoNotBoxStruct_MDArray_FSInterface.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd DoNotBoxStruct_MDArray_FSInterface.exe" # DoNotBoxStruct_MDArray_FSInterface.fs - [] let ``DoNotBoxStruct_MDArray_FSInterface_fs`` compilation = compilation - |> verifyCompilation + |> verifyCompilation false //SOURCE=DoNotBoxStruct_NoArray_CSInterface.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd DoNotBoxStruct_NoArray_CSInterface.exe" # DoNotBoxStruct_NoArray_CSInterface.fs [] let ``DoNotBoxStruct_NoArray_CSInterface_fs`` compilation = compilation - |> verifyCompilation + |> verifyCompilation false //SOURCE=DoNotBoxStruct_NoArray_FSInterface.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd DoNotBoxStruct_NoArray_FSInterface.exe" # DoNotBoxStruct_NoArray_FSInterface.fs - [] let ``DoNotBoxStruct_NoArray_FSInterface_fs`` compilation = compilation - |> verifyCompilation + |> verifyCompilation false //SOURCE=DoNotBoxStruct_ToString.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd DoNotBoxStruct_ToString.exe" # DoNotBoxStruct_ToString.fs [] let ``DoNotBoxStruct_ToString_fs`` compilation = compilation - |> verifyCompilation + |> verifyCompilation false diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/RealInternalSignature/ClassTypeInitialization.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/RealInternalSignature/ClassTypeInitialization.fs index fe209b3e50e..fd9eb1848d4 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/RealInternalSignature/ClassTypeInitialization.fs +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/RealInternalSignature/ClassTypeInitialization.fs @@ -5,6 +5,7 @@ namespace EmittedIL.RealInternalSignature open Xunit open FSharp.Test open FSharp.Test.Compiler +open System.IO module ClassTypeInitialization = @@ -484,364 +485,322 @@ printfn "%A" (MyClass.result()) ] - [] // RealSig - [] // Regular + [] // RealSig Optimize + [] // RealSig NoOptimize + [] // Regular Optimize + [] // Regular NoOptimize [] - let ``nested generic closure`` (realSig) = + let ``nested generic closure`` (realSig, optimize) = + let path = __SOURCE_DIRECTORY__ ++ "nested_generic_closure.fs" + let source = File.ReadAllText (path) + + FSharp source + |> asExe + |> withRealInternalSignature realSig + |> withOptimization optimize + |> compileAndRun + |> shouldSucceed + + [] // RealSig Optimize + [] // RealSig NoOptimize + [] // Regular Optimize + [] // Regular NoOptimize + [] + let ``Generic class with closure with constraints`` (realSig, optimize) = FSharp """ -// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. +namespace Test +open System -namespace MyCollections +module RuntimeHelpers = + [] + type MyType<'A,'B when 'B :> seq<'A>>(sources: seq<'B>) = + + member x.MoveNext() = + let rec takeInner c = + let rec takeOuter b = + if b.ToString () = "1" then failwith "Oops" + if sources |> Seq.length > 10 then + sources |> Seq.skip 10 + else + sources + if c.ToString() = "1" then failwith "Oops" + if sources |> Seq.length < 5 then + sources + else + takeOuter 7 + takeInner 3 + +open RuntimeHelpers +module doIt = + let x = seq { ArraySegment([|1uy; 2uy; 3uy|]); ArraySegment([|1uy; 2uy; 3uy|]); ArraySegment([|1uy; 2uy; 3uy|]); } + let enumerator = x |> MyType<_,_> + for i in enumerator.MoveNext() do + printfn "%A" i + """ + |> asExe + |> withRealInternalSignature realSig + |> withOptimization optimize + |> compileAndRun + |> shouldSucceed -#nowarn "52" // The value has been copied to ensure the original is not mutated by this operation + [] // RealSig Optimize + [] // RealSig NoOptimize + [] // Regular Optimize + [] // Regular NoOptimize + [] + let ``AgedLookup`` (realSig, optimize) = -open System.Diagnostics -open System.Collections -open System.Collections.Generic -open Microsoft.FSharp.Core + FSharp """ +namespace Internal.Utilities.Collections -module internal IEnumerator = +open System + +[] +type internal ValueStrength<'T when 'T: not struct> = + | Strong of 'T + | Weak of WeakReference<'T> + +type internal AgedLookup<'Token, 'Key, 'Value when 'Value: not struct>(keepStrongly: int, areSimilar, ?requiredToKeep, ?keepMax: int) = + /// The list of items stored. Youngest is at the end of the list. + /// The choice of order is somewhat arbitrary. If the other way then adding + /// items would be O(1) and removing O(N). + let mutable refs: ('Key * ValueStrength<'Value>) list = [] + + let mutable keepStrongly = keepStrongly + + // The 75 here determines how long the list should be passed the end of strongly held + // references. Some operations are O(N) and we don't want to let things get out of + // hand. + let keepMax = defaultArg keepMax 75 + let mutable keepMax = max keepStrongly keepMax + let requiredToKeep = defaultArg requiredToKeep (fun _ -> false) + + /// Look up the given key, return None if not found. + let TryPeekKeyValueImpl (data, key) = + let rec Lookup key = + function + // Treat a list of key-value pairs as a lookup collection. + // This function returns true if two keys are the same according to the predicate + // function passed in. + | [] -> None + | (similarKey, value) :: t -> + if areSimilar (key, similarKey) then + Some(similarKey, value) + else + Lookup key t + + Lookup key data + + /// Determines whether a particular key exists. + let Exists (data, key) = TryPeekKeyValueImpl(data, key).IsSome + + /// Set a particular key's value. + let Add (data, key, value) = data @ [ key, value ] + + /// Promote a particular key value. + let Promote (data, key, value) = + (data |> List.filter (fun (similarKey, _) -> not (areSimilar (key, similarKey)))) + @ [ (key, value) ] + + /// Remove a particular key value. + let RemoveImpl (data, key) = + let keep = + data |> List.filter (fun (similarKey, _) -> not (areSimilar (key, similarKey))) + + keep + + let TryGetKeyValueImpl (data, key) = + match TryPeekKeyValueImpl(data, key) with + | Some(similarKey, value) as result -> + // If the result existed, move it to the end of the list (more likely to keep it) + result, Promote(data, similarKey, value) + | None -> None, data + + /// Remove weak entries from the list that have been collected. + let FilterAndHold (tok: 'Token) = + ignore tok // reading 'refs' requires a token + + [ + for key, value in refs do + match value with + | Strong(value) -> yield (key, value) + | Weak(weakReference) -> + match weakReference.TryGetTarget() with + | false, _ -> () + | true, value -> yield key, value + ] - let noReset() = raise (new System.NotSupportedException("SR.GetString(SR.resetNotSupported)")) - let notStarted() = raise (new System.InvalidOperationException("SR.GetString(SR.enumerationNotStarted)")) - let alreadyFinished() = raise (new System.InvalidOperationException("SR.GetString(SR.enumerationAlreadyFinished)")) - let check started = if not started then notStarted() - let dispose (r : System.IDisposable) = r.Dispose() + let AssignWithStrength (tok, newData) = + let actualLength = List.length newData + let tossThreshold = max 0 (actualLength - keepMax) // Delete everything less than this threshold + let weakThreshold = max 0 (actualLength - keepStrongly) // Weaken everything less than this threshold + + let newData = newData |> List.mapi (fun n kv -> n, kv) // Place the index. + + let newData = + newData + |> List.filter (fun (n: int, v) -> n >= tossThreshold || requiredToKeep (snd v)) + + let newData = + newData + |> List.map (fun (n: int, (k, v)) -> + let handle = + if n < weakThreshold && not (requiredToKeep v) then + Weak(WeakReference<_>(v)) + else + Strong(v) + + k, handle) + + ignore tok // Updating refs requires tok + refs <- newData + + member al.TryPeekKeyValue(tok, key) = + // Returns the original key value as well since it may be different depending on equality test. + let data = FilterAndHold(tok) + TryPeekKeyValueImpl(data, key) + + member al.TryGetKeyValue(tok, key) = + let data = FilterAndHold(tok) + let result, newData = TryGetKeyValueImpl(data, key) + AssignWithStrength(tok, newData) + result + + member al.TryGet(tok, key) = + let data = FilterAndHold(tok) + let result, newData = TryGetKeyValueImpl(data, key) + AssignWithStrength(tok, newData) + + match result with + | Some(_, value) -> Some(value) + | None -> None + + member al.Put(tok, key, value) = + let data = FilterAndHold(tok) + + let data = if Exists(data, key) then RemoveImpl(data, key) else data + + let data = Add(data, key, value) + AssignWithStrength(tok, data) // This will remove extras + + member al.Remove(tok, key) = + let data = FilterAndHold(tok) + let newData = RemoveImpl(data, key) + AssignWithStrength(tok, newData) + + member al.Clear(tok) = + let _discards = FilterAndHold(tok) + AssignWithStrength(tok, []) + + member al.Resize(tok, newKeepStrongly, ?newKeepMax) = + let newKeepMax = defaultArg newKeepMax 75 + keepStrongly <- newKeepStrongly + keepMax <- max newKeepStrongly newKeepMax + let keep = FilterAndHold(tok) + AssignWithStrength(tok, keep) + """ + |> asLibrary + |> withRealInternalSignature realSig + |> withOptimization optimize + |> compile + |> shouldSucceed - let cast (e : IEnumerator) : IEnumerator<'T> = - { new IEnumerator<'T> with - member _.Current = unbox<'T> e.Current + [] // RealSig Optimize + [] // RealSig NoOptimize + [] // Regular Optimize + [] // Regular NoOptimize + [] + let ``BigTuples`` (realSig, optimize) = - interface IEnumerator with - member _.Current = unbox<'T> e.Current :> obj + FSharp """ +namespace Equality - [] - member _.MoveNext() = e.MoveNext() +type BigGenericTuple<'a> = BigGenericTuple of int * 'a * byte * int * 'a * byte + """ + |> asLibrary + |> withRealInternalSignature realSig + |> withOptimization optimize + |> compile + |> shouldSucceed - member _.Reset() = noReset() + [] // RealSig Optimize + [] // RealSig NoOptimize + [] // Regular Optimize + [] // Regular NoOptimize + [] + let ``Array groupBy id`` (realSig, optimize) = - interface System.IDisposable with - member _.Dispose() = - match e with - | :? System.IDisposable as e -> e.Dispose() - | _ -> () } + FSharp """ +module GroupByTest +let ``for _ in Array groupBy id [||] do ...`` () = [|for _ in Array.groupBy id [||] do 0|] + """ + |> asLibrary + |> withRealInternalSignature realSig + |> withOptimization optimize + |> compile + |> shouldSucceed - /// A concrete implementation of an enumerator that returns no values - [] - type EmptyEnumerator<'T>() = - let mutable started = false - interface IEnumerator<'T> with - member _.Current = - check started - (alreadyFinished() : 'T) - - interface System.Collections.IEnumerator with - member _.Current = - check started - (alreadyFinished() : obj) - - [] - member _.MoveNext() = - if not started then started <- true - false - - member _.Reset() = noReset() - - interface System.IDisposable with - member _.Dispose() = () - - let Empty<'T> () = (new EmptyEnumerator<'T>() :> IEnumerator<'T>) - - [] - type EmptyEnumerable<'T> = - - | EmptyEnumerable - - interface IEnumerable<'T> with - member _.GetEnumerator() = Empty<'T>() - - interface IEnumerable with - member _.GetEnumerator() = (Empty<'T>() :> IEnumerator) - - type GeneratedEnumerable<'T, 'State>(openf: unit -> 'State, compute: 'State -> 'T option, closef: 'State -> unit) = - let mutable started = false - let mutable curr = None - let state = ref (Some (openf ())) - let getCurr() : 'T = - check started - match curr with - | None -> alreadyFinished() - | Some x -> x - - let readAndClear () = - lock state (fun () -> - match state.Value with - | None -> None - | Some _ as res -> - state.Value <- None - res) - - let start() = - if not started then - started <- true - - let dispose() = - readAndClear() |> Option.iter closef - - let finish() = - try dispose() - finally curr <- None - - interface IEnumerator<'T> with - member _.Current = getCurr() - - interface IEnumerator with - member _.Current = box (getCurr()) - - [] - member _.MoveNext() = - start() - match state.Value with - | None -> false // we started, then reached the end, then got another MoveNext - | Some s -> - match (try compute s with e -> finish(); reraise()) with - | None -> finish(); false - | Some _ as x -> - curr <- x - true - - member _.Reset() = noReset() - - interface System.IDisposable with - member _.Dispose() = dispose() - [] - type Singleton<'T>(v:'T) = - let mutable started = false + let roundTripWithInterfaceGeneration(realsig, optimize, implementationFile) = - interface IEnumerator<'T> with - member _.Current = v + let generatedSignature = + Fs implementationFile + |> withRealInternalSignature realsig + |> withOptimization optimize + |> printSignatures - interface IEnumerator with - member _.Current = box v + Fsi generatedSignature + |> asLibrary + |> withAdditionalSourceFile (FsSource implementationFile) + |> withRealInternalSignature realsig + |> withOptimization optimize + |> compile + |> shouldSucceed - [] - member _.MoveNext() = if started then false else (started <- true; true) + [] // RealSig Optimize + [] // RealSig NoOptimize + [] // Regular Optimize + [] // Regular NoOptimize + [] + let ``generic-parameter-order-roundtrip`` (realsig, optimize) = - member _.Reset() = noReset() + let implementationFile = """ +module OrderMatters - interface System.IDisposable with - member _.Dispose() = () +type IMonad<'a> = + interface + // Hash constraint leads to another type parameter + abstract bind : #IMonad<'a> -> ('a -> #IMonad<'b>) -> IMonad<'b> + end""" - let Singleton x = (new Singleton<'T>(x) :> IEnumerator<'T>) + roundTripWithInterfaceGeneration(realsig, optimize, implementationFile) - let EnumerateThenFinally f (e : IEnumerator<'T>) = - { new IEnumerator<'T> with - member _.Current = e.Current + [] // RealSig Optimize + [] // RealSig NoOptimize + [] // Regular Optimize + [] // Regular NoOptimize + [] + let ``members_basic-roundtrip`` (realsig, optimize) = - interface IEnumerator with - member _.Current = (e :> IEnumerator).Current + let implementationFile = """ +namespace GenericInterfaceTest - [] - member _.MoveNext() = e.MoveNext() + type Foo<'a> = + interface + abstract fun1 : 'a -> 'a + abstract fun2 : int -> int + end - member _.Reset() = noReset() - interface System.IDisposable with - member _.Dispose() = - try - e.Dispose() - finally - f() - } + type Bar<'b> = + class + val store : 'b + interface Foo<'b> with + member self.fun1(x) = x + member self.fun2(x) = 1 + end + new(x) = { store = x } + end""" - let inline checkNonNull argName arg = - if isNull arg then - nullArg argName - - let mkSeq f = - { new IEnumerable<'U> with - member _.GetEnumerator() = f() - - interface IEnumerable with - member _.GetEnumerator() = (f() :> IEnumerator) } - -namespace Microsoft.FSharp.Core.CompilerServices - - open System.Diagnostics - open Microsoft.FSharp.Core - open MyCollections - open MyCollections.IEnumerator - open System.Collections - open System.Collections.Generic - - module RuntimeHelpers = - - [] - type internal StructBox<'T when 'T:equality>(value:'T) = - member x.Value = value - - static member Comparer = - let gcomparer = HashIdentity.Structural<'T> - { new IEqualityComparer> with - member _.GetHashCode(v) = gcomparer.GetHashCode(v.Value) - member _.Equals(v1,v2) = gcomparer.Equals(v1.Value,v2.Value) } - - let Generate openf compute closef = - mkSeq (fun () -> new IEnumerator.GeneratedEnumerable<_,_>(openf, compute, closef) :> IEnumerator<'T>) - - let EnumerateFromFunctions create moveNext current = - Generate - create - (fun x -> if moveNext x then Some(current x) else None) - (fun x -> match box(x) with :? System.IDisposable as id -> id.Dispose() | _ -> ()) - - // A family of enumerators that can have additional 'finally' actions added to the enumerator through - // the use of mutation. This is used to 'push' the disposal action for a 'use' into the next enumerator. - // For example, - // seq { use x = ... - // while ... } - // results in the 'while' loop giving an adjustable enumerator. This is then adjusted by adding the disposal action - // from the 'use' into the enumerator. This means that we avoid constructing a two-deep enumerator chain in this - // common case. - type IFinallyEnumerator = - abstract AppendFinallyAction : (unit -> unit) -> unit - - /// A concrete implementation of IEnumerable that adds the given compensation to the "Dispose" chain of any - /// enumerators returned by the enumerable. - [] - type FinallyEnumerable<'T>(compensation: unit -> unit, restf: unit -> seq<'T>) = - interface IEnumerable<'T> with - member _.GetEnumerator() = - try - let ie = restf().GetEnumerator() - match ie with - | :? IFinallyEnumerator as a -> - a.AppendFinallyAction(compensation) - ie - | _ -> - IEnumerator.EnumerateThenFinally compensation ie - with e -> - compensation() - reraise() - interface IEnumerable with - member x.GetEnumerator() = ((x :> IEnumerable<'T>).GetEnumerator() :> IEnumerator) - - /// An optimized object for concatenating a sequence of enumerables - [] - type ConcatEnumerator<'T,'U when 'U :> seq<'T>>(sources: seq<'U>) = - let mutable outerEnum = sources.GetEnumerator() - let mutable currInnerEnum = IEnumerator.Empty() - - let mutable started = false - let mutable finished = false - let mutable compensations = [] - - [] // false = unchecked - val mutable private currElement : 'T - - member _.Finish() = - finished <- true - try - match currInnerEnum with - | null -> () - | _ -> - try - currInnerEnum.Dispose() - finally - currInnerEnum <- null - finally - try - match outerEnum with - | null -> () - | _ -> - try - outerEnum.Dispose() - finally - outerEnum <- null - finally - let rec iter comps = - match comps with - | [] -> () - | h :: t -> - try h() finally iter t - try - compensations |> List.rev |> iter - finally - compensations <- [] - - member x.GetCurrent() = - IEnumerator.check started - if finished then IEnumerator.alreadyFinished() else x.currElement - - interface IFinallyEnumerator with - member _.AppendFinallyAction(f) = - compensations <- f :: compensations - - interface IEnumerator<'T> with - member x.Current = x.GetCurrent() - - interface IEnumerator with - member x.Current = box (x.GetCurrent()) - - [] - member x.MoveNext() = - if not started then started <- true - if finished then false - else - let rec takeInner () = - // check the inner list - if currInnerEnum.MoveNext() then - x.currElement <- currInnerEnum.Current - true - else - // check the outer list - let rec takeOuter() = - if outerEnum.MoveNext() then - let ie = outerEnum.Current - // Optimization to detect the statically-allocated empty IEnumerables - match box ie with - | :? EmptyEnumerable<'T> -> - // This one is empty, just skip, don't call GetEnumerator, try again - takeOuter() - | _ -> - // OK, this one may not be empty. - // Don't forget to dispose of the enumerator for the inner list now we're done with it - currInnerEnum.Dispose() - currInnerEnum <- ie.GetEnumerator() - takeInner () - else - // We're done - x.Finish() - false - takeOuter() - takeInner () - - member _.Reset() = IEnumerator.noReset() - - interface System.IDisposable with - - [] - member x.Dispose() = - if not finished then - x.Finish() - - module doIt = - open System - open Microsoft.FSharp.Core.CompilerServices - open Microsoft.FSharp.Collections - - let x = seq { ArraySegment([|1uy; 2uy; 3uy|]); ArraySegment([|1uy; 2uy; 3uy|]); ArraySegment([|1uy; 2uy; 3uy|]); } - let enumerator = new RuntimeHelpers.ConcatEnumerator<_,_>(x) :> IEnumerator - let rec loop () = - if enumerator.MoveNext() then - printfn $"{enumerator.Current}" - loop () - loop () -""" - |> asExe - |> withRealInternalSignature realSig - |> withOptimize - |> compileAndRun - |> shouldSucceed + roundTripWithInterfaceGeneration(realsig, optimize, implementationFile) diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/RealInternalSignature/nested_generic_closure.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/RealInternalSignature/nested_generic_closure.fs new file mode 100644 index 00000000000..4d63e54ce28 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/RealInternalSignature/nested_generic_closure.fs @@ -0,0 +1,349 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace MyCollections + +#nowarn "52" // The value has been copied to ensure the original is not mutated by this operation + +open System.Diagnostics +open System.Collections +open System.Collections.Generic +open Microsoft.FSharp.Core + +module internal IEnumerator = + + let noReset() = raise (new System.NotSupportedException("SR.GetString(SR.resetNotSupported)")) + let notStarted() = raise (new System.InvalidOperationException("SR.GetString(SR.enumerationNotStarted)")) + let alreadyFinished() = raise (new System.InvalidOperationException("SR.GetString(SR.enumerationAlreadyFinished)")) + let check started = if not started then notStarted() + let dispose (r : System.IDisposable) = r.Dispose() + + let cast (e : IEnumerator) : IEnumerator<'T> = + { new IEnumerator<'T> with + member _.Current = unbox<'T> e.Current + + interface IEnumerator with + member _.Current = unbox<'T> e.Current :> obj + + [] + member _.MoveNext() = e.MoveNext() + + member _.Reset() = noReset() + + interface System.IDisposable with + member _.Dispose() = + match e with + | :? System.IDisposable as e -> e.Dispose() + | _ -> () } + + /// A concrete implementation of an enumerator that returns no values + [] + type EmptyEnumerator<'T>() = + let mutable started = false + interface IEnumerator<'T> with + member _.Current = + check started + (alreadyFinished() : 'T) + + interface System.Collections.IEnumerator with + member _.Current = + check started + (alreadyFinished() : obj) + + [] + member _.MoveNext() = + if not started then started <- true + false + + member _.Reset() = noReset() + + interface System.IDisposable with + member _.Dispose() = () + + let Empty<'T> () = (new EmptyEnumerator<'T>() :> IEnumerator<'T>) + + [] + type EmptyEnumerable<'T> = + + | EmptyEnumerable + + interface IEnumerable<'T> with + member _.GetEnumerator() = Empty<'T>() + + interface IEnumerable with + member _.GetEnumerator() = (Empty<'T>() :> IEnumerator) + + type GeneratedEnumerable<'T, 'State>(openf: unit -> 'State, compute: 'State -> 'T option, closef: 'State -> unit) = + let mutable started = false + let mutable curr = None + let state = ref (Some (openf ())) + let getCurr() : 'T = + check started + match curr with + | None -> alreadyFinished() + | Some x -> x + + let readAndClear () = + lock state (fun () -> + match state.Value with + | None -> None + | Some _ as res -> + state.Value <- None + res) + + let start() = + if not started then + started <- true + + let dispose() = + readAndClear() |> Option.iter closef + + let finish() = + try dispose() + finally curr <- None + + interface IEnumerator<'T> with + member _.Current = getCurr() + + interface IEnumerator with + member _.Current = box (getCurr()) + + [] + member _.MoveNext() = + start() + match state.Value with + | None -> false // we started, then reached the end, then got another MoveNext + | Some s -> + match (try compute s with e -> finish(); reraise()) with + | None -> finish(); false + | Some _ as x -> + curr <- x + true + + member _.Reset() = noReset() + + interface System.IDisposable with + member _.Dispose() = dispose() + + [] + type Singleton<'T>(v:'T) = + let mutable started = false + + interface IEnumerator<'T> with + member _.Current = v + + interface IEnumerator with + member _.Current = box v + + [] + member _.MoveNext() = if started then false else (started <- true; true) + + member _.Reset() = noReset() + + interface System.IDisposable with + member _.Dispose() = () + + let Singleton x = (new Singleton<'T>(x) :> IEnumerator<'T>) + + let EnumerateThenFinally f (e : IEnumerator<'T>) = + { new IEnumerator<'T> with + member _.Current = e.Current + + interface IEnumerator with + member _.Current = (e :> IEnumerator).Current + + [] + member _.MoveNext() = e.MoveNext() + + member _.Reset() = noReset() + + interface System.IDisposable with + member _.Dispose() = + try + e.Dispose() + finally + f() + } + + let inline checkNonNull argName arg = + if isNull arg then + nullArg argName + + let mkSeq f = + { new IEnumerable<'U> with + member _.GetEnumerator() = f() + + interface IEnumerable with + member _.GetEnumerator() = (f() :> IEnumerator) } + +namespace Microsoft.FSharp.Core.CompilerServices + + open System.Diagnostics + open Microsoft.FSharp.Core + open MyCollections + open MyCollections.IEnumerator + open System.Collections + open System.Collections.Generic + + module RuntimeHelpers = + + [] + type internal StructBox<'T when 'T:equality>(value:'T) = + member x.Value = value + + static member Comparer = + let gcomparer = HashIdentity.Structural<'T> + { new IEqualityComparer> with + member _.GetHashCode(v) = gcomparer.GetHashCode(v.Value) + member _.Equals(v1,v2) = gcomparer.Equals(v1.Value,v2.Value) } + + let Generate openf compute closef = + mkSeq (fun () -> new IEnumerator.GeneratedEnumerable<_,_>(openf, compute, closef) :> IEnumerator<'T>) + + let EnumerateFromFunctions create moveNext current = + Generate + create + (fun x -> if moveNext x then Some(current x) else None) + (fun x -> match box(x) with :? System.IDisposable as id -> id.Dispose() | _ -> ()) + + // A family of enumerators that can have additional 'finally' actions added to the enumerator through + // the use of mutation. This is used to 'push' the disposal action for a 'use' into the next enumerator. + // For example, + // seq { use x = ... + // while ... } + // results in the 'while' loop giving an adjustable enumerator. This is then adjusted by adding the disposal action + // from the 'use' into the enumerator. This means that we avoid constructing a two-deep enumerator chain in this + // common case. + type IFinallyEnumerator = + abstract AppendFinallyAction : (unit -> unit) -> unit + + /// A concrete implementation of IEnumerable that adds the given compensation to the "Dispose" chain of any + /// enumerators returned by the enumerable. + [] + type FinallyEnumerable<'T>(compensation: unit -> unit, restf: unit -> seq<'T>) = + interface IEnumerable<'T> with + member _.GetEnumerator() = + try + let ie = restf().GetEnumerator() + match ie with + | :? IFinallyEnumerator as a -> + a.AppendFinallyAction(compensation) + ie + | _ -> + IEnumerator.EnumerateThenFinally compensation ie + with e -> + compensation() + reraise() + interface IEnumerable with + member x.GetEnumerator() = ((x :> IEnumerable<'T>).GetEnumerator() :> IEnumerator) + + /// An optimized object for concatenating a sequence of enumerables + [] + type ConcatEnumerator<'T,'U when 'U :> seq<'T>>(sources: seq<'U>) = + let mutable outerEnum = sources.GetEnumerator() + let mutable currInnerEnum = IEnumerator.Empty() + + let mutable started = false + let mutable finished = false + let mutable compensations = [] + + [] // false = unchecked + val mutable private currElement : 'T + + member _.Finish() = + finished <- true + try + match currInnerEnum with + | null -> () + | _ -> + try + currInnerEnum.Dispose() + finally + currInnerEnum <- null + finally + try + match outerEnum with + | null -> () + | _ -> + try + outerEnum.Dispose() + finally + outerEnum <- null + finally + let rec iter comps = + match comps with + | [] -> () + | h :: t -> + try h() finally iter t + try + compensations |> List.rev |> iter + finally + compensations <- [] + + member x.GetCurrent() = + IEnumerator.check started + if finished then IEnumerator.alreadyFinished() else x.currElement + + interface IFinallyEnumerator with + member _.AppendFinallyAction(f) = + compensations <- f :: compensations + + interface IEnumerator<'T> with + member x.Current = x.GetCurrent() + + interface IEnumerator with + member x.Current = box (x.GetCurrent()) + + [] + member x.MoveNext() = + if not started then started <- true + if finished then false + else + let rec takeInner () = + // check the inner list + if currInnerEnum.MoveNext() then + x.currElement <- currInnerEnum.Current + true + else + // check the outer list + let rec takeOuter() = + if outerEnum.MoveNext() then + let ie = outerEnum.Current + // Optimization to detect the statically-allocated empty IEnumerables + match box ie with + | :? EmptyEnumerable<'T> -> + // This one is empty, just skip, don't call GetEnumerator, try again + takeOuter() + | _ -> + // OK, this one may not be empty. + // Don't forget to dispose of the enumerator for the inner list now we're done with it + currInnerEnum.Dispose() + currInnerEnum <- ie.GetEnumerator() + takeInner () + else + // We're done + x.Finish() + false + takeOuter() + takeInner () + + member _.Reset() = IEnumerator.noReset() + + interface System.IDisposable with + + [] + member x.Dispose() = + if not finished then + x.Finish() + + module doIt = + open System + open Microsoft.FSharp.Core.CompilerServices + open Microsoft.FSharp.Collections + + let x = seq { ArraySegment([|1uy; 2uy; 3uy|]); ArraySegment([|1uy; 2uy; 3uy|]); ArraySegment([|1uy; 2uy; 3uy|]); } + let enumerator = new RuntimeHelpers.ConcatEnumerator<_,_>(x) :> IEnumerator + let rec loop () = + if enumerator.MoveNext() then + printfn $"{enumerator.Current}" + loop () + loop () diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/TestFunctions/TestFunction23.fs.il.net472.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/TestFunctions/TestFunction23.fs.il.net472.bsl index 3f4c324d6dd..879f6b4e90f 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/TestFunctions/TestFunction23.fs.il.net472.bsl +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/TestFunctions/TestFunction23.fs.il.net472.bsl @@ -16,16 +16,6 @@ .hash algorithm 0x00008004 .ver 0:0:0:0 -} -.mresource public FSharpSignatureCompressedData.assembly -{ - - -} -.mresource public FSharpOptimizationCompressedData.assembly -{ - - } .module assembly.exe @@ -49,8 +39,7 @@ .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 ) .field assembly string x .field assembly string x@8 - .method public specialname rtspecialname - instance void .ctor() cil managed + .method public specialname rtspecialname instance void .ctor() cil managed { .maxstack 8 @@ -67,8 +56,7 @@ IL_001e: ret } - .method public hidebysig instance string - M() cil managed + .method public hidebysig instance string M() cil managed { .maxstack 4 @@ -84,8 +72,7 @@ IL_0013: ret } - .method assembly hidebysig instance string - g() cil managed + .method assembly hidebysig instance string g() cil managed { .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) @@ -101,8 +88,7 @@ extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 { .field static assembly initonly class assembly/g@13 @_instance - .method assembly specialname rtspecialname - instance void .ctor() cil managed + .method assembly specialname rtspecialname instance void .ctor() cil managed { .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 ) @@ -113,8 +99,7 @@ IL_0006: ret } - .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Core.Unit - Invoke(class [FSharp.Core]Microsoft.FSharp.Core.Unit unitVar0) cil managed + .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Core.Unit Invoke(class [FSharp.Core]Microsoft.FSharp.Core.Unit unitVar0) cil managed { .maxstack 8 @@ -129,8 +114,7 @@ IL_0021: ret } - .method private specialname rtspecialname static - void .cctor() cil managed + .method private specialname rtspecialname static void .cctor() cil managed { .maxstack 10 @@ -141,8 +125,7 @@ } - .method public static class [runtime]System.Tuple`2 - f(!!a x) cil managed + .method public static class [runtime]System.Tuple`2 f(!!a x) cil managed { .maxstack 5 diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/TestFunctions/TestFunctions.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/TestFunctions/TestFunctions.fs index 9b2ce64194e..3cb6124d34e 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/TestFunctions/TestFunctions.fs +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/TestFunctions/TestFunctions.fs @@ -316,8 +316,15 @@ module TestFunctions = //SOURCE=TestFunction23.fs SCFLAGS="-g --test:EmitFeeFeeAs100001 --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd TestFunction23.exe" # TestFunction23.fs - [] - let ``TestFunction23_fs`` compilation = + let ``TestFunction23_RealInternalSignatureOff_fs`` compilation = compilation + |> withRealInternalSignatureOff + |> verifyCompilation + + [] + let ``TestFunction23_RealInternalSignatureOn_fs`` compilation = + compilation + |> withRealInternalSignatureOn |> verifyCompilation //SOURCE=TestFunction24.fs SCFLAGS="-g --optimize-" PEVER=/Exp_Fail COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd TestFunction24.exe" # TestFunction24.fs - diff --git a/tests/FSharp.Compiler.ComponentTests/Signatures/SigGenerationRoundTripTests.fs b/tests/FSharp.Compiler.ComponentTests/Signatures/SigGenerationRoundTripTests.fs index 469f9fda0e7..d70fb546637 100644 --- a/tests/FSharp.Compiler.ComponentTests/Signatures/SigGenerationRoundTripTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Signatures/SigGenerationRoundTripTests.fs @@ -6,24 +6,24 @@ open FSharp.Test.Compiler open System.IO let testCasesDir = Path.Combine(__SOURCE_DIRECTORY__,"TestCasesForGenerationRoundTrip") -let allTestCases = - Directory.EnumerateFiles(testCasesDir) - |> Seq.toArray +let allTestCases = + Directory.EnumerateFiles(testCasesDir) + |> Seq.toArray |> Array.map Path.GetFileName |> Array.map (fun f -> [|f :> obj|]) [] [] -let ``Generate and compile`` implFileName = +let ``Generate and compile`` implFileName = let implContents = File.ReadAllText (Path.Combine(testCasesDir,implFileName)) - let generatedSignature = - Fs implContents + let generatedSignature = + Fs implContents |> withLangVersion80 |> withDefines ["TESTS_AS_APP";"COMPILED"] - |> printSignatures + |> printSignatures - Fsi generatedSignature + Fsi generatedSignature |> withAdditionalSourceFile (FsSource implContents) |> withLangVersion80 |> withDefines ["TESTS_AS_APP";"COMPILED"] diff --git a/tests/FSharp.Compiler.ComponentTests/resources/tests/Conformance/LexicalAnalysis/SymbolicOperators/E_LessThanDotOpenParen001.fs b/tests/FSharp.Compiler.ComponentTests/resources/tests/Conformance/LexicalAnalysis/SymbolicOperators/E_LessThanDotOpenParen001.fs deleted file mode 100644 index a8cf50ea24b..00000000000 --- a/tests/FSharp.Compiler.ComponentTests/resources/tests/Conformance/LexicalAnalysis/SymbolicOperators/E_LessThanDotOpenParen001.fs +++ /dev/null @@ -1,31 +0,0 @@ -// #Regression #Conformance #LexicalAnalysis #Operators -// Regression test for FSHARP1.0:4805 -// We are not really after the actual error messages here (some of them have been omitted), rather we -// want to verify we do not crash! -//This construct causes code to be less generic than indicated by the type annotations\. The type variable 'S has been constrained to be type 'int' -//This code is not sufficiently generic\. The type variable \^T when \^T : \(static member \( \+ \) : \^T \* \^T -> \^a\) could not be generalized because it would escape its scope - -type public TestType<'T,'S>() = - - member public s.Value with get() = Unchecked.defaultof<'T> - static member public (+++) (a : TestType<'T,'S>, b : TestType<'T,'S>) = a.Value - static member public (+++) (a : TestType<'T,'S>, b : 'T) = b - static member public (+++) (a : 'T, b : TestType<'T,'S>) = a - static member public (+++) (a : TestType<'T,'S>, b : 'T -> 'S) = a.Value - static member public (+++) (a : 'S -> 'T, b : TestType<'T,'S>) = (a 17) + b.Value - -let inline (+++) (a : ^a) (b : ^b) = ((^a or ^b): (static member (+++): ^a * ^b -> ^c) (a,b) ) - -let tt0 = TestType() -let tt1 = TestType() - -let f (x : string) = 18 - -let a0 = tt0 +++ tt1 -let a1 = tt0 +++ 11 -let a2 = 12 +++ tt1 -let a3 = tt0 +++ (fun x -> "18") -let a4 = f +++ tt0 - -let a5 = TestType.(+++)(f, tt0) -let a6 = TestType.(+++)((fun (x : string) -> 18), tt0) diff --git a/tests/FSharp.Test.Utilities/Compiler.fs b/tests/FSharp.Test.Utilities/Compiler.fs index cd409116c3c..ebd0bf52648 100644 --- a/tests/FSharp.Test.Utilities/Compiler.fs +++ b/tests/FSharp.Test.Utilities/Compiler.fs @@ -537,6 +537,10 @@ module rec Compiler = let withOptimize (cUnit: CompilationUnit) : CompilationUnit = withOptionsHelper [ "--optimize+" ] "withOptimize is only supported for F#" cUnit + let withOptimization (optimization: bool) (cUnit: CompilationUnit) : CompilationUnit = + let option = if optimization then "--optimize+" else "--optimize-" + withOptionsHelper [ option ] "withOptimization is only supported for F#" cUnit + let withFullPdb(cUnit: CompilationUnit) : CompilationUnit = withOptionsHelper [ "--debug:full" ] "withFullPdb is only supported for F#" cUnit diff --git a/tests/FSharp.Test.Utilities/XunitHelpers.fs b/tests/FSharp.Test.Utilities/XunitHelpers.fs index cda74f7867c..c98ee088fe7 100644 --- a/tests/FSharp.Test.Utilities/XunitHelpers.fs +++ b/tests/FSharp.Test.Utilities/XunitHelpers.fs @@ -18,6 +18,8 @@ type FSharpXunitFramework(sink: IMessageSink) = interface IDisposable with member _.Dispose() = - cleanUpTemporaryDirectoryOfThisTestRun () - base.Dispose() + match Environment.GetEnvironmentVariable("FSHARP_RETAIN_TESTBUILDS") with + | null -> cleanUpTemporaryDirectoryOfThisTestRun () + | _ -> () + base.Dispose() diff --git a/tests/ILVerify/ilverify_FSharp.Compiler.Service_Release_net9.0.bsl b/tests/ILVerify/ilverify_FSharp.Compiler.Service_Release_net9.0.bsl index 20f8131d238..9bae481e0e9 100644 --- a/tests/ILVerify/ilverify_FSharp.Compiler.Service_Release_net9.0.bsl +++ b/tests/ILVerify/ilverify_FSharp.Compiler.Service_Release_net9.0.bsl @@ -43,8 +43,8 @@ [IL]: Error [StackUnexpected]: : FSharp.Compiler.ParseAndCheckInputs+CheckMultipleInputsUsingGraphMode@1865::Invoke(int32)][offset 0x0000003A][found Char] Unexpected type on the stack. [IL]: Error [StackUnexpected]: : FSharp.Compiler.CompilerConfig+TcConfig::.ctor([FSharp.Compiler.Service]FSharp.Compiler.CompilerConfig+TcConfigBuilder, bool)][offset 0x0000059C][found Char] Unexpected type on the stack. [IL]: Error [StackUnexpected]: : FSharp.Compiler.CompilerConfig+TcConfig::.ctor([FSharp.Compiler.Service]FSharp.Compiler.CompilerConfig+TcConfigBuilder, bool)][offset 0x000005A5][found Char] Unexpected type on the stack. -[IL]: Error [StackUnexpected]: : FSharp.Compiler.IlxGen::HashRangeSorted([S.P.CoreLib]System.Collections.Generic.IDictionary`2>)][offset 0x00000011][found ref '[FSharp.Compiler.Service]FSharp.Compiler.IlxGen+HashRangeSorted@1850-1'][expected ref '[FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,int32>'] Unexpected type on the stack. -[IL]: Error [StackUnexpected]: : FSharp.Compiler.IlxGen::HashRangeSorted([S.P.CoreLib]System.Collections.Generic.IDictionary`2>)][offset 0x00000012][found ref '[FSharp.Compiler.Service]FSharp.Compiler.IlxGen+HashRangeSorted@1850'][expected ref '[FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,T0>'] Unexpected type on the stack. +[IL]: Error [StackUnexpected]: : FSharp.Compiler.IlxGen::HashRangeSorted([S.P.CoreLib]System.Collections.Generic.IDictionary`2>)][offset 0x00000011][found ref '[FSharp.Compiler.Service]FSharp.Compiler.IlxGen+HashRangeSorted@1859-1'][expected ref '[FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,int32>'] Unexpected type on the stack. +[IL]: Error [StackUnexpected]: : FSharp.Compiler.IlxGen::HashRangeSorted([S.P.CoreLib]System.Collections.Generic.IDictionary`2>)][offset 0x00000012][found ref '[FSharp.Compiler.Service]FSharp.Compiler.IlxGen+HashRangeSorted@1859'][expected ref '[FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,T0>'] Unexpected type on the stack. [IL]: Error [StackUnexpected]: : FSharp.Compiler.PatternMatchCompilation::isProblematicClause([FSharp.Compiler.Service]FSharp.Compiler.PatternMatchCompilation+MatchClause)][offset 0x00000040][found Byte] Unexpected type on the stack. [IL]: Error [StackUnexpected]: : .$FSharp.Compiler.PatternMatchCompilation::.cctor()][offset 0x0000000B][found Boolean] Unexpected type on the stack. [IL]: Error [StackUnexpected]: : FSharp.Compiler.TypeProviders::ValidateExpectedName([FSharp.Compiler.Service]FSharp.Compiler.Text.Range, string[], string, [FSharp.Compiler.Service]FSharp.Compiler.Tainted`1)][offset 0x000000A8][found Char] Unexpected type on the stack. diff --git a/tests/ILVerify/ilverify_FSharp.Compiler.Service_Release_netstandard2.0.bsl b/tests/ILVerify/ilverify_FSharp.Compiler.Service_Release_netstandard2.0.bsl index c5ce02a7c08..34f289b7fe3 100644 --- a/tests/ILVerify/ilverify_FSharp.Compiler.Service_Release_netstandard2.0.bsl +++ b/tests/ILVerify/ilverify_FSharp.Compiler.Service_Release_netstandard2.0.bsl @@ -61,8 +61,8 @@ [IL]: Error [StackUnexpected]: : FSharp.Compiler.CompilerImports+TcConfig-TryResolveLibWithDirectories@558-1::Invoke([FSharp.Core]Microsoft.FSharp.Core.Unit)][offset 0x0000003B][found Char] Unexpected type on the stack. [IL]: Error [StackUnexpected]: : FSharp.Compiler.CompilerConfig+TcConfig::.ctor([FSharp.Compiler.Service]FSharp.Compiler.CompilerConfig+TcConfigBuilder, bool)][offset 0x0000059C][found Char] Unexpected type on the stack. [IL]: Error [StackUnexpected]: : FSharp.Compiler.CompilerConfig+TcConfig::.ctor([FSharp.Compiler.Service]FSharp.Compiler.CompilerConfig+TcConfigBuilder, bool)][offset 0x000005A5][found Char] Unexpected type on the stack. -[IL]: Error [StackUnexpected]: : FSharp.Compiler.IlxGen::HashRangeSorted([S.P.CoreLib]System.Collections.Generic.IDictionary`2>)][offset 0x00000011][found ref '[FSharp.Compiler.Service]FSharp.Compiler.IlxGen+HashRangeSorted@1850-1'][expected ref '[FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,int32>'] Unexpected type on the stack. -[IL]: Error [StackUnexpected]: : FSharp.Compiler.IlxGen::HashRangeSorted([S.P.CoreLib]System.Collections.Generic.IDictionary`2>)][offset 0x00000012][found ref '[FSharp.Compiler.Service]FSharp.Compiler.IlxGen+HashRangeSorted@1850'][expected ref '[FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,T0>'] Unexpected type on the stack. +[IL]: Error [StackUnexpected]: : FSharp.Compiler.IlxGen::HashRangeSorted([S.P.CoreLib]System.Collections.Generic.IDictionary`2>)][offset 0x00000011][found ref '[FSharp.Compiler.Service]FSharp.Compiler.IlxGen+HashRangeSorted@1859-1'][expected ref '[FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,int32>'] Unexpected type on the stack. +[IL]: Error [StackUnexpected]: : FSharp.Compiler.IlxGen::HashRangeSorted([S.P.CoreLib]System.Collections.Generic.IDictionary`2>)][offset 0x00000012][found ref '[FSharp.Compiler.Service]FSharp.Compiler.IlxGen+HashRangeSorted@1859'][expected ref '[FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,T0>'] Unexpected type on the stack. [IL]: Error [StackUnexpected]: : FSharp.Compiler.PatternMatchCompilation::isProblematicClause([FSharp.Compiler.Service]FSharp.Compiler.PatternMatchCompilation+MatchClause)][offset 0x00000040][found Byte] Unexpected type on the stack. [IL]: Error [StackUnexpected]: : .$FSharp.Compiler.PatternMatchCompilation::.cctor()][offset 0x0000000B][found Boolean] Unexpected type on the stack. [IL]: Error [StackUnexpected]: : FSharp.Compiler.NicePrint+TastDefinitionPrinting+meths@2092-3::Invoke([FSharp.Compiler.Service]FSharp.Compiler.Infos+MethInfo)][offset 0x000000B3][found Char] Unexpected type on the stack. diff --git a/tests/fsharp/Compiler/CodeGen/EmittedIL/TaskGeneratedCode.fs b/tests/fsharp/Compiler/CodeGen/EmittedIL/TaskGeneratedCode.fs index 7fe5a0db4b4..d4f5c692e05 100644 --- a/tests/fsharp/Compiler/CodeGen/EmittedIL/TaskGeneratedCode.fs +++ b/tests/fsharp/Compiler/CodeGen/EmittedIL/TaskGeneratedCode.fs @@ -1104,7 +1104,7 @@ type Generic1InGeneric1<'T>() = 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 ) - .class auto autochar sealed nested assembly beforefieldinit specialname clo@7 + .class auto autochar sealed nested assembly beforefieldinit specialname clo@7 extends [runtime]System.ValueType implements [runtime]System.Runtime.CompilerServices.IAsyncStateMachine, class [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.IResumableStateMachine`1> @@ -1132,7 +1132,7 @@ type Generic1InGeneric1<'T>() = class [runtime]System.Exception V_9, class [runtime]System.Exception V_10) IL_0000: ldarg.0 - IL_0001: ldfld int32 valuetype Test/Generic1InGeneric1`1/clo@7::ResumptionPoint + IL_0001: ldfld int32 valuetype Test/Generic1InGeneric1`1/clo@7::ResumptionPoint IL_0006: stloc.0 IL_0007: ldloc.0 IL_0008: ldc.i4.1 @@ -1161,16 +1161,16 @@ type Generic1InGeneric1<'T>() = IL_002c: nop IL_002d: ldarg.0 - IL_002e: ldfld class [runtime]System.Threading.Tasks.Task`1 valuetype Test/Generic1InGeneric1`1/clo@7::computation + IL_002e: ldfld class [runtime]System.Threading.Tasks.Task`1 valuetype Test/Generic1InGeneric1`1/clo@7::computation IL_0033: stloc.3 IL_0034: ldarg.0 IL_0035: ldloc.3 IL_0036: callvirt instance valuetype [netstandard]System.Runtime.CompilerServices.TaskAwaiter`1 class [netstandard]System.Threading.Tasks.Task`1::GetAwaiter() - IL_003b: stfld valuetype [runtime]System.Runtime.CompilerServices.TaskAwaiter`1 valuetype Test/Generic1InGeneric1`1/clo@7::awaiter + IL_003b: stfld valuetype [runtime]System.Runtime.CompilerServices.TaskAwaiter`1 valuetype Test/Generic1InGeneric1`1/clo@7::awaiter IL_0040: ldc.i4.1 IL_0041: stloc.s V_4 IL_0043: ldarg.0 - IL_0044: ldflda valuetype [runtime]System.Runtime.CompilerServices.TaskAwaiter`1 valuetype Test/Generic1InGeneric1`1/clo@7::awaiter + IL_0044: ldflda valuetype [runtime]System.Runtime.CompilerServices.TaskAwaiter`1 valuetype Test/Generic1InGeneric1`1/clo@7::awaiter IL_0049: call instance bool valuetype [netstandard]System.Runtime.CompilerServices.TaskAwaiter`1::get_IsCompleted() IL_004e: brfalse.s IL_0052 @@ -1185,7 +1185,7 @@ type Generic1InGeneric1<'T>() = IL_0059: ldarg.0 IL_005a: ldc.i4.1 - IL_005b: stfld int32 valuetype Test/Generic1InGeneric1`1/clo@7::ResumptionPoint + IL_005b: stfld int32 valuetype Test/Generic1InGeneric1`1/clo@7::ResumptionPoint IL_0060: ldc.i4.0 IL_0061: nop IL_0062: stloc.s V_5 @@ -1199,13 +1199,13 @@ type Generic1InGeneric1<'T>() = IL_006e: brfalse.s IL_0092 IL_0070: ldarg.0 - IL_0071: ldflda valuetype [runtime]System.Runtime.CompilerServices.TaskAwaiter`1 valuetype Test/Generic1InGeneric1`1/clo@7::awaiter + IL_0071: ldflda valuetype [runtime]System.Runtime.CompilerServices.TaskAwaiter`1 valuetype Test/Generic1InGeneric1`1/clo@7::awaiter IL_0076: call instance !0 valuetype [netstandard]System.Runtime.CompilerServices.TaskAwaiter`1::GetResult() IL_007b: stloc.s V_6 IL_007d: ldloc.s V_6 IL_007f: stloc.s V_7 IL_0081: ldarg.0 - IL_0082: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 valuetype Test/Generic1InGeneric1`1/clo@7::Data + IL_0082: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 valuetype Test/Generic1InGeneric1`1/clo@7::Data IL_0087: ldloc.s V_7 IL_0089: stfld !0 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::Result IL_008e: ldc.i4.1 @@ -1213,13 +1213,13 @@ type Generic1InGeneric1<'T>() = IL_0090: br.s IL_00ab IL_0092: ldarg.0 - IL_0093: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 valuetype Test/Generic1InGeneric1`1/clo@7::Data + IL_0093: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 valuetype Test/Generic1InGeneric1`1/clo@7::Data IL_0098: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder IL_009d: ldarg.0 - IL_009e: ldflda valuetype [runtime]System.Runtime.CompilerServices.TaskAwaiter`1 valuetype Test/Generic1InGeneric1`1/clo@7::awaiter + IL_009e: ldflda valuetype [runtime]System.Runtime.CompilerServices.TaskAwaiter`1 valuetype Test/Generic1InGeneric1`1/clo@7::awaiter IL_00a3: ldarg.0 - IL_00a4: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::AwaitUnsafeOnCompleted,valuetype Test/Generic1InGeneric1`1/clo@7>(!!0&, - !!1&) + IL_00a4: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::AwaitUnsafeOnCompleted,valuetype Test/Generic1InGeneric1`1/clo@7>(!!0&, + !!1&) IL_00a9: ldc.i4.0 IL_00aa: nop IL_00ab: brfalse.s IL_00c1 @@ -1228,7 +1228,7 @@ type Generic1InGeneric1<'T>() = IL_00ae: ldloca.s V_8 IL_00b0: initobj valuetype [runtime]System.Runtime.CompilerServices.TaskAwaiter`1 IL_00b6: ldloc.s V_8 - IL_00b8: stfld valuetype [runtime]System.Runtime.CompilerServices.TaskAwaiter`1 valuetype Test/Generic1InGeneric1`1/clo@7::awaiter + IL_00b8: stfld valuetype [runtime]System.Runtime.CompilerServices.TaskAwaiter`1 valuetype Test/Generic1InGeneric1`1/clo@7::awaiter IL_00bd: ldc.i4.1 IL_00be: nop IL_00bf: br.s IL_00c3 @@ -1240,10 +1240,10 @@ type Generic1InGeneric1<'T>() = IL_00c5: brfalse.s IL_00e4 IL_00c7: ldarg.0 - IL_00c8: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 valuetype Test/Generic1InGeneric1`1/clo@7::Data + IL_00c8: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 valuetype Test/Generic1InGeneric1`1/clo@7::Data IL_00cd: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder IL_00d2: ldarg.0 - IL_00d3: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 valuetype Test/Generic1InGeneric1`1/clo@7::Data + IL_00d3: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 valuetype Test/Generic1InGeneric1`1/clo@7::Data IL_00d8: ldfld !0 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::Result IL_00dd: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::SetResult(!0) IL_00e2: leave.s IL_00f2 @@ -1268,7 +1268,7 @@ type Generic1InGeneric1<'T>() = IL_00f9: ret IL_00fa: ldarg.0 - IL_00fb: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 valuetype Test/Generic1InGeneric1`1/clo@7::Data + IL_00fb: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 valuetype Test/Generic1InGeneric1`1/clo@7::Data IL_0100: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder IL_0105: ldloc.s V_10 IL_0107: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::SetException(class [netstandard]System.Exception) @@ -1281,7 +1281,7 @@ type Generic1InGeneric1<'T>() = .maxstack 8 IL_0000: ldarg.0 - IL_0001: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 valuetype Test/Generic1InGeneric1`1/clo@7::Data + IL_0001: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 valuetype Test/Generic1InGeneric1`1/clo@7::Data IL_0006: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder IL_000b: ldarg.1 IL_000c: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::SetStateMachine(class [netstandard]System.Runtime.CompilerServices.IAsyncStateMachine) @@ -1294,7 +1294,7 @@ type Generic1InGeneric1<'T>() = .maxstack 8 IL_0000: ldarg.0 - IL_0001: ldfld int32 valuetype Test/Generic1InGeneric1`1/clo@7::ResumptionPoint + IL_0001: ldfld int32 valuetype Test/Generic1InGeneric1`1/clo@7::ResumptionPoint IL_0006: ret } @@ -1304,7 +1304,7 @@ type Generic1InGeneric1<'T>() = .maxstack 8 IL_0000: ldarg.0 - IL_0001: ldfld valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 valuetype Test/Generic1InGeneric1`1/clo@7::Data + IL_0001: ldfld valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 valuetype Test/Generic1InGeneric1`1/clo@7::Data IL_0006: ret } @@ -1315,7 +1315,7 @@ type Generic1InGeneric1<'T>() = .maxstack 8 IL_0000: ldarg.0 IL_0001: ldarg.1 - IL_0002: stfld valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 valuetype Test/Generic1InGeneric1`1/clo@7::Data + IL_0002: stfld valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 valuetype Test/Generic1InGeneric1`1/clo@7::Data IL_0007: ret } @@ -1348,26 +1348,26 @@ type Generic1InGeneric1<'T>() = .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) .maxstack 4 - .locals init (valuetype Test/Generic1InGeneric1`1/clo@7 V_0, - valuetype Test/Generic1InGeneric1`1/clo@7& V_1) + .locals init (valuetype Test/Generic1InGeneric1`1/clo@7 V_0, + valuetype Test/Generic1InGeneric1`1/clo@7& V_1) IL_0000: ldloca.s V_0 - IL_0002: initobj valuetype Test/Generic1InGeneric1`1/clo@7 + IL_0002: initobj valuetype Test/Generic1InGeneric1`1/clo@7 IL_0008: ldloca.s V_0 IL_000a: stloc.1 IL_000b: ldloc.1 IL_000c: ldarg.1 - IL_000d: stfld class [runtime]System.Threading.Tasks.Task`1 valuetype Test/Generic1InGeneric1`1/clo@7::computation + IL_000d: stfld class [runtime]System.Threading.Tasks.Task`1 valuetype Test/Generic1InGeneric1`1/clo@7::computation IL_0012: ldloc.1 - IL_0013: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 valuetype Test/Generic1InGeneric1`1/clo@7::Data + IL_0013: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 valuetype Test/Generic1InGeneric1`1/clo@7::Data IL_0018: call valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::Create() IL_001d: stfld valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder IL_0022: ldloc.1 - IL_0023: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 valuetype Test/Generic1InGeneric1`1/clo@7::Data + IL_0023: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 valuetype Test/Generic1InGeneric1`1/clo@7::Data IL_0028: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder IL_002d: ldloc.1 - IL_002e: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::Start>(!!0&) + IL_002e: call instance void valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::Start>(!!0&) IL_0033: ldloc.1 - IL_0034: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 valuetype Test/Generic1InGeneric1`1/clo@7::Data + IL_0034: ldflda valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1 valuetype Test/Generic1InGeneric1`1/clo@7::Data IL_0039: ldflda valuetype [runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [FSharp.Core]Microsoft.FSharp.Control.TaskStateMachineData`1::MethodBuilder IL_003e: call instance class [netstandard]System.Threading.Tasks.Task`1 valuetype [netstandard]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::get_Task() IL_0043: ret