From 8e7bb008c25d8a7b9be2d48829371e0cf87e8be0 Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Fri, 3 Apr 2026 20:55:44 +0200 Subject: [PATCH 01/35] Optimizer: don't inline named functions in debug builds --- src/Compiler/CodeGen/IlxGen.fs | 4 + src/Compiler/Driver/CompilerConfig.fs | 4 + src/Compiler/Driver/CompilerConfig.fsi | 4 + src/Compiler/Driver/CompilerOptions.fs | 8 + src/Compiler/Driver/OptimizeInputs.fs | 4 + src/Compiler/FSComp.txt | 1 + src/Compiler/Optimize/Optimizer.fs | 68 ++- src/Compiler/Optimize/Optimizer.fsi | 2 + src/Compiler/Symbols/Symbols.fs | 2 +- src/Compiler/TypedTree/TypedTree.fs | 13 +- src/Compiler/TypedTree/TypedTree.fsi | 3 + .../EmittedIL/DebugInlineAsCall.fs | 414 ++++++++++++++++++ .../FSharp.Compiler.ComponentTests.fsproj | 1 + 13 files changed, 516 insertions(+), 12 deletions(-) create mode 100644 tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs diff --git a/src/Compiler/CodeGen/IlxGen.fs b/src/Compiler/CodeGen/IlxGen.fs index 4675e8369bd..513be5b3f93 100644 --- a/src/Compiler/CodeGen/IlxGen.fs +++ b/src/Compiler/CodeGen/IlxGen.fs @@ -312,6 +312,7 @@ type cenv = /// Guard the stack and move to a new one if necessary mutable stackGuard: StackGuard + emittedSpecializedInlineVals: HashSet } member cenv.options = @@ -8689,6 +8690,8 @@ and GenBindingAfterDebugPoint cenv cgbuf eenv bind isStateVar startMarkOpt = GenExpr cenv cgbuf eenv cctorBody discard | Method(valReprInfo, _, mspec, mspecW, _, ctps, mtps, curriedArgInfos, paramInfos, witnessInfos, argTys, retInfo) when not isStateVar -> + if vspec.InlineInfo = ValInline.InlinedDefinition && not (cenv.emittedSpecializedInlineVals.Add(vspec.Stamp)) then + CommitStartScope cgbuf startMarkOpt else let methLambdaTypars, methLambdaCtorThisValOpt, methLambdaBaseValOpt, methLambdaCurriedVars, methLambdaBody, methLambdaBodyTy = IteratedAdjustLambdaToMatchValReprInfo g cenv.amap valReprInfo rhsExpr @@ -12669,6 +12672,7 @@ type IlxAssemblyGenerator(amap: ImportMap, g: TcGlobals, tcVal: ConstraintSolver optimizeDuringCodeGen = (fun _flag expr -> expr) stackGuard = getEmptyStackGuard () delayedGenMethods = Queue() + emittedSpecializedInlineVals = HashSet() } /// Register a set of referenced assemblies with the ILX code generator diff --git a/src/Compiler/Driver/CompilerConfig.fs b/src/Compiler/Driver/CompilerConfig.fs index 0fbe48fb2eb..6075a7a32a7 100644 --- a/src/Compiler/Driver/CompilerConfig.fs +++ b/src/Compiler/Driver/CompilerConfig.fs @@ -600,6 +600,8 @@ type TcConfigBuilder = mutable strictIndentation: bool option + mutable inlineNamedFunctions: bool option + mutable exename: string option // If true - the compiler will copy FSharp.Core.dll along the produced binaries @@ -853,6 +855,7 @@ type TcConfigBuilder = dumpSignatureData = false realsig = false strictIndentation = None + inlineNamedFunctions = None compilationMode = TcGlobals.CompilationMode.Unset } @@ -1253,6 +1256,7 @@ type TcConfig private (data: TcConfigBuilder, validate: bool) = member _.fsiMultiAssemblyEmit = data.fsiMultiAssemblyEmit member _.FxResolver = data.FxResolver member _.strictIndentation = data.strictIndentation + member _.inlineNamedFunctions = data.inlineNamedFunctions member _.primaryAssembly = data.primaryAssembly member _.noFeedback = data.noFeedback member _.stackReserveSize = data.stackReserveSize diff --git a/src/Compiler/Driver/CompilerConfig.fsi b/src/Compiler/Driver/CompilerConfig.fsi index 17e035109ab..85ce24133a6 100644 --- a/src/Compiler/Driver/CompilerConfig.fsi +++ b/src/Compiler/Driver/CompilerConfig.fsi @@ -472,6 +472,8 @@ type TcConfigBuilder = mutable strictIndentation: bool option + mutable inlineNamedFunctions: bool option + mutable exename: string option mutable copyFSharpCore: CopyFSharpCoreFlag @@ -814,6 +816,8 @@ type TcConfig = member strictIndentation: bool option + member inlineNamedFunctions: bool option + member GetTargetFrameworkDirectories: unit -> string list /// Get the loaded sources that exist and issue a warning for the ones that don't diff --git a/src/Compiler/Driver/CompilerOptions.fs b/src/Compiler/Driver/CompilerOptions.fs index 98cec17265c..0ba0afb60ca 100644 --- a/src/Compiler/Driver/CompilerOptions.fs +++ b/src/Compiler/Driver/CompilerOptions.fs @@ -1207,6 +1207,14 @@ let languageFlags tcConfigB = None, Some(FSComp.SR.optsStrictIndentation (formatOptionSwitch (Option.defaultValue false tcConfigB.strictIndentation))) ) + + CompilerOption( + "inline-named-functions", + tagNone, + OptionSwitch(fun switch -> tcConfigB.inlineNamedFunctions <- Some(switch = OptionSwitch.On)), + None, + Some(FSComp.SR.optsInlineNamedFunctions ()) + ) ] // OptionBlock: Advanced user options diff --git a/src/Compiler/Driver/OptimizeInputs.fs b/src/Compiler/Driver/OptimizeInputs.fs index 78bca4bf979..cace428af4d 100644 --- a/src/Compiler/Driver/OptimizeInputs.fs +++ b/src/Compiler/Driver/OptimizeInputs.fs @@ -327,6 +327,9 @@ let ApplyAllOptimizations // Only do abstractBigTargets in the first phase, and only when TLR is on. abstractBigTargets = tcConfig.doTLR reportingPhase = true + inlineNamedFunctions = + tcConfig.inlineNamedFunctions + |> Option.defaultValue (not tcConfig.debuginfo || tcConfig.optSettings.LocalOptimizationsEnabled) } // Only do these two steps in the first phase. @@ -334,6 +337,7 @@ let ApplyAllOptimizations { firstLoopSettings with abstractBigTargets = false reportingPhase = false + inlineNamedFunctions = false } let addPhaseDiagnostics (f: PhaseFunc) (info: Phase) = diff --git a/src/Compiler/FSComp.txt b/src/Compiler/FSComp.txt index 7ca8f0a7f85..ab355660224 100644 --- a/src/Compiler/FSComp.txt +++ b/src/Compiler/FSComp.txt @@ -1561,6 +1561,7 @@ optsSetLangVersion,"Specify language version such as 'latest' or 'preview'." optsDisableLanguageFeature,"Disable a specific language feature by name." optsSupportedLangVersions,"Supported language versions:" optsStrictIndentation,"Override indentation rules implied by the language version (%s by default)" +optsInlineNamedFunctions,"Inline named 'inline' functions" nativeResourceFormatError,"Stream does not begin with a null resource and is not in '.RES' format." nativeResourceHeaderMalformed,"Resource header beginning at offset %s is malformed." formatDashItem," - %s" diff --git a/src/Compiler/Optimize/Optimizer.fs b/src/Compiler/Optimize/Optimizer.fs index 3cbb574598c..8026cc54b99 100644 --- a/src/Compiler/Optimize/Optimizer.fs +++ b/src/Compiler/Optimize/Optimizer.fs @@ -23,6 +23,7 @@ open FSharp.Compiler.Text.LayoutRender open FSharp.Compiler.Text.TaggedText open FSharp.Compiler.TypedTree open FSharp.Compiler.TypedTreeBasics +open FSharp.Compiler.Xml open FSharp.Compiler.TypedTreeOps open FSharp.Compiler.TypedTreeOps.DebugPrint open FSharp.Compiler.TypedTreePickle @@ -327,6 +328,8 @@ type OptimizationSettings = reportTotalSizes : bool processingMode : OptimizationProcessingMode + + inlineNamedFunctions: bool } static member Defaults = @@ -344,6 +347,7 @@ type OptimizationSettings = reportHasEffect = false reportTotalSizes = false processingMode = OptimizationProcessingMode.Parallel + inlineNamedFunctions = false } /// Determines if JIT optimizations are enabled @@ -432,6 +436,8 @@ type cenv = stackGuard: StackGuard realsig: bool + + specializedInlineVals: HashMultiMap } override x.ToString() = "" @@ -1692,6 +1698,7 @@ let TryEliminateBinding cenv _env bind e2 _m = not vspec1.IsCompilerGenerated then None elif vspec1.IsFixed then None + elif vspec1.InlineInfo = ValInline.InlinedDefinition then None elif vspec1.LogicalName.StartsWithOrdinal stackVarPrefix || vspec1.LogicalName.Contains suffixForVariablesThatMayNotBeEliminated then None else @@ -3421,8 +3428,60 @@ and TryDevirtualizeApplication cenv env (f, tyargs, args, m) = | _ -> None /// Attempt to inline an application of a known value at callsites -and TryInlineApplication cenv env finfo (tyargs: TType list, args: Expr list, m) = +and TryInlineApplication cenv env finfo (valExpr: Expr) (tyargs: TType list, args: Expr list, m) = let g = cenv.g + + match cenv.settings.inlineNamedFunctions, stripExpr valExpr with + | false, Expr.Val(vref, _, _) when vref.ShouldInline -> + let origFinfo = GetInfoForValWithCheck cenv env m vref + match stripValue origFinfo.ValExprInfo with + | CurriedLambdaValue(origLambdaId, _, _, origLambda, origLambdaTy) when not (Zset.contains origLambdaId env.dontInline) -> + let argsR = args |> List.map (OptimizeExpr cenv env >> fst) + let info = { TotalSize = 1; FunctionSize = 1; HasEffect = true; MightMakeCriticalTailcall = false; Info = UnknownValue } + + let canCallDirectly = + let hasNoTraits = + match vref.ValReprInfo with + | Some reprInfo -> + let tps, _, _, _ = GetValReprTypeInFSharpForm g reprInfo vref.Type m + GetTraitWitnessInfosOfTypars g 0 tps |> List.isEmpty + | None -> false + + let hasNoFreeTyargs = + tyargs |> List.forall (fun t -> (freeInType CollectTyparsNoCaching t).FreeTypars.IsEmpty) |> not + + hasNoTraits || hasNoFreeTyargs + + if canCallDirectly then + Some(mkApps g ((exprForValRef m vref, vref.Type), [tyargs], argsR, m), info) + else + let f2R = CopyExprForInlining cenv true origLambda m + let specLambda = MakeApplicationAndBetaReduce g (f2R, origLambdaTy, [tyargs], [], m) + let specLambdaTy = tyOfExpr g specLambda + + let debugVal, specLambdaR = + match cenv.specializedInlineVals.FindAll(origLambdaId) |> List.tryFind (fun (ty, _, _) -> typeEquiv g ty specLambdaTy) with + | Some (_, v, body) -> v, body + | None -> + + let specLambdaR, _ = OptimizeExpr cenv { env with dontInline = Zset.add origLambdaId env.dontInline } specLambda + let debugVal = + let name = $"<{vref.LogicalName}>__debug" + let valReprInfo = Some(InferValReprInfoOfExpr g AllowTypeDirectedDetupling.No specLambdaTy [] [] specLambdaR) + + Construct.NewVal(name, m, None, specLambdaTy, Immutable, true, valReprInfo, taccessPublic, ValNotInRecScope, None, + NormalVal, [], ValInline.InlinedDefinition, XmlDoc.Empty, false, false, false, false, false, false, None, + ParentNone) + + cenv.specializedInlineVals.Add(origLambdaId, (specLambdaTy, debugVal, specLambdaR)) + debugVal, specLambdaR + + let callExpr = mkApps g ((exprForVal m debugVal, specLambdaTy), [], argsR, m) + Some(mkCompGenLet m debugVal specLambdaR callExpr, info) + + | _ -> None + | _ -> + // Considering inlining app match finfo.Info with | StripLambdaValue (lambdaId, arities, size, f2, f2ty) when @@ -3621,7 +3680,7 @@ and OptimizeApplication cenv env (f0, f0ty, tyargs, args, m) = OptimizeExpr cenv env remade | Choice2Of2 (newf0, remake) -> - match TryInlineApplication cenv env finfo (tyargs, args, m) with + match TryInlineApplication cenv env finfo f0 (tyargs, args, m) with | Some (res, info) -> // inlined (res |> remake), info @@ -3869,6 +3928,10 @@ and OptimizeLambdas (vspec: Val option) cenv env valReprInfo expr exprTy = // can't inline any values with semi-recursive object references to self or base let value_ = + match vspec with + | Some v when v.InlineInfo = ValInline.InlinedDefinition -> UnknownValue + | _ -> + match baseValOpt with | None -> CurriedLambdaValue (lambdaId, arities, bsize, exprR, exprTy) | Some baseVal -> @@ -4403,6 +4466,7 @@ let OptimizeImplFile (settings, ccu, tcGlobals, tcVal, importMap, optEnv, isIncr casApplied=Dictionary() stackGuard = StackGuard("OptimizerStackGuardDepth") realsig = tcGlobals.realsig + specializedInlineVals = HashMultiMap(HashIdentity.Structural, true) } let env, _, _, _ as results = OptimizeImplFileInternal cenv optEnv isIncrementalFragment hidden mimpls diff --git a/src/Compiler/Optimize/Optimizer.fsi b/src/Compiler/Optimize/Optimizer.fsi index 17912af7598..10335e93a64 100644 --- a/src/Compiler/Optimize/Optimizer.fsi +++ b/src/Compiler/Optimize/Optimizer.fsi @@ -51,6 +51,8 @@ type OptimizationSettings = reportTotalSizes: bool processingMode: OptimizationProcessingMode + + inlineNamedFunctions: bool } member JitOptimizationsEnabled: bool diff --git a/src/Compiler/Symbols/Symbols.fs b/src/Compiler/Symbols/Symbols.fs index 08252dd76d5..6348ec64649 100644 --- a/src/Compiler/Symbols/Symbols.fs +++ b/src/Compiler/Symbols/Symbols.fs @@ -1857,7 +1857,7 @@ type FSharpMemberOrFunctionOrValue(cenv, d:FSharpMemberOrValData, item) = match v.InlineInfo with | ValInline.Always -> FSharpInlineAnnotation.AlwaysInline | ValInline.Optional -> FSharpInlineAnnotation.OptionalInline - | ValInline.Never -> FSharpInlineAnnotation.NeverInline + | ValInline.Never | ValInline.InlinedDefinition -> FSharpInlineAnnotation.NeverInline member _.IsMutable = if isUnresolved() then false else diff --git a/src/Compiler/TypedTree/TypedTree.fs b/src/Compiler/TypedTree/TypedTree.fs index 733b269b588..4c43a568bc3 100644 --- a/src/Compiler/TypedTree/TypedTree.fs +++ b/src/Compiler/TypedTree/TypedTree.fs @@ -41,21 +41,15 @@ type StampMap<'T> = Map [] type ValInline = - - /// Indicates the value is inlined but the .NET IL code for the function still exists, e.g. to satisfy interfaces on objects, but that it is also always inlined | Always - - /// Indicates the value may optionally be inlined by the optimizer | Optional - - /// Indicates the value must never be inlined by the optimizer | Never + | InlinedDefinition - /// Returns true if the implementation of a value should be inlined member x.ShouldInline = match x with | ValInline.Always -> true - | ValInline.Optional | ValInline.Never -> false + | ValInline.Optional | ValInline.Never | ValInline.InlinedDefinition -> false /// A flag associated with values that indicates whether the recursive scope of the value is currently being processed, and /// if the value has been generalized or not as yet. @@ -110,6 +104,7 @@ type ValFlags(flags: int64) = (if isCompGen then 0b00000000000000001000L else 0b000000000000000000000L) ||| (match inlineInfo with + | ValInline.InlinedDefinition -> 0b00000000000000000000L | ValInline.Always -> 0b00000000000000010000L | ValInline.Optional -> 0b00000000000000100000L | ValInline.Never -> 0b00000000000000110000L) ||| @@ -166,7 +161,7 @@ type ValFlags(flags: int64) = member x.InlineInfo = match (flags &&& 0b00000000000000110000L) with - | 0b00000000000000000000L + | 0b00000000000000000000L -> ValInline.InlinedDefinition | 0b00000000000000010000L -> ValInline.Always | 0b00000000000000100000L -> ValInline.Optional | 0b00000000000000110000L -> ValInline.Never diff --git a/src/Compiler/TypedTree/TypedTree.fsi b/src/Compiler/TypedTree/TypedTree.fsi index 7fbe446641a..e104625655f 100644 --- a/src/Compiler/TypedTree/TypedTree.fsi +++ b/src/Compiler/TypedTree/TypedTree.fsi @@ -41,6 +41,9 @@ type ValInline = /// Indicates the value must never be inlined by the optimizer | Never + /// Indicates a debug-only value produced from inlining an 'inline' function definition. + | InlinedDefinition + /// Returns true if the implementation of a value must always be inlined member ShouldInline: bool diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs new file mode 100644 index 00000000000..94fb1c79a4b --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs @@ -0,0 +1,414 @@ +namespace EmittedIL + +open Xunit +open FSharp.Test.Compiler + +module DebugInlineAsCall = + + [] + let ``Call 01 - Release`` () = + FSharp """ +let inline f (x: int) = + x + x + +let i = f 5 +""" + |> asExe + |> compile + |> verifyILContains ["ldc.i4.s 10"] + |> shouldSucceed + + [] + let ``Call 02 - Debug`` () = + FSharp """ +let inline f (x: int) = + x + x + +[] +let main _ = + let i = f 5 + if i = 10 then 0 else 1 +""" + |> withDebug + |> withNoOptimize + |> asExe + |> compileAndRun + |> verifyILContains ["call int32 Test::f(int32)"] + |> shouldSucceed + + [] + let ``Call 03 - Two args`` () = + FSharp """ + +let inline add a b = + a + b + +[] +let main _ = + let i = add 1 2 + if i = 3 then 0 else 1 +""" + |> withDebug + |> withNoOptimize + |> asExe + |> compileAndRun + |> verifyILContains ["call int32 Test::'__debug@8'(int32,"] + |> shouldSucceed + + [] + let ``Call 04 - Function arg`` () = + FSharp """ +let inline apply (f: 'a -> 'b -> 'c) (x: 'a) (y: 'b) : 'c = + f x y + +[] +let main _ = + let i = apply (+) 3 4 + if i = 7 then 0 else 1 +""" + |> withDebug + |> withNoOptimize + |> asExe + |> compileAndRun + |> verifyILContains ["call !!2 Test::apply(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>,"] + |> shouldSucceed + + + [] + let ``Call 05 - Nested inline`` () = + FSharp """ +let inline double (x: int) = + x + x + +let inline quadruple (x: int) = + double (double x) + +[] +let main _ = + let i = quadruple 3 + if i = 12 then 0 else 1 +""" + |> withDebug + |> withNoOptimize + |> asExe + |> compileAndRun + |> verifyILContains + ["call int32 Test::double(int32)" + "call int32 Test::quadruple(int32)"] + |> shouldSucceed + + [] + let ``Call 06 - Multiple calls`` () = + FSharp """ +let inline double (x: int) = + x + x + +[] +let main _ = + let i = double 1 + double 2 + if i = 6 then 0 else 1 +""" + |> withDebug + |> withNoOptimize + |> asExe + |> compileAndRun + |> verifyILContains [ "call int32 Test::double(int32)" ] + + [] + let ``Call 07 - Local function`` () = + FSharp """ +[] +let main _ = + let inline double (x: int) = x + x + let i = double 5 + if i = 10 then 0 else 1 +""" + |> withDebug + |> withNoOptimize + |> asExe + |> compileAndRun + |> verifyILContains ["call int32 Test::'__debug@5'(int32)"] + |> shouldSucceed + + [] + let ``Call 08 - Local generic function`` () = + FSharp """ +[] +let main _ = + let inline apply (f: 'a -> 'b) (x: 'a) : 'b = f x + let i = apply (fun x -> x + 1) 5 + if i = 6 then 0 else 1 +""" + |> withDebug + |> withNoOptimize + |> asExe + |> compileAndRun + |> verifyILContains ["call int32 Test::'__debug@5'(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,"] + |> shouldSucceed + + [] + let ``Call 09 - FSharp.Core not`` () = + FSharp """ +[] +let main _ = + let b = not true + if b = false then 0 else 1 +""" + |> withDebug + |> withNoOptimize + |> asExe + |> compileAndRun + |> verifyILContains ["call bool [FSharp.Core]Microsoft.FSharp.Core.Operators::Not(bool)"] + |> shouldSucceed + + [] + let ``Call 10 - Different assembly`` () = + let library = + FSharp """ +module MyLib + +let inline triple (x: int) = x + x + x +""" + |> withDebug + |> withNoOptimize + |> asLibrary + |> withName "mylib" + + FSharp """ +open MyLib + +[] +let main _ = + let i = triple 3 + if i = 9 then 0 else 1 +""" + |> withDebug + |> withNoOptimize + |> withReferences [library] + |> asExe + |> compileAndRun + |> verifyILContains ["call int32 [mylib]MyLib::triple(int32)"] + |> shouldSucceed + + [] + let ``Call 11 - Measure`` () = + FSharp """ +[] type cm + +let inline scale (x: float<'u>) = x * 2.0 + +[] +let main _ = + let v = scale 5.0 + if v = 10.0 then 0 else 1 +""" + |> withDebug + |> withNoOptimize + |> asExe + |> compileAndRun + |> verifyILContains ["call float64 Test::scale(float64)"] + |> shouldSucceed + + [] + let ``Call 12 - No inner optimization`` () = + FSharp """ +[] +let main _ = + let inline f (x: int) = + let i = 5 + 10 + x + i + + let i = f 20 + if i = 35 then 0 else 1 +""" + |> withDebug + |> withNoOptimize + |> asExe + |> compileAndRun + |> verifyILContains + [ "ldc.i4.5" + "ldc.i4.s 10" + "call int32 Test::'__debug@8'(int32)" ] + |> shouldSucceed + + [] + let ``SRTP 01`` () = + FSharp """ +let inline add (x: ^T) (y: ^T) = + x + y + +[] +let main _ = + let i = add 3 4 + if i = 7 then 0 else 1 +""" + |> withDebug + |> withNoOptimize + |> asExe + |> compileAndRun + |> verifyILContains ["call int32 Test::'__debug@7'(int32,"] + |> shouldSucceed + + [] + let ``SRTP 02 - Local `` () = + FSharp """ +[] +let main _ = + let inline add (x: ^T) (y: ^T) = x + y + let i = add 3 4 + if i = 7 then 0 else 1 +""" + |> withDebug + |> withNoOptimize + |> asExe + |> compileAndRun + |> verifyILContains ["call int32 Test::'__debug@5'(int32,"] + |> shouldSucceed + + [] + let ``SRTP 03 - Different type arguments`` () = + FSharp """ +let inline getLength (x: ^T) = + (^T : (member Length : int) x) + +[] +let main _ = + let i = getLength "hello" + let j = getLength [1; 2; 3] + if i = 5 && j = 3 then 0 else 1 +""" + |> withDebug + |> withNoOptimize + |> asExe + |> compileAndRun + |> verifyILContains + [ "call int32 Test::'__debug@7'(string)" + "call int32 Test::'__debug@8-1'(class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1)" ] + |> shouldSucceed + + [] + let ``SRTP 04 - Multiple calls`` () = + FSharp """ +let inline add (x: ^T) (y: ^T) = x + y + +[] +let main _ = + let i = add 1 2 + add 3 4 + if i = 10 then 0 else 1 +""" + |> withDebug + |> withNoOptimize + |> asExe + |> compileAndRun + |> verifyILContains [ "call int32 Test::'__debug@6'(int32," ] + |> shouldSucceed + + + [] + let ``SRTP 05 - Different assembly`` () = + let library = + FSharp """ +module MyLib + +let inline add (x: ^T) (y: ^T) = x + y +""" + |> withDebug + |> withNoOptimize + |> asLibrary + |> withName "mylib2" + + FSharp """ +open MyLib + +[] +let main _ = + let i = add 3 4 + if i = 7 then 0 else 1 +""" + |> withDebug + |> withNoOptimize + |> withReferences [library] + |> asExe + |> compileAndRun + |> verifyILContains ["call int32 Test::'__debug@6'(int32,"] + |> shouldSucceed + + [] + let ``SRTP 06 - Different assembly`` () = + let library = + FSharp """ +module MyLib + +let inline add (x: ^T) (y: ^T) = x + y +""" + |> withDebug + |> withNoOptimize + |> asLibrary + |> withName "mylib3" + + FSharp """ +open MyLib + +let inline double (x: ^T) = add x x + +[] +let main _ = + let i = double 5 + if i = 10 then 0 else 1 +""" + |> withDebug + |> withNoOptimize + |> withReferences [library] + |> asExe + |> compileAndRun + |> verifyILContains + [ "call int32 Test::'__debug@8'(int32)" + "call int32 Test::'__debug@4'(int32," ] + |> shouldSucceed + + [] + let ``SRTP 07 - Nested - Same project`` () = + FSharp """ +let inline add (x: ^T) (y: ^T) = x + y + +let inline double (x: ^T) = add x x + +[] +let main _ = + let i = double 5 + if i = 10 then 0 else 1 +""" + |> withDebug + |> withNoOptimize + |> asExe + |> compileAndRun + |> verifyILContains + [ "call int32 Test::'__debug@8'(int32)" + "call int32 Test::'__debug@4'(int32," ] + |> shouldSucceed + + + + [] + let ``SRTP 08 - Nested - Different type arguments`` () = + FSharp """ +let inline add (x: ^T) (y: ^T) = x + y + +let inline addBoth (x: ^A) (y: ^B) = + let a = add x x + let b = add y y + (a, b) + +[] +let main _ = + let (a, b) = addBoth 2 3.0 + if a = 4 && b = 6.0 then 0 else 1 +""" + |> withDebug + |> withNoOptimize + |> asExe + |> compileAndRun + |> verifyILContains + [ "call int32 Test::'__debug@5'(int32," + "call float64 Test::'__debug@6-1'(float64," ] + |> shouldSucceed diff --git a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj index aa5a5cc11f2..7fd792f8f3f 100644 --- a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj +++ b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj @@ -229,6 +229,7 @@ + From 4eca296bf36d235f697149faca5c9e0046a03fe0 Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Tue, 7 Apr 2026 15:09:05 +0200 Subject: [PATCH 02/35] Xlf --- src/Compiler/xlf/FSComp.txt.cs.xlf | 5 +++++ src/Compiler/xlf/FSComp.txt.de.xlf | 5 +++++ src/Compiler/xlf/FSComp.txt.es.xlf | 5 +++++ src/Compiler/xlf/FSComp.txt.fr.xlf | 5 +++++ src/Compiler/xlf/FSComp.txt.it.xlf | 5 +++++ src/Compiler/xlf/FSComp.txt.ja.xlf | 5 +++++ src/Compiler/xlf/FSComp.txt.ko.xlf | 5 +++++ src/Compiler/xlf/FSComp.txt.pl.xlf | 5 +++++ src/Compiler/xlf/FSComp.txt.pt-BR.xlf | 5 +++++ src/Compiler/xlf/FSComp.txt.ru.xlf | 5 +++++ src/Compiler/xlf/FSComp.txt.tr.xlf | 5 +++++ src/Compiler/xlf/FSComp.txt.zh-Hans.xlf | 5 +++++ src/Compiler/xlf/FSComp.txt.zh-Hant.xlf | 5 +++++ 13 files changed, 65 insertions(+) diff --git a/src/Compiler/xlf/FSComp.txt.cs.xlf b/src/Compiler/xlf/FSComp.txt.cs.xlf index 811bc1b86bb..ac2eccfb559 100644 --- a/src/Compiler/xlf/FSComp.txt.cs.xlf +++ b/src/Compiler/xlf/FSComp.txt.cs.xlf @@ -1037,6 +1037,11 @@ Zobrazí povolené hodnoty pro jazykovou verzi. + + Inline named 'inline' functions + Inline named 'inline' functions + + Invalid use of emitting a reference assembly, do not use '--standalone or --staticlink' with '--refonly or --refout'. Neplatné použití generování referenčního sestavení, nepoužívejte --standalone ani --staticlink s --refonly nebo --refout. diff --git a/src/Compiler/xlf/FSComp.txt.de.xlf b/src/Compiler/xlf/FSComp.txt.de.xlf index 994f29280bd..c0ab56aa7ac 100644 --- a/src/Compiler/xlf/FSComp.txt.de.xlf +++ b/src/Compiler/xlf/FSComp.txt.de.xlf @@ -1037,6 +1037,11 @@ Anzeigen der zulässigen Werte für die Sprachversion. + + Inline named 'inline' functions + Inline named 'inline' functions + + Invalid use of emitting a reference assembly, do not use '--standalone or --staticlink' with '--refonly or --refout'. Ungültige Verwendung der Ausgabe einer Referenzassembly. Verwenden Sie nicht „--standalone“ oder „--staticlink“ mit „--refonly“ oder „--refout“. diff --git a/src/Compiler/xlf/FSComp.txt.es.xlf b/src/Compiler/xlf/FSComp.txt.es.xlf index 670163d0f88..8e9678d60c8 100644 --- a/src/Compiler/xlf/FSComp.txt.es.xlf +++ b/src/Compiler/xlf/FSComp.txt.es.xlf @@ -1037,6 +1037,11 @@ Muestra los valores permitidos para la versión del lenguaje. + + Inline named 'inline' functions + Inline named 'inline' functions + + Invalid use of emitting a reference assembly, do not use '--standalone or --staticlink' with '--refonly or --refout'. Uso no válido de emisión de un ensamblado de referencia, no use '--standalone or --staticlink' con '--refonly or --refout'. diff --git a/src/Compiler/xlf/FSComp.txt.fr.xlf b/src/Compiler/xlf/FSComp.txt.fr.xlf index de16952ceec..4bce8d1951f 100644 --- a/src/Compiler/xlf/FSComp.txt.fr.xlf +++ b/src/Compiler/xlf/FSComp.txt.fr.xlf @@ -1037,6 +1037,11 @@ Affichez les valeurs autorisées pour la version du langage. + + Inline named 'inline' functions + Inline named 'inline' functions + + Invalid use of emitting a reference assembly, do not use '--standalone or --staticlink' with '--refonly or --refout'. Utilisation non valide de l’émission d’un assembly de référence, n’utilisez pas '--standalone ou --staticlink' avec '--refonly ou --refout'. diff --git a/src/Compiler/xlf/FSComp.txt.it.xlf b/src/Compiler/xlf/FSComp.txt.it.xlf index 5b52ef2ebb2..f7de737a99d 100644 --- a/src/Compiler/xlf/FSComp.txt.it.xlf +++ b/src/Compiler/xlf/FSComp.txt.it.xlf @@ -1037,6 +1037,11 @@ Visualizzare i valori consentiti per la versione della lingua. + + Inline named 'inline' functions + Inline named 'inline' functions + + Invalid use of emitting a reference assembly, do not use '--standalone or --staticlink' with '--refonly or --refout'. Utilizzo non valido della creazione di un assembly di riferimento. Non usare insieme '--standalone o --staticlink' con '--refonly o --refout'.. diff --git a/src/Compiler/xlf/FSComp.txt.ja.xlf b/src/Compiler/xlf/FSComp.txt.ja.xlf index 5eef9cc71a4..0c9b2825081 100644 --- a/src/Compiler/xlf/FSComp.txt.ja.xlf +++ b/src/Compiler/xlf/FSComp.txt.ja.xlf @@ -1037,6 +1037,11 @@ 言語バージョンで許可されている値を表示します。 + + Inline named 'inline' functions + Inline named 'inline' functions + + Invalid use of emitting a reference assembly, do not use '--standalone or --staticlink' with '--refonly or --refout'. 参照アセンブリの出力の使用が無効です。'--standalone または --staticlink' を '--relabelly または --refout' と共に使用しないでください。 diff --git a/src/Compiler/xlf/FSComp.txt.ko.xlf b/src/Compiler/xlf/FSComp.txt.ko.xlf index ae7ca4394f0..a602a54ae29 100644 --- a/src/Compiler/xlf/FSComp.txt.ko.xlf +++ b/src/Compiler/xlf/FSComp.txt.ko.xlf @@ -1037,6 +1037,11 @@ 언어 버전에 허용되는 값을 표시합니다. + + Inline named 'inline' functions + Inline named 'inline' functions + + Invalid use of emitting a reference assembly, do not use '--standalone or --staticlink' with '--refonly or --refout'. 참조 어셈블리 내보내기를 잘못 사용했습니다. '--refonly 또는 --refout'과 함께 '--standalone 또는 --staticlink'를 사용하지 마세요. diff --git a/src/Compiler/xlf/FSComp.txt.pl.xlf b/src/Compiler/xlf/FSComp.txt.pl.xlf index 5ed89505503..eba3456114e 100644 --- a/src/Compiler/xlf/FSComp.txt.pl.xlf +++ b/src/Compiler/xlf/FSComp.txt.pl.xlf @@ -1037,6 +1037,11 @@ Wyświetl dozwolone wartości dla wersji językowej. + + Inline named 'inline' functions + Inline named 'inline' functions + + Invalid use of emitting a reference assembly, do not use '--standalone or --staticlink' with '--refonly or --refout'. Nieprawidłowe użycie emitowania zestawu odwołania. Nie używaj elementu „--standalone ani --staticlink” z elementem „--refonly lub --refout”. diff --git a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf index 30f75e12c8f..f14a1e9222f 100644 --- a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf +++ b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf @@ -1037,6 +1037,11 @@ Exiba os valores permitidos para a versão do idioma. + + Inline named 'inline' functions + Inline named 'inline' functions + + Invalid use of emitting a reference assembly, do not use '--standalone or --staticlink' with '--refonly or --refout'. Uso inválido da emissão de um assembly de referência, não use '--standalone ou --staticlink' com '--refonly ou --refout'. diff --git a/src/Compiler/xlf/FSComp.txt.ru.xlf b/src/Compiler/xlf/FSComp.txt.ru.xlf index 2f606681434..f9ec703c7a2 100644 --- a/src/Compiler/xlf/FSComp.txt.ru.xlf +++ b/src/Compiler/xlf/FSComp.txt.ru.xlf @@ -1037,6 +1037,11 @@ Отображение допустимых значений для версии языка. + + Inline named 'inline' functions + Inline named 'inline' functions + + Invalid use of emitting a reference assembly, do not use '--standalone or --staticlink' with '--refonly or --refout'. Недопустимое использование при создании базовой сборки. Не используйте "--standalone or --staticlink" с "--refonly or --refout". diff --git a/src/Compiler/xlf/FSComp.txt.tr.xlf b/src/Compiler/xlf/FSComp.txt.tr.xlf index 4e89b343fe7..9c2eaaa4ad3 100644 --- a/src/Compiler/xlf/FSComp.txt.tr.xlf +++ b/src/Compiler/xlf/FSComp.txt.tr.xlf @@ -1037,6 +1037,11 @@ Dil sürümü için izin verilen değerleri görüntüleyin. + + Inline named 'inline' functions + Inline named 'inline' functions + + Invalid use of emitting a reference assembly, do not use '--standalone or --staticlink' with '--refonly or --refout'. Başvuru bütünleştirilmiş kodu oluşturmanın geçersiz kullanımı; '--standalone’ veya ‘--staticlink' seçeneğini '--refonly’ veya ‘--refout' ile birlikte kullanmayın. diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf index 3485c64f09a..d468814b809 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf @@ -1037,6 +1037,11 @@ 显示语言版本的允许值。 + + Inline named 'inline' functions + Inline named 'inline' functions + + Invalid use of emitting a reference assembly, do not use '--standalone or --staticlink' with '--refonly or --refout'. 发出引用程序集的使用无效,请勿将 '--standalone 或 --staticlink' 与 '--refonly 或 --refout' 一起使用。 diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf index 2c60a0abcf2..de67f5633e9 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf @@ -1037,6 +1037,11 @@ 顯示語言版本的允許值。 + + Inline named 'inline' functions + Inline named 'inline' functions + + Invalid use of emitting a reference assembly, do not use '--standalone or --staticlink' with '--refonly or --refout'. 發出參考組件的使用無效,請勿同時使用 '--standalone 或 '--refonly' 和 '--refout'。 From 48092676f56412f0e424648b78885f9f2d28da3a Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Tue, 7 Apr 2026 15:11:35 +0200 Subject: [PATCH 03/35] Release notes --- docs/release-notes/.FSharp.Compiler.Service/11.0.100.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md index 5c87eb88b88..281aedcb283 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md +++ b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md @@ -60,3 +60,4 @@ * Improvements in error and warning messages: new error FS3885 when `let!`/`use!` is the final expression in a computation expression; new warning FS3886 when a list literal contains a single tuple element (likely missing `;` separator); improved wording for FS0003, FS0025, FS0039, FS0072, FS0247, FS0597, FS0670, FS3082, and SRTP operator-not-in-scope hints. ([PR #19398](https://github.com/dotnet/fsharp/pull/19398)) ### Breaking Changes +* Optimizer: don't inline named functions in debug builds ([PR #19548](https://github.com/dotnet/fsharp/pull/19548) \ No newline at end of file From 7ef0be3ed142a2d56557c6aa563c7f8e4d96ae5d Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Tue, 7 Apr 2026 16:37:54 +0200 Subject: [PATCH 04/35] Don't specialize local functions --- src/Compiler/Optimize/Optimizer.fs | 7 ++----- .../EmittedIL/DebugInlineAsCall.fs | 6 +++--- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/Compiler/Optimize/Optimizer.fs b/src/Compiler/Optimize/Optimizer.fs index 8026cc54b99..226cfa76a52 100644 --- a/src/Compiler/Optimize/Optimizer.fs +++ b/src/Compiler/Optimize/Optimizer.fs @@ -3441,11 +3441,8 @@ and TryInlineApplication cenv env finfo (valExpr: Expr) (tyargs: TType list, arg let canCallDirectly = let hasNoTraits = - match vref.ValReprInfo with - | Some reprInfo -> - let tps, _, _, _ = GetValReprTypeInFSharpForm g reprInfo vref.Type m - GetTraitWitnessInfosOfTypars g 0 tps |> List.isEmpty - | None -> false + let tps, _ = tryDestForallTy g vref.Type + GetTraitConstraintInfosOfTypars g tps |> List.isEmpty let hasNoFreeTyargs = tyargs |> List.forall (fun t -> (freeInType CollectTyparsNoCaching t).FreeTypars.IsEmpty) |> not diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs index 94fb1c79a4b..dea745e707f 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs @@ -127,7 +127,7 @@ let main _ = |> withNoOptimize |> asExe |> compileAndRun - |> verifyILContains ["call int32 Test::'__debug@5'(int32)"] + |> verifyILContains ["callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0)"] |> shouldSucceed [] @@ -143,7 +143,7 @@ let main _ = |> withNoOptimize |> asExe |> compileAndRun - |> verifyILContains ["call int32 Test::'__debug@5'(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,"] + |> verifyILContains ["call !!0 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,int32>::InvokeFast(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>,"] |> shouldSucceed [] @@ -228,7 +228,7 @@ let main _ = |> verifyILContains [ "ldc.i4.5" "ldc.i4.s 10" - "call int32 Test::'__debug@8'(int32)" ] + "callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0)" ] |> shouldSucceed [] From 6002d831d6ddfed6f4485db3363fdfdcc36903cf Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Tue, 7 Apr 2026 17:03:03 +0200 Subject: [PATCH 05/35] Remove specialized values caching --- src/Compiler/CodeGen/IlxGen.fs | 4 ---- src/Compiler/Optimize/Optimizer.fs | 24 +++++++++---------- .../EmittedIL/DebugInlineAsCall.fs | 4 +++- 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/src/Compiler/CodeGen/IlxGen.fs b/src/Compiler/CodeGen/IlxGen.fs index 513be5b3f93..4675e8369bd 100644 --- a/src/Compiler/CodeGen/IlxGen.fs +++ b/src/Compiler/CodeGen/IlxGen.fs @@ -312,7 +312,6 @@ type cenv = /// Guard the stack and move to a new one if necessary mutable stackGuard: StackGuard - emittedSpecializedInlineVals: HashSet } member cenv.options = @@ -8690,8 +8689,6 @@ and GenBindingAfterDebugPoint cenv cgbuf eenv bind isStateVar startMarkOpt = GenExpr cenv cgbuf eenv cctorBody discard | Method(valReprInfo, _, mspec, mspecW, _, ctps, mtps, curriedArgInfos, paramInfos, witnessInfos, argTys, retInfo) when not isStateVar -> - if vspec.InlineInfo = ValInline.InlinedDefinition && not (cenv.emittedSpecializedInlineVals.Add(vspec.Stamp)) then - CommitStartScope cgbuf startMarkOpt else let methLambdaTypars, methLambdaCtorThisValOpt, methLambdaBaseValOpt, methLambdaCurriedVars, methLambdaBody, methLambdaBodyTy = IteratedAdjustLambdaToMatchValReprInfo g cenv.amap valReprInfo rhsExpr @@ -12672,7 +12669,6 @@ type IlxAssemblyGenerator(amap: ImportMap, g: TcGlobals, tcVal: ConstraintSolver optimizeDuringCodeGen = (fun _flag expr -> expr) stackGuard = getEmptyStackGuard () delayedGenMethods = Queue() - emittedSpecializedInlineVals = HashSet() } /// Register a set of referenced assemblies with the ILX code generator diff --git a/src/Compiler/Optimize/Optimizer.fs b/src/Compiler/Optimize/Optimizer.fs index 226cfa76a52..5edc4dd37a1 100644 --- a/src/Compiler/Optimize/Optimizer.fs +++ b/src/Compiler/Optimize/Optimizer.fs @@ -437,7 +437,7 @@ type cenv = realsig: bool - specializedInlineVals: HashMultiMap + specializedInlineVals: HashMultiMap } override x.ToString() = "" @@ -3456,22 +3456,22 @@ and TryInlineApplication cenv env finfo (valExpr: Expr) (tyargs: TType list, arg let specLambda = MakeApplicationAndBetaReduce g (f2R, origLambdaTy, [tyargs], [], m) let specLambdaTy = tyOfExpr g specLambda - let debugVal, specLambdaR = - match cenv.specializedInlineVals.FindAll(origLambdaId) |> List.tryFind (fun (ty, _, _) -> typeEquiv g ty specLambdaTy) with - | Some (_, v, body) -> v, body + let specLambdaR = + match cenv.specializedInlineVals.FindAll(origLambdaId) |> List.tryFind (fun (ty, _) -> typeEquiv g ty specLambdaTy) with + | Some (_, body) -> copyExpr g CloneAll body | None -> let specLambdaR, _ = OptimizeExpr cenv { env with dontInline = Zset.add origLambdaId env.dontInline } specLambda - let debugVal = - let name = $"<{vref.LogicalName}>__debug" - let valReprInfo = Some(InferValReprInfoOfExpr g AllowTypeDirectedDetupling.No specLambdaTy [] [] specLambdaR) + cenv.specializedInlineVals.Add(origLambdaId, (specLambdaTy, specLambdaR)) + specLambdaR - Construct.NewVal(name, m, None, specLambdaTy, Immutable, true, valReprInfo, taccessPublic, ValNotInRecScope, None, - NormalVal, [], ValInline.InlinedDefinition, XmlDoc.Empty, false, false, false, false, false, false, None, - ParentNone) + let debugVal = + let name = $"<{vref.LogicalName}>__debug" + let valReprInfo = Some(InferValReprInfoOfExpr g AllowTypeDirectedDetupling.No specLambdaTy [] [] specLambdaR) - cenv.specializedInlineVals.Add(origLambdaId, (specLambdaTy, debugVal, specLambdaR)) - debugVal, specLambdaR + Construct.NewVal(name, m, None, specLambdaTy, Immutable, true, valReprInfo, taccessPublic, ValNotInRecScope, None, + NormalVal, [], ValInline.InlinedDefinition, XmlDoc.Empty, false, false, false, false, false, false, None, + ParentNone) let callExpr = mkApps g ((exprForVal m debugVal, specLambdaTy), [], argsR, m) Some(mkCompGenLet m debugVal specLambdaR callExpr, info) diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs index dea745e707f..e85be18d47b 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs @@ -300,7 +300,9 @@ let main _ = |> withNoOptimize |> asExe |> compileAndRun - |> verifyILContains [ "call int32 Test::'__debug@6'(int32," ] + |> verifyILContains + [ "call int32 Test::'__debug@6'(int32," + "call int32 Test::'__debug@6-1'(int32," ] |> shouldSucceed From 1b666825b0a7c4137ac298a9115f6fb734d5b7f0 Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Wed, 8 Apr 2026 16:20:46 +0200 Subject: [PATCH 06/35] Fix witness passing --- src/Compiler/Optimize/Optimizer.fs | 40 +++++++++++++++++++----------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/src/Compiler/Optimize/Optimizer.fs b/src/Compiler/Optimize/Optimizer.fs index 5edc4dd37a1..b092fa46037 100644 --- a/src/Compiler/Optimize/Optimizer.fs +++ b/src/Compiler/Optimize/Optimizer.fs @@ -3439,15 +3439,15 @@ and TryInlineApplication cenv env finfo (valExpr: Expr) (tyargs: TType list, arg let argsR = args |> List.map (OptimizeExpr cenv env >> fst) let info = { TotalSize = 1; FunctionSize = 1; HasEffect = true; MightMakeCriticalTailcall = false; Info = UnknownValue } - let canCallDirectly = - let hasNoTraits = - let tps, _ = tryDestForallTy g vref.Type - GetTraitConstraintInfosOfTypars g tps |> List.isEmpty + let hasNoTraits = + let tps, _ = tryDestForallTy g vref.Type + GetTraitConstraintInfosOfTypars g tps |> List.isEmpty - let hasNoFreeTyargs = - tyargs |> List.forall (fun t -> (freeInType CollectTyparsNoCaching t).FreeTypars.IsEmpty) |> not + let allTyargsAreConcrete = + tyargs |> List.forall (fun t -> (freeInType CollectTyparsNoCaching t).FreeTypars.IsEmpty) - hasNoTraits || hasNoFreeTyargs + let canCallDirectly = + hasNoTraits || (not allTyargsAreConcrete && vref.ValReprInfo.IsSome) if canCallDirectly then Some(mkApps g ((exprForValRef m vref, vref.Type), [tyargs], argsR, m), info) @@ -3457,17 +3457,27 @@ and TryInlineApplication cenv env finfo (valExpr: Expr) (tyargs: TType list, arg let specLambdaTy = tyOfExpr g specLambda let specLambdaR = - match cenv.specializedInlineVals.FindAll(origLambdaId) |> List.tryFind (fun (ty, _) -> typeEquiv g ty specLambdaTy) with - | Some (_, body) -> copyExpr g CloneAll body - | None -> - - let specLambdaR, _ = OptimizeExpr cenv { env with dontInline = Zset.add origLambdaId env.dontInline } specLambda - cenv.specializedInlineVals.Add(origLambdaId, (specLambdaTy, specLambdaR)) - specLambdaR + if allTyargsAreConcrete then + match cenv.specializedInlineVals.FindAll(origLambdaId) |> List.tryFind (fun (ty, _) -> typeEquiv g ty specLambdaTy) with + | Some (_, body) -> copyExpr g CloneAll body + | None -> + + let specLambdaR, _ = OptimizeExpr cenv { env with dontInline = Zset.add origLambdaId env.dontInline } specLambda + cenv.specializedInlineVals.Add(origLambdaId, (specLambdaTy, specLambdaR)) + specLambdaR + else + let specLambdaR, _ = OptimizeExpr cenv { env with dontInline = Zset.add origLambdaId env.dontInline } specLambda + specLambdaR let debugVal = let name = $"<{vref.LogicalName}>__debug" - let valReprInfo = Some(InferValReprInfoOfExpr g AllowTypeDirectedDetupling.No specLambdaTy [] [] specLambdaR) + // When tyargs have free type variables, omit ValReprInfo so IlxGen compiles this + // as a closure that captures type variables and witnesses from the enclosing scope. + let valReprInfo = + if allTyargsAreConcrete then + Some(InferValReprInfoOfExpr g AllowTypeDirectedDetupling.No specLambdaTy [] [] specLambdaR) + else + None Construct.NewVal(name, m, None, specLambdaTy, Immutable, true, valReprInfo, taccessPublic, ValNotInRecScope, None, NormalVal, [], ValInline.InlinedDefinition, XmlDoc.Empty, false, false, false, false, false, false, None, From d37bc134d43ea8dfee90245b15e5f523dc7cefdb Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Thu, 9 Apr 2026 16:53:27 +0200 Subject: [PATCH 07/35] Inline NoDynamicInvocation and some builtin functions --- src/Compiler/Optimize/Optimizer.fs | 13 ++++++++++++- src/Compiler/TypedTree/TcGlobals.fs | 14 ++++++++++++++ src/Compiler/TypedTree/TcGlobals.fsi | 2 ++ .../EmittedIL/DebugInlineAsCall.fs | 3 +-- 4 files changed, 29 insertions(+), 3 deletions(-) diff --git a/src/Compiler/Optimize/Optimizer.fs b/src/Compiler/Optimize/Optimizer.fs index b092fa46037..39aa5fc4d38 100644 --- a/src/Compiler/Optimize/Optimizer.fs +++ b/src/Compiler/Optimize/Optimizer.fs @@ -2341,6 +2341,17 @@ let inline IsStateMachineExpr g overallExpr = isReturnsResumableCodeTy g valRef.TauType | _ -> false +let shouldForceInlineMembersInDebug (g: TcGlobals) (tcref: EntityRef) = + match g.fslibForceInlineModules.TryGetValue tcref.LogicalName with + | true, modRef -> tyconRefEq g tcref modRef + | _ -> false + +let shouldForceInlineInDebug (g: TcGlobals) (vref: ValRef) : bool = + ValHasWellKnownAttribute g WellKnownValAttributes.NoDynamicInvocationAttribute_True vref.Deref || + ValHasWellKnownAttribute g WellKnownValAttributes.NoDynamicInvocationAttribute_False vref.Deref || + + vref.HasDeclaringEntity && shouldForceInlineMembersInDebug g vref.DeclaringEntity + /// Optimize/analyze an expression let rec OptimizeExpr cenv (env: IncrementalOptimizationEnv) expr = cenv.stackGuard.Guard <| fun () -> @@ -3432,7 +3443,7 @@ and TryInlineApplication cenv env finfo (valExpr: Expr) (tyargs: TType list, arg let g = cenv.g match cenv.settings.inlineNamedFunctions, stripExpr valExpr with - | false, Expr.Val(vref, _, _) when vref.ShouldInline -> + | false, Expr.Val(vref, _, _) when vref.ShouldInline && not (shouldForceInlineInDebug cenv.g vref) -> let origFinfo = GetInfoForValWithCheck cenv env m vref match stripValue origFinfo.ValExprInfo with | CurriedLambdaValue(origLambdaId, _, _, origLambda, origLambdaTy) when not (Zset.contains origLambdaId env.dontInline) -> diff --git a/src/Compiler/TypedTree/TcGlobals.fs b/src/Compiler/TypedTree/TcGlobals.fs index ef6e00ffb16..6af6e0ea5f6 100644 --- a/src/Compiler/TypedTree/TcGlobals.fs +++ b/src/Compiler/TypedTree/TcGlobals.fs @@ -646,6 +646,18 @@ type TcGlobals( yield nleref.LastItemMangledName, ERefNonLocal nleref ] + let v_FSharpCoreForceInlineModules = + dict [ for nleref in [ fslib_MFIntrinsicFunctions_nleref + fslib_MFIntrinsicOperators_nleref + fslib_MFLanguagePrimitives_nleref + fslib_MFOperators_nleref + fslib_MFOperatorIntrinsics_nleref + fslib_MFOperatorsChecked_nleref + fslib_MFOperatorsUnchecked_nleref + fslib_MFNativePtrModule_nleref ] do + + yield nleref.LastItemMangledName, ERefNonLocal nleref ] + let tryDecodeTupleTy tupInfo l = match l with | [t1;t2;t3;t4;t5;t6;t7;markerTy] -> @@ -1133,6 +1145,8 @@ type TcGlobals( // better the job we do of mapping from provided expressions back to FSharp.Core F# functions and values. member _.knownFSharpCoreModules = v_knownFSharpCoreModules + member _.fslibForceInlineModules = v_FSharpCoreForceInlineModules + member _.compilingFSharpCore = compilingFSharpCore member _.useReflectionFreeCodeGen = useReflectionFreeCodeGen diff --git a/src/Compiler/TypedTree/TcGlobals.fsi b/src/Compiler/TypedTree/TcGlobals.fsi index e27bc1605a2..214ad0d17cd 100644 --- a/src/Compiler/TypedTree/TcGlobals.fsi +++ b/src/Compiler/TypedTree/TcGlobals.fsi @@ -698,6 +698,8 @@ type internal TcGlobals = member knownFSharpCoreModules: System.Collections.Generic.IDictionary + member fslibForceInlineModules: System.Collections.Generic.IDictionary + member knownIntrinsics: System.Collections.Concurrent.ConcurrentDictionary diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs index e85be18d47b..b85bf372fa6 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs @@ -158,8 +158,7 @@ let main _ = |> withNoOptimize |> asExe |> compileAndRun - |> verifyILContains ["call bool [FSharp.Core]Microsoft.FSharp.Core.Operators::Not(bool)"] - |> shouldSucceed + |> verifyILNotPresent ["call bool [FSharp.Core]Microsoft.FSharp.Core.Operators::Not(bool)"] [] let ``Call 10 - Different assembly`` () = From c689afd58fe4e6cfa8a2701b6a9f8729f507d3a8 Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Thu, 9 Apr 2026 17:07:13 +0200 Subject: [PATCH 08/35] Add more tests --- .../EmittedIL/DebugInlineAsCall.fs | 193 ++++++++++++++++++ 1 file changed, 193 insertions(+) diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs index b85bf372fa6..51d6f492120 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs @@ -413,3 +413,196 @@ let main _ = [ "call int32 Test::'__debug@5'(int32," "call float64 Test::'__debug@6-1'(float64," ] |> shouldSucceed + + [] + let ``SRTP 09 - Witness`` () = + FSharp """ +let check s (b1: 'a) (b2: 'a) = if b1 = b2 then () else failwith s + +let inline add (x: ^T) (y: ^T) = x + y + +[] +let main _ = + check "int" (add 3 4) 7 + check "float" (add 1.0 2.0) 3.0 + 0 +""" + |> withDebug + |> withNoOptimize + |> asExe + |> compileAndRun + |> shouldSucceed + + [] + let ``SRTP 10 - Witness`` () = + FSharp """ +type MyNum = + { Value: float } + static member FromFloat (_: MyNum) = fun (x: float) -> { Value = x } + +type T = + static member inline Invoke(x: float) : 'Num = + let inline call (a: ^a) = (^a: (static member FromFloat : _ -> _) a) + call Unchecked.defaultof<'Num> x + +[] +let main _ = + let result = T.Invoke(3.14) + if result.Value = 3.14 then 0 else 1 +""" + |> withDebug + |> withNoOptimize + |> asExe + |> compileAndRun + |> verifyILContains [ "call class Test/MyNum Test::'__debug@13'(float64)" ] + |> shouldSucceed + + [] + let ``SRTP 11 - Witness`` () = + FSharp """ +type MyNum = + { Value: float } + static member FromFloat (_: MyNum, _: T) = fun (x: float) -> { Value = x } + +and T = + { Dummy: int } + static member inline Invoke(x: float) : 'Num = + let inline call2 (a: ^a, b: ^b) = ((^a or ^b) : (static member FromFloat : _ * _ -> _) (b, a)) + let inline call (a: 'a) = fun (x: 'x) -> call2 (a, Unchecked.defaultof<'r>) x : 'r + call Unchecked.defaultof x + +[] +let main _ = + let result = T.Invoke(2.71) + if result.Value = 2.71 then 0 else 1 +""" + |> withDebug + |> withNoOptimize + |> asExe + |> compileAndRun + |> verifyILContains [ "call class Test/MyNum Test::'__debug@15'(float64)" ] + |> shouldSucceed + + + [] + let ``Member 01 - Non-generic`` () = + FSharp """ +type T() = + member inline _.Double(x: int) = x + x + +[] +let main _ = + let t = T() + let i = t.Double(5) + if i = 10 then 0 else 1 +""" + |> withDebug + |> withNoOptimize + |> asExe + |> compileAndRun + |> verifyILContains ["callvirt instance int32 Test/T::Double(int32)"] + |> shouldSucceed + + [] + let ``Member 02 - Generic`` () = + FSharp """ +type T() = + member inline _.Apply(f: 'a -> 'b, x: 'a) : 'b = f x + +[] +let main _ = + let t = T() + let i = t.Apply((fun x -> x + 1), 5) + if i = 6 then 0 else 1 +""" + |> withDebug + |> withNoOptimize + |> asExe + |> compileAndRun + |> verifyILContains ["callvirt instance !!1 Test/T::Apply(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,"] + |> shouldSucceed + + [] + let ``Member 03 - SRTP`` () = + FSharp """ +type T() = + member inline _.Add(x: ^T, y: ^T) = x + y + +[] +let main _ = + let t = T() + let i = t.Add(3, 4) + if i = 7 then 0 else 1 +""" + |> withDebug + |> withNoOptimize + |> asExe + |> compileAndRun + |> verifyILContains ["call int32 Test::'__debug@8'(class Test/T,"] + |> shouldSucceed + + [] + let ``Operator 01 - Top-level`` () = + FSharp """ +let inline (++) (x: int) (y: int) = x + y + 1 + +[] +let main _ = + let i = 3 ++ 4 + if i = 8 then 0 else 1 +""" + |> withDebug + |> withNoOptimize + |> asExe + |> compileAndRun + |> verifyILContains ["call int32 Test::op_PlusPlus(int32,"] + |> shouldSucceed + + [] + let ``Operator 02 - Top-level SRTP`` () = + FSharp """ +let inline (++) (x: ^T) (y: ^T) = x + y + +[] +let main _ = + let i = 3 ++ 4 + if i = 7 then 0 else 1 +""" + |> withDebug + |> withNoOptimize + |> asExe + |> compileAndRun + |> verifyILContains ["call int32 Test::'__debug@6'(int32,"] + |> shouldSucceed + + [] + let ``Operator 03 - Local`` () = + FSharp """ +[] +let main _ = + let inline (++) (x: int) (y: int) = x + y + 1 + let i = 3 ++ 4 + if i = 8 then 0 else 1 +""" + |> withDebug + |> withNoOptimize + |> asExe + |> compileAndRun + |> verifyILContains ["call !!0 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::InvokeFast(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>,"] + |> shouldSucceed + + [] + let ``Operator 04 - Local SRTP`` () = + FSharp """ +[] +let main _ = + let inline (++) (x: ^T) (y: ^T) = x + y + let i = 3 ++ 4 + if i = 7 then 0 else 1 +""" + |> withDebug + |> withNoOptimize + |> asExe + |> compileAndRun + |> verifyILContains ["call int32 Test::'__debug@5'(int32,"] + |> shouldSucceed From f4af98fcb8140ff5d69ae015d3892a0214d4cbed Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Sat, 11 Apr 2026 10:03:23 +0200 Subject: [PATCH 09/35] More witness fixes --- src/Compiler/Optimize/Optimizer.fs | 5 +- .../EmittedIL/DebugInlineAsCall.fs | 55 +++++++++++++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/src/Compiler/Optimize/Optimizer.fs b/src/Compiler/Optimize/Optimizer.fs index 39aa5fc4d38..0ca64d982d7 100644 --- a/src/Compiler/Optimize/Optimizer.fs +++ b/src/Compiler/Optimize/Optimizer.fs @@ -3457,8 +3457,11 @@ and TryInlineApplication cenv env finfo (valExpr: Expr) (tyargs: TType list, arg let allTyargsAreConcrete = tyargs |> List.forall (fun t -> (freeInType CollectTyparsNoCaching t).FreeTypars.IsEmpty) + let allTyargsAreGeneric = + tyargs |> List.forall (fun t -> not (freeInType CollectTyparsNoCaching t).FreeTypars.IsEmpty) + let canCallDirectly = - hasNoTraits || (not allTyargsAreConcrete && vref.ValReprInfo.IsSome) + hasNoTraits || (allTyargsAreGeneric && vref.ValReprInfo.IsSome) if canCallDirectly then Some(mkApps g ((exprForValRef m vref, vref.Type), [tyargs], argsR, m), info) diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs index 51d6f492120..299232238b7 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs @@ -484,6 +484,61 @@ let main _ = |> shouldSucceed + [] + let ``SRTP 12 - Witness - Struct with partially resolved type args`` () = + FSharp """ +[] +type S = + member _.M() = () + +type T() = + member _.N() = () + +let inline f (a: ^A when ^A: (member M: unit -> unit)) (_b: ^B when ^B: (member N: unit -> unit)) = + (^A: (member M: unit -> unit) a) + +let inline g b = f (S()) b + +[] +let main _ = + g (T()) + 0 +""" + |> withDebug + |> withNoOptimize + |> asExe + |> compileAndRun + |> shouldSucceed + + [] + let ``SRTP 13 - Witness - Struct with ResumableCode and partially resolved type args`` () = + FSharp """ +open Microsoft.FSharp.Core.CompilerServices + +[] +type S = member this.Foo() = () + +type D = member _.Bar() = true + +let inline f (x: ^A) = + ResumableCode< ^B, _>(fun sm -> + (^A: (member Foo: unit -> unit) x) + (^B: (member Bar: unit -> bool) sm.Data) + ) + +let inline g () = f (S()) + +[] +let main _ = + let _ : ResumableCode = g () + 0 +""" + |> withDebug + |> withNoOptimize + |> asExe + |> compileAndRun + |> shouldSucceed + [] let ``Member 01 - Non-generic`` () = FSharp """ From 4630833a1f821b8bd31c55fe9a410dd0930bd171 Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Fri, 10 Apr 2026 17:27:50 +0200 Subject: [PATCH 10/35] Don't check accessibility for non-inlined functions --- src/Compiler/Optimize/Optimizer.fs | 31 +++++++++--------- .../EmittedIL/DebugInlineAsCall.fs | 32 +++++++++++++++++++ 2 files changed, 48 insertions(+), 15 deletions(-) diff --git a/src/Compiler/Optimize/Optimizer.fs b/src/Compiler/Optimize/Optimizer.fs index 0ca64d982d7..4d035ade8bd 100644 --- a/src/Compiler/Optimize/Optimizer.fs +++ b/src/Compiler/Optimize/Optimizer.fs @@ -506,8 +506,9 @@ let CheckInlineValueIsComplete (v: Val) res = errorR(Error(FSComp.SR.optValueMarkedInlineButIncomplete(v.DisplayName), v.Range)) //System.Diagnostics.Debug.Assert(false, sprintf "Break for incomplete inline value %s" v.DisplayName) -let check (vref: ValRef) (res: ValInfo) = - CheckInlineValueIsComplete vref.Deref res.ValExprInfo +let check (cenv: cenv) (vref: ValRef) (res: ValInfo) = + if cenv.settings.inlineNamedFunctions then + CheckInlineValueIsComplete vref.Deref res.ValExprInfo (vref, res) //------------------------------------------------------------------------- @@ -697,7 +698,7 @@ let GetInfoForVal cenv env m (vref: ValRef) = let GetInfoForValWithCheck cenv env m (vref: ValRef) = let res = GetInfoForVal cenv env m vref - check vref res |> ignore + check cenv vref res |> ignore res let IsPartialExpr cenv env m x = @@ -1331,7 +1332,7 @@ let CombineValueInfos einfos res = let CombineValueInfosUnknown einfos = CombineValueInfos einfos UnknownValue /// Hide information because of a signature -let AbstractLazyModulInfoByHiding isAssemblyBoundary mhi = +let AbstractLazyModulInfoByHiding isAssemblyBoundary (cenv: cenv) mhi = // The freevars and FreeTyvars can indicate if the non-public (hidden) items have been used. // Under those checks, the further hidden* checks may be subsumed (meaning, not required anymore). @@ -1406,7 +1407,7 @@ let AbstractLazyModulInfoByHiding isAssemblyBoundary mhi = ValInfos = ValInfos(ss.ValInfos.Entries |> Seq.filter (fun (vref, _) -> not (hiddenVal vref.Deref)) - |> Seq.map (fun (vref, e) -> check (* "its implementation uses a binding hidden by a signature" m *) vref (abstractValInfo e) )) } + |> Seq.map (fun (vref, e) -> check cenv vref (abstractValInfo e) )) } and abstractLazyModulInfo (ss: LazyModuleInfo) = ss.Force() |> abstractModulInfo |> notlazy @@ -1425,7 +1426,7 @@ let AbstractOptimizationInfoToEssentials = abstractLazyModulInfo /// Hide information because of a "let ... in ..." or "let rec ... in ... " -let AbstractExprInfoByVars (boundVars: Val list, boundTyVars) ivalue = +let AbstractExprInfoByVars (cenv: cenv) (boundVars: Val list, boundTyVars) ivalue = // Module and member bindings can be skipped when checking abstraction, since abstraction of these values has already been done when // we hit the end of the module and called AbstractLazyModulInfoByHiding. If we don't skip these then we end up quadratically retraversing // the inferred optimization data, i.e. at each binding all the way up a sequences of 'lets' in a module. @@ -1485,7 +1486,7 @@ let AbstractExprInfoByVars (boundVars: Val list, boundTyVars) ivalue = let rec abstractModulInfo ss = { ModuleOrNamespaceInfos = ss.ModuleOrNamespaceInfos |> NameMap.map (InterruptibleLazy.force >> abstractModulInfo >> notlazy) ValInfos = ss.ValInfos.Map (fun (vref, e) -> - check vref (abstractValInfo e) ) } + check cenv vref (abstractValInfo e)) } abstractExprInfo ivalue @@ -1525,9 +1526,9 @@ let RemapOptimizationInfo g tmenv = remapLazyModulInfo /// Hide information when a value is no longer visible -let AbstractAndRemapModulInfo g (repackage, hidden) info = +let AbstractAndRemapModulInfo g (cenv: cenv) (repackage, hidden) info = let mrpi = mkRepackageRemapping repackage - let info = info |> AbstractLazyModulInfoByHiding false hidden + let info = info |> AbstractLazyModulInfoByHiding false cenv hidden let info = info |> RemapOptimizationInfo g mrpi info @@ -2850,7 +2851,7 @@ and OptimizeLetRec cenv env (binds, bodyExpr, m) = let fvs = List.fold (fun acc x -> unionFreeVars acc (fst x |> freeInBindingRhs CollectLocals)) fvs0 bindsR SplitValuesByIsUsedOrHasEffect cenv (fun () -> fvs.FreeLocals) bindsR // Trim out any optimization info that involves escaping values - let evalueR = AbstractExprInfoByVars (vs, []) einfo.Info + let evalueR = AbstractExprInfoByVars cenv (vs, []) einfo.Info // REVIEW: size of constructing new closures - should probably add #freevars + #recfixups here let bodyExprR = Expr.LetRec (bindsRR, bodyExprR, m, Construct.NewFreeVarsCache()) let info = CombineValueInfos (einfo :: bindinfos) evalueR @@ -2926,7 +2927,7 @@ and OptimizeLinearExpr cenv env expr contf = Info = UnknownValue } else // On the way back up: Trim out any optimization info that involves escaping values on the way back up - let evalueR = AbstractExprInfoByVars ([bindR.Var], []) bodyInfo.Info + let evalueR = AbstractExprInfoByVars cenv ([bindR.Var], []) bodyInfo.Info // Preserve the debug points for eliminated bindings that have debug points. let bodyR = @@ -4101,7 +4102,7 @@ and OptimizeDecisionTreeTarget cenv env _m (TTarget(vs, expr, flags)) = let env = BindInternalValsToUnknown cenv vs env let exprR, einfo = OptimizeExpr cenv env expr let exprR, einfo = ConsiderSplitToMethod cenv.settings.abstractBigTargets cenv.settings.bigTargetSize cenv env (exprR, einfo) - let evalueR = AbstractExprInfoByVars (vs, []) einfo.Info + let evalueR = AbstractExprInfoByVars cenv (vs, []) einfo.Info TTarget(vs, exprR, flags), { TotalSize=einfo.TotalSize FunctionSize=einfo.FunctionSize @@ -4385,7 +4386,7 @@ and OptimizeModuleExprWithSig cenv env mty def = elimModuleDefn def - let info = AbstractAndRemapModulInfo g rpi info + let info = AbstractAndRemapModulInfo g cenv rpi info def, info @@ -4458,14 +4459,14 @@ and OptimizeImplFileInternal cenv env isIncrementalFragment hidden implFile = // This optimizes and builds minfo ignoring the signature let (defR, minfo), (_env, _bindInfosColl) = OptimizeModuleContents cenv (env, []) contents let hidden = ComputeImplementationHidingInfoAtAssemblyBoundary defR hidden - let minfo = AbstractLazyModulInfoByHiding false hidden minfo + let minfo = AbstractLazyModulInfoByHiding false cenv hidden minfo let env = BindValsInModuleOrNamespace cenv minfo env env, defR, minfo, hidden else // This optimizes and builds minfo w.r.t. the signature let mexprR, minfo = OptimizeModuleExprWithSig cenv env signature contents let hidden = ComputeSignatureHidingInfoAtAssemblyBoundary signature hidden - let minfoExternal = AbstractLazyModulInfoByHiding true hidden minfo + let minfoExternal = AbstractLazyModulInfoByHiding true cenv hidden minfo let env = BindValsInModuleOrNamespace cenv minfo env env, mexprR, minfoExternal, hidden diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs index 299232238b7..ef0ac23b709 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs @@ -661,3 +661,35 @@ let main _ = |> compileAndRun |> verifyILContains ["call int32 Test::'__debug@5'(int32,"] |> shouldSucceed + + [] + let ``Accessibility 01`` () = + FSharp """ +module Module + +let inline internal fInternal () = () +let inline f () = fInternal () +""" + |> withDebug + |> withNoOptimize + |> asLibrary + |> compile + |> shouldSucceed + + [] + let ``Accessibility 02`` () = + FSharp """ +module Module + +type T() = + member inline internal this.InternalMethod() = + () + + member inline this.Method() = + this.InternalMethod() +""" + |> withDebug + |> withNoOptimize + |> asLibrary + |> compile + |> shouldSucceed \ No newline at end of file From e025208ff48db1ac0a790c3beb1dfa8d70f59317 Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Sun, 12 Apr 2026 17:10:51 +0200 Subject: [PATCH 11/35] Fix --- src/Compiler/CodeGen/IlxGen.fs | 11 +++- src/Compiler/CodeGen/IlxGen.fsi | 3 + src/Compiler/Driver/OptimizeInputs.fs | 3 + .../EmittedIL/DebugInlineAsCall.fs | 56 +++++++++++++++++++ 4 files changed, 71 insertions(+), 2 deletions(-) diff --git a/src/Compiler/CodeGen/IlxGen.fs b/src/Compiler/CodeGen/IlxGen.fs index 4675e8369bd..69326209de8 100644 --- a/src/Compiler/CodeGen/IlxGen.fs +++ b/src/Compiler/CodeGen/IlxGen.fs @@ -269,6 +269,8 @@ type IlxGenOptions = /// When set to true, the IlxGen will delay generation of method bodies and generated them later in parallel (parallelized across files) parallelIlxGenEnabled: bool + + inlineNamedFunctions: bool } /// Compilation environment for compiling a fragment of an assembly @@ -5693,8 +5695,13 @@ and GenTraitCall (cenv: cenv) cgbuf eenv (traitInfo: TraitConstraintInfo, argExp | None -> - // If witnesses are available, we should now always find trait witnesses in scope - assert not generateWitnesses + // When inlineNamedFunctions is true, all trait calls should be resolved via witnesses in scope. + // When inlineNamedFunctions is false, inline functions are kept as calls rather than inlined. + // Their witness arguments may contain TraitCall operations for constraints that were resolved + // without a witness (e.g., when the constraint is satisfied by a known concrete type). + // In such cases, generateWitnesses can be true (because other witnesses are in scope) but + // the specific trait's witness is not found. Fall through to the constraint solver to resolve it. + assert (not generateWitnesses || not cenv.options.inlineNamedFunctions) let exprOpt = CommitOperationResult(ConstraintSolver.CodegenWitnessExprForTraitConstraint cenv.tcVal g cenv.amap m traitInfo argExprs) diff --git a/src/Compiler/CodeGen/IlxGen.fsi b/src/Compiler/CodeGen/IlxGen.fsi index cd9dd0f2ffb..abf5320b697 100644 --- a/src/Compiler/CodeGen/IlxGen.fsi +++ b/src/Compiler/CodeGen/IlxGen.fsi @@ -61,6 +61,9 @@ type internal IlxGenOptions = /// When set to true, the IlxGen will delay generation of method bodies and generate them later in parallel (parallelized across files) parallelIlxGenEnabled: bool + + /// Indicates if inline named functions are being inlined or emitted as calls + inlineNamedFunctions: bool } /// The results of the ILX compilation of one fragment of an assembly diff --git a/src/Compiler/Driver/OptimizeInputs.fs b/src/Compiler/Driver/OptimizeInputs.fs index cace428af4d..81825929f3b 100644 --- a/src/Compiler/Driver/OptimizeInputs.fs +++ b/src/Compiler/Driver/OptimizeInputs.fs @@ -582,6 +582,9 @@ let GenerateIlxCode isInteractiveItExpr = isInteractiveItExpr alwaysCallVirt = tcConfig.alwaysCallVirt parallelIlxGenEnabled = tcConfig.parallelIlxGen + inlineNamedFunctions = + tcConfig.inlineNamedFunctions + |> Option.defaultValue (not tcConfig.debuginfo || tcConfig.optSettings.LocalOptimizationsEnabled) } ilxGenerator.GenerateCode(ilxGenOpts, optimizedImpls, topAttrs.assemblyAttrs, topAttrs.netModuleAttrs) diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs index ef0ac23b709..9869c9febdd 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs @@ -539,6 +539,62 @@ let main _ = |> compileAndRun |> shouldSucceed + [] + let ``SRTP 14 - StateMachine with unresolved trait from composed inline function`` () = + FSharp """ +open Microsoft.FSharp.Core.CompilerServices +open Microsoft.FSharp.Core.CompilerServices.StateMachineHelpers +open Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicOperators + +[] +type S<'T> = member _.M(_: 'T) = () + +let inline f<'A, 'R, 'B when 'A: (member M: int -> 'R) and 'B: (member M: 'R -> unit)> (_a: 'A) : 'B = Unchecked.defaultof<_> + +let inline g (_: S<'T>) = + if __useResumableCode then + __stateMachine, int> + (MoveNextMethodImpl<_>(fun _ -> ())) + (SetStateMachineMethodImpl<_>(fun _ _ -> ())) + (AfterCode<_, _>(fun _ -> 0)) + else 0 + +let inline h a = g (f a) + +[] +let main _ = + let _ = h (S()) + 0 +""" + |> withDebug + |> withNoOptimize + |> asExe + |> compileAndRun + |> shouldSucceed + + [] + let ``SRTP 15 - Composed inline with linked constraints`` () = + FSharp """ +[] +type S<'T> = member _.M(_: 'T) = () + +let inline f<'A, 'R, 'B when 'A: (member M: int -> 'R) and 'B: (member M: 'R -> unit)> (_a: 'A) : 'B = Unchecked.defaultof<_> + +let inline g (_: S<'T>) = 42 + +let inline h a = g (f a) + +[] +let main _ = + let i = h (S()) + if i = 42 then 0 else 1 +""" + |> withDebug + |> withNoOptimize + |> asExe + |> compileAndRun + |> shouldSucceed + [] let ``Member 01 - Non-generic`` () = FSharp """ From 61b45a547eccedb7267238c50cfd67744dd240f2 Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Sun, 12 Apr 2026 19:37:33 +0200 Subject: [PATCH 12/35] Fix cross-file inline same collision --- src/Compiler/Optimize/Optimizer.fs | 6 ++ .../EmittedIL/DebugInlineAsCall.fs | 58 +++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/src/Compiler/Optimize/Optimizer.fs b/src/Compiler/Optimize/Optimizer.fs index 4d035ade8bd..66764a29819 100644 --- a/src/Compiler/Optimize/Optimizer.fs +++ b/src/Compiler/Optimize/Optimizer.fs @@ -3484,6 +3484,12 @@ and TryInlineApplication cenv env finfo (valExpr: Expr) (tyargs: TType list, arg let specLambdaR, _ = OptimizeExpr cenv { env with dontInline = Zset.add origLambdaId env.dontInline } specLambda specLambdaR + let specLambdaR = + match specLambdaR with + | Expr.Lambda(uniq, a, b, c, d, _, ty) -> Expr.Lambda(uniq, a, b, c, d, m, ty) + | Expr.TyLambda(uniq, a, b, _, ty) -> Expr.TyLambda(uniq, a, b, m, ty) + | _ -> specLambdaR + let debugVal = let name = $"<{vref.LogicalName}>__debug" // When tyargs have free type variables, omit ValReprInfo so IlxGen compiles this diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs index 9869c9febdd..4f814e9d7f6 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs @@ -595,6 +595,64 @@ let main _ = |> compileAndRun |> shouldSucceed + [] + let ``SRTP 16 - Same line`` () = + let additionalSource = FsSourceWithFileName "Program.fs" """ +module Program + +open Module + +let inline foo (a: 'a) = U.F(a, 0); fun () -> () + +[] +let main _ = + let _ = foo (T()) + 0 +""" + FSharpWithFileName "Module.fs" """ +module Module + +type T() = member _.M() = () + +type U = static member inline F<'a, 'b when 'a: (member M: unit -> unit)>(_a: 'a, _b: 'b) = () +""" + |> withAdditionalSourceFile additionalSource + |> withDebug + |> withNoOptimize + |> asExe + |> compileAndRun + |> shouldSucceed + + [] + let ``SRTP 17 - Same line`` () = + let library = + FSharp """ +module Module + +let inline add<'a, 'b, 'c when 'a: (static member (+): 'a * 'a -> 'b)> (x: 'a) (y: 'a) = + x + y +""" + |> withDebug + |> withNoOptimize + |> asLibrary + + FSharp """ +open Module + +let inline foo x y = add x y |> ignore; fun () -> () + +[] +let main _ = + let _ = foo 1 2 + 0 +""" + |> withDebug + |> withNoOptimize + |> withReferences [library] + |> asExe + |> compileAndRun + |> shouldSucceed + [] let ``Member 01 - Non-generic`` () = FSharp """ From abdb60aded3b78f3b2d799c586cfcfe90bafc645 Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Sun, 12 Apr 2026 22:06:25 +0200 Subject: [PATCH 13/35] More SRTP --- src/Compiler/CodeGen/IlxGen.fs | 12 ++++++++ .../EmittedIL/DebugInlineAsCall.fs | 30 +++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/src/Compiler/CodeGen/IlxGen.fs b/src/Compiler/CodeGen/IlxGen.fs index 69326209de8..5644997953d 100644 --- a/src/Compiler/CodeGen/IlxGen.fs +++ b/src/Compiler/CodeGen/IlxGen.fs @@ -7208,6 +7208,18 @@ and GetIlxClosureFreeVars cenv m (thisVars: ValRef list) boxity eenv takenNames let cloFreeTyvars = cloFreeTyvars.FreeTypars |> Zset.elements + // When generating witnesses, witness types may reference type variables that appear + // only in SRTP constraints of the captured type variables (e.g. 'b in 'a : (member M: unit -> 'b)). + // Include those so they are available when generating witness field types. + let cloFreeTyvars = + if ComputeGenerateWitnesses g eenv then + let extra = + GetTraitWitnessInfosOfTypars g 0 cloFreeTyvars + |> List.collect (fun w -> (freeInType CollectTyparsNoCaching (GenWitnessTy g w)).FreeTypars |> Zset.elements) + (cloFreeTyvars @ extra) |> List.distinctBy (fun tp -> tp.Stamp) + else + cloFreeTyvars + let eenvinner = eenv |> EnvForTypars cloFreeTyvars let ilCloTyInner = diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs index 4f814e9d7f6..69a4df4a23a 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs @@ -653,6 +653,36 @@ let main _ = |> compileAndRun |> shouldSucceed + [] + let ``SRTP 18 - Type abbreviation with constraint`` () = + let additionalSource = FsSourceWithFileName "Program.fs" """ +module Program + +open Module + +type T() = member _.M() = 42 + +let inline foo (a: 'a) = C.F(a); fun () -> () + +[] +let main _ = + let _ = foo (T()) + 0 +""" + FSharpWithFileName "Module.fs" """ +module Module + +type C<'a, 'b when 'a: (member M: unit -> 'b)> = 'a + +type C = static member inline F<'a, 'b, 'c when C<'a, 'b>>(_a: 'a) = () +""" + |> withAdditionalSourceFile additionalSource + |> withDebug + |> withNoOptimize + |> asExe + |> compileAndRun + |> shouldSucceed + [] let ``Member 01 - Non-generic`` () = FSharp """ From 894e597426f7063a59efb58dadace8e24b356f4f Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Mon, 13 Apr 2026 12:30:20 +0200 Subject: [PATCH 14/35] Accessibility --- src/Compiler/Optimize/Optimizer.fs | 121 +++++++++--------- .../EmittedIL/DebugInlineAsCall.fs | 94 +++++++++++++- 2 files changed, 156 insertions(+), 59 deletions(-) diff --git a/src/Compiler/Optimize/Optimizer.fs b/src/Compiler/Optimize/Optimizer.fs index 66764a29819..1a5e66974d2 100644 --- a/src/Compiler/Optimize/Optimizer.fs +++ b/src/Compiler/Optimize/Optimizer.fs @@ -1358,8 +1358,9 @@ let AbstractLazyModulInfoByHiding isAssemblyBoundary (cenv: cenv) mhi = then detailR else ValValue (vref2, detailR) - // Check for escape in lambda - | CurriedLambdaValue (_, _, _, expr, _) | ConstExprValue(_, expr) when + // Check for escape in lambda + | CurriedLambdaValue (_, _, _, expr, _) | ConstExprValue(_, expr) when + cenv.settings.inlineNamedFunctions && (let fvs = freeInExpr CollectAll expr (isAssemblyBoundary && not (freeVarsAllPublic fvs)) || Zset.exists hiddenVal fvs.FreeLocals || @@ -1406,7 +1407,9 @@ let AbstractLazyModulInfoByHiding isAssemblyBoundary (cenv: cenv) mhi = { ModuleOrNamespaceInfos = NameMap.map abstractLazyModulInfo ss.ModuleOrNamespaceInfos ValInfos = ValInfos(ss.ValInfos.Entries - |> Seq.filter (fun (vref, _) -> not (hiddenVal vref.Deref)) + |> Seq.filter (fun (vref, _) -> + not (hiddenVal vref.Deref) || + (not cenv.settings.inlineNamedFunctions && vref.Deref.ShouldInline)) |> Seq.map (fun (vref, e) -> check cenv vref (abstractValInfo e) )) } and abstractLazyModulInfo (ss: LazyModuleInfo) = @@ -3104,7 +3107,8 @@ and TryOptimizeVal cenv env (vOpt: ValRef option, shouldInline, inlineIfLambda, failwith "tuple, union and record values cannot be marked 'inline'" | UnknownValue when shouldInline -> - warning(Error(FSComp.SR.optValueMarkedInlineHasUnexpectedValue(), m)) + if cenv.settings.inlineNamedFunctions then + warning(Error(FSComp.SR.optValueMarkedInlineHasUnexpectedValue(), m)) None | _ when shouldInline -> @@ -3153,7 +3157,7 @@ and OptimizeVal cenv env expr (v: ValRef, m) = e, AddValEqualityInfo g m v einfo | None -> - if v.ShouldInline then + if v.ShouldInline && cenv.settings.inlineNamedFunctions then match valInfoForVal.ValExprInfo with | UnknownValue -> error(Error(FSComp.SR.optFailedToInlineValue(v.DisplayName), m)) | _ -> warning(Error(FSComp.SR.optFailedToInlineValue(v.DisplayName), m)) @@ -3445,67 +3449,68 @@ and TryInlineApplication cenv env finfo (valExpr: Expr) (tyargs: TType list, arg match cenv.settings.inlineNamedFunctions, stripExpr valExpr with | false, Expr.Val(vref, _, _) when vref.ShouldInline && not (shouldForceInlineInDebug cenv.g vref) -> - let origFinfo = GetInfoForValWithCheck cenv env m vref - match stripValue origFinfo.ValExprInfo with - | CurriedLambdaValue(origLambdaId, _, _, origLambda, origLambdaTy) when not (Zset.contains origLambdaId env.dontInline) -> - let argsR = args |> List.map (OptimizeExpr cenv env >> fst) - let info = { TotalSize = 1; FunctionSize = 1; HasEffect = true; MightMakeCriticalTailcall = false; Info = UnknownValue } + let hasNoTraits = + let tps, _ = tryDestForallTy g vref.Type + GetTraitConstraintInfosOfTypars g tps |> List.isEmpty - let hasNoTraits = - let tps, _ = tryDestForallTy g vref.Type - GetTraitConstraintInfosOfTypars g tps |> List.isEmpty + let allTyargsAreConcrete = + tyargs |> List.forall (fun t -> (freeInType CollectTyparsNoCaching t).FreeTypars.IsEmpty) - let allTyargsAreConcrete = - tyargs |> List.forall (fun t -> (freeInType CollectTyparsNoCaching t).FreeTypars.IsEmpty) + let allTyargsAreGeneric = + tyargs |> List.forall (fun t -> not (freeInType CollectTyparsNoCaching t).FreeTypars.IsEmpty) - let allTyargsAreGeneric = - tyargs |> List.forall (fun t -> not (freeInType CollectTyparsNoCaching t).FreeTypars.IsEmpty) + let canCallDirectly = + hasNoTraits || (allTyargsAreGeneric && vref.ValReprInfo.IsSome) - let canCallDirectly = - hasNoTraits || (allTyargsAreGeneric && vref.ValReprInfo.IsSome) + let argsR = args |> List.map (OptimizeExpr cenv env >> fst) + let info = { TotalSize = 1; FunctionSize = 1; HasEffect = true; MightMakeCriticalTailcall = false; Info = UnknownValue } - if canCallDirectly then - Some(mkApps g ((exprForValRef m vref, vref.Type), [tyargs], argsR, m), info) - else - let f2R = CopyExprForInlining cenv true origLambda m - let specLambda = MakeApplicationAndBetaReduce g (f2R, origLambdaTy, [tyargs], [], m) - let specLambdaTy = tyOfExpr g specLambda + if canCallDirectly then + Some(mkApps g ((exprForValRef m vref, vref.Type), [tyargs], argsR, m), info) + else - let specLambdaR = + let origFinfo = GetInfoForValWithCheck cenv env m vref + match stripValue origFinfo.ValExprInfo with + | CurriedLambdaValue(origLambdaId, _, _, origLambda, origLambdaTy) when not (Zset.contains origLambdaId env.dontInline) -> + let f2R = CopyExprForInlining cenv true origLambda m + let specLambda = MakeApplicationAndBetaReduce g (f2R, origLambdaTy, [tyargs], [], m) + let specLambdaTy = tyOfExpr g specLambda + + let specLambdaR = + if allTyargsAreConcrete then + match cenv.specializedInlineVals.FindAll(origLambdaId) |> List.tryFind (fun (ty, _) -> typeEquiv g ty specLambdaTy) with + | Some (_, body) -> copyExpr g CloneAll body + | None -> + + let specLambdaR, _ = OptimizeExpr cenv { env with dontInline = Zset.add origLambdaId env.dontInline } specLambda + cenv.specializedInlineVals.Add(origLambdaId, (specLambdaTy, specLambdaR)) + specLambdaR + else + let specLambdaR, _ = OptimizeExpr cenv { env with dontInline = Zset.add origLambdaId env.dontInline } specLambda + specLambdaR + + let specLambdaR = + match specLambdaR with + | Expr.Lambda(uniq, a, b, c, d, _, ty) -> Expr.Lambda(uniq, a, b, c, d, m, ty) + | Expr.TyLambda(uniq, a, b, _, ty) -> Expr.TyLambda(uniq, a, b, m, ty) + | _ -> specLambdaR + + let debugVal = + let name = $"<{vref.LogicalName}>__debug" + // When tyargs have free type variables, omit ValReprInfo so IlxGen compiles this + // as a closure that captures type variables and witnesses from the enclosing scope. + let valReprInfo = if allTyargsAreConcrete then - match cenv.specializedInlineVals.FindAll(origLambdaId) |> List.tryFind (fun (ty, _) -> typeEquiv g ty specLambdaTy) with - | Some (_, body) -> copyExpr g CloneAll body - | None -> - - let specLambdaR, _ = OptimizeExpr cenv { env with dontInline = Zset.add origLambdaId env.dontInline } specLambda - cenv.specializedInlineVals.Add(origLambdaId, (specLambdaTy, specLambdaR)) - specLambdaR + Some(InferValReprInfoOfExpr g AllowTypeDirectedDetupling.No specLambdaTy [] [] specLambdaR) else - let specLambdaR, _ = OptimizeExpr cenv { env with dontInline = Zset.add origLambdaId env.dontInline } specLambda - specLambdaR - - let specLambdaR = - match specLambdaR with - | Expr.Lambda(uniq, a, b, c, d, _, ty) -> Expr.Lambda(uniq, a, b, c, d, m, ty) - | Expr.TyLambda(uniq, a, b, _, ty) -> Expr.TyLambda(uniq, a, b, m, ty) - | _ -> specLambdaR - - let debugVal = - let name = $"<{vref.LogicalName}>__debug" - // When tyargs have free type variables, omit ValReprInfo so IlxGen compiles this - // as a closure that captures type variables and witnesses from the enclosing scope. - let valReprInfo = - if allTyargsAreConcrete then - Some(InferValReprInfoOfExpr g AllowTypeDirectedDetupling.No specLambdaTy [] [] specLambdaR) - else - None - - Construct.NewVal(name, m, None, specLambdaTy, Immutable, true, valReprInfo, taccessPublic, ValNotInRecScope, None, - NormalVal, [], ValInline.InlinedDefinition, XmlDoc.Empty, false, false, false, false, false, false, None, - ParentNone) - - let callExpr = mkApps g ((exprForVal m debugVal, specLambdaTy), [], argsR, m) - Some(mkCompGenLet m debugVal specLambdaR callExpr, info) + None + + Construct.NewVal(name, m, None, specLambdaTy, Immutable, true, valReprInfo, taccessPublic, ValNotInRecScope, None, + NormalVal, [], ValInline.InlinedDefinition, XmlDoc.Empty, false, false, false, false, false, false, None, + ParentNone) + + let callExpr = mkApps g ((exprForVal m debugVal, specLambdaTy), [], argsR, m) + Some(mkCompGenLet m debugVal specLambdaR callExpr, info) | _ -> None | _ -> diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs index 69a4df4a23a..342ac0f8a89 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs @@ -836,4 +836,96 @@ type T() = |> withNoOptimize |> asLibrary |> compile - |> shouldSucceed \ No newline at end of file + |> shouldSucceed + + [] + let ``Accessibility 03`` () = + let library = + FSharp """ +module Lib + +type T() = + member inline internal _.F(x) = x + member inline this.G(x) = this.F(x) +""" + |> withDebug + |> withNoOptimize + |> asLibrary + |> withName "lib" + + FSharp """ +module App +let r = Lib.T().G(1) +""" + |> withDebug + |> withNoOptimize + |> withReferences [library] + |> compile + |> shouldSucceed + + + [] + let ``Accessibility 04`` () = + let library = + FSharp """ +module MyLib + +let inline internal addInternal (x: ^T) (y: ^T) = x + y +let inline addPublic (x: ^T) (y: ^T) = addInternal x y +""" + |> withDebug + |> withNoOptimize + |> asLibrary + + FSharp """ +open MyLib + +[] +let main _ = + let i = addPublic 3 4 + if i = 7 then 0 else 1 +""" + |> withDebug + |> withNoOptimize + |> withReferences [library] + |> asExe + |> compileAndRun + |> shouldSucceed + + [] + let ``Accessibility 05`` () = + let library = + FSharp """ +module Module + +type MyNum = + { Value: float } + static member FromFloat (_: MyNum) = fun (x: float) -> { Value = x } + +type T = + static member inline internal InvokeInternal(x: float) : 'Num = + let inline call (a: ^a) = (^a: (static member FromFloat : _ -> _) a) + call Unchecked.defaultof<'Num> x + + static member inline Invoke(x: float) : 'Num = + T.InvokeInternal<'Num>(x) +""" + |> withDebug + |> withNoOptimize + |> asLibrary + |> withName "Library" + + FSharp """ +open Module + +[] +let main _ = + let result = T.Invoke(3.14) + if result.Value = 3.14 then 0 else 1 +""" + |> withDebug + |> withNoOptimize + |> withReferences [library] + |> asExe + |> compileAndRun + |> shouldSucceed From 4d6d3ccf2c207a5f87876c082830523714c2a538 Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Mon, 13 Apr 2026 12:54:19 +0200 Subject: [PATCH 15/35] Fantomas --- src/Compiler/CodeGen/IlxGen.fs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Compiler/CodeGen/IlxGen.fs b/src/Compiler/CodeGen/IlxGen.fs index 5644997953d..58c6ef08ee4 100644 --- a/src/Compiler/CodeGen/IlxGen.fs +++ b/src/Compiler/CodeGen/IlxGen.fs @@ -7215,7 +7215,10 @@ and GetIlxClosureFreeVars cenv m (thisVars: ValRef list) boxity eenv takenNames if ComputeGenerateWitnesses g eenv then let extra = GetTraitWitnessInfosOfTypars g 0 cloFreeTyvars - |> List.collect (fun w -> (freeInType CollectTyparsNoCaching (GenWitnessTy g w)).FreeTypars |> Zset.elements) + |> List.collect (fun w -> + (freeInType CollectTyparsNoCaching (GenWitnessTy g w)).FreeTypars + |> Zset.elements) + (cloFreeTyvars @ extra) |> List.distinctBy (fun tp -> tp.Stamp) else cloFreeTyvars From 4f4c8d95bbb6163ce40f2cf11b6719fd47b45b13 Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Mon, 13 Apr 2026 16:37:40 +0200 Subject: [PATCH 16/35] Inline when extra optimization loops --- src/Compiler/Driver/CompilerConfig.fs | 10 +++++++++- src/Compiler/Driver/CompilerConfig.fsi | 2 +- src/Compiler/Driver/OptimizeInputs.fs | 9 ++------- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/Compiler/Driver/CompilerConfig.fs b/src/Compiler/Driver/CompilerConfig.fs index 6075a7a32a7..ed8d7914497 100644 --- a/src/Compiler/Driver/CompilerConfig.fs +++ b/src/Compiler/Driver/CompilerConfig.fs @@ -1256,7 +1256,15 @@ type TcConfig private (data: TcConfigBuilder, validate: bool) = member _.fsiMultiAssemblyEmit = data.fsiMultiAssemblyEmit member _.FxResolver = data.FxResolver member _.strictIndentation = data.strictIndentation - member _.inlineNamedFunctions = data.inlineNamedFunctions + + member _.inlineNamedFunctions = + data.inlineNamedFunctions + |> Option.defaultValue ( + not data.debuginfo + || data.optSettings.LocalOptimizationsEnabled + || data.extraOptimizationIterations > 0 + ) + member _.primaryAssembly = data.primaryAssembly member _.noFeedback = data.noFeedback member _.stackReserveSize = data.stackReserveSize diff --git a/src/Compiler/Driver/CompilerConfig.fsi b/src/Compiler/Driver/CompilerConfig.fsi index 85ce24133a6..b81a37917c5 100644 --- a/src/Compiler/Driver/CompilerConfig.fsi +++ b/src/Compiler/Driver/CompilerConfig.fsi @@ -816,7 +816,7 @@ type TcConfig = member strictIndentation: bool option - member inlineNamedFunctions: bool option + member inlineNamedFunctions: bool member GetTargetFrameworkDirectories: unit -> string list diff --git a/src/Compiler/Driver/OptimizeInputs.fs b/src/Compiler/Driver/OptimizeInputs.fs index 81825929f3b..120285358a3 100644 --- a/src/Compiler/Driver/OptimizeInputs.fs +++ b/src/Compiler/Driver/OptimizeInputs.fs @@ -327,9 +327,7 @@ let ApplyAllOptimizations // Only do abstractBigTargets in the first phase, and only when TLR is on. abstractBigTargets = tcConfig.doTLR reportingPhase = true - inlineNamedFunctions = - tcConfig.inlineNamedFunctions - |> Option.defaultValue (not tcConfig.debuginfo || tcConfig.optSettings.LocalOptimizationsEnabled) + inlineNamedFunctions = tcConfig.inlineNamedFunctions } // Only do these two steps in the first phase. @@ -337,7 +335,6 @@ let ApplyAllOptimizations { firstLoopSettings with abstractBigTargets = false reportingPhase = false - inlineNamedFunctions = false } let addPhaseDiagnostics (f: PhaseFunc) (info: Phase) = @@ -582,9 +579,7 @@ let GenerateIlxCode isInteractiveItExpr = isInteractiveItExpr alwaysCallVirt = tcConfig.alwaysCallVirt parallelIlxGenEnabled = tcConfig.parallelIlxGen - inlineNamedFunctions = - tcConfig.inlineNamedFunctions - |> Option.defaultValue (not tcConfig.debuginfo || tcConfig.optSettings.LocalOptimizationsEnabled) + inlineNamedFunctions = tcConfig.inlineNamedFunctions } ilxGenerator.GenerateCode(ilxGenOpts, optimizedImpls, topAttrs.assemblyAttrs, topAttrs.netModuleAttrs) From a6d242e7f1c773d049b0587fd2a5ac4a9a1f0043 Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Mon, 13 Apr 2026 17:13:50 +0200 Subject: [PATCH 17/35] Specialize signature-hidden values --- src/Compiler/Optimize/Optimizer.fs | 27 +++++-- .../EmittedIL/DebugInlineAsCall.fs | 80 +++++++++++++++++++ 2 files changed, 101 insertions(+), 6 deletions(-) diff --git a/src/Compiler/Optimize/Optimizer.fs b/src/Compiler/Optimize/Optimizer.fs index 1a5e66974d2..4c8470c53c2 100644 --- a/src/Compiler/Optimize/Optimizer.fs +++ b/src/Compiler/Optimize/Optimizer.fs @@ -438,6 +438,8 @@ type cenv = realsig: bool specializedInlineVals: HashMultiMap + + signatureHidingInfo: SignatureHidingInfo } override x.ToString() = "" @@ -3459,8 +3461,14 @@ and TryInlineApplication cenv env finfo (valExpr: Expr) (tyargs: TType list, arg let allTyargsAreGeneric = tyargs |> List.forall (fun t -> not (freeInType CollectTyparsNoCaching t).FreeTypars.IsEmpty) + // When inside an inline function body being prepared for export (!cenv.optimizing), + // only emit a direct call if the callee is publicly accessible. Non-public vals + // (e.g. in internal modules, or hidden by .fsi) can't be called by consumers, + // so route those through the specialization path which inlines the body. + let isHiddenBySignature = cenv.signatureHidingInfo.HiddenVals.Contains vref.Deref let canCallDirectly = - hasNoTraits || (allTyargsAreGeneric && vref.ValReprInfo.IsSome) + (cenv.optimizing || (vref.Accessibility.IsPublic && not isHiddenBySignature)) && + (hasNoTraits || (allTyargsAreGeneric && vref.ValReprInfo.IsSome)) let argsR = args |> List.map (OptimizeExpr cenv env >> fst) let info = { TotalSize = 1; FunctionSize = 1; HasEffect = true; MightMakeCriticalTailcall = false; Info = UnknownValue } @@ -4324,17 +4332,23 @@ and OptimizeBindings cenv isRec env xs = and OptimizeModuleExprWithSig cenv env mty def = let g = cenv.g - // Optimize the module implementation - let (def, info), (_env, bindInfosColl) = OptimizeModuleContents cenv (env, []) def - let bindInfosColl = List.concat bindInfosColl - + // Compute the elements truly hidden by the module signature. // The hidden set here must contain NOT MORE THAN the set of values made inaccessible by // the application of the signature. If it contains extra elements we'll accidentally eliminate // bindings. - + // This only walks structural elements (Val/Entity declarations), not expressions, + // so it gives the same result before and after optimization. let _renaming, hidden as rpi = ComputeRemappingFromImplementationToSignature g def mty + // Make hiding info available during optimization so TryInlineApplication + // can avoid emitting direct calls to vals hidden by signature. + let cenv = { cenv with signatureHidingInfo = hidden } + + // Optimize the module implementation + let (def, info), (_env, bindInfosColl) = OptimizeModuleContents cenv (env, []) def + let bindInfosColl = List.concat bindInfosColl + let def = if not cenv.settings.LocalOptimizationsEnabled then def else @@ -4500,6 +4514,7 @@ let OptimizeImplFile (settings, ccu, tcGlobals, tcVal, importMap, optEnv, isIncr stackGuard = StackGuard("OptimizerStackGuardDepth") realsig = tcGlobals.realsig specializedInlineVals = HashMultiMap(HashIdentity.Structural, true) + signatureHidingInfo = SignatureHidingInfo.Empty } let env, _, _, _ as results = OptimizeImplFileInternal cenv optEnv isIncrementalFragment hidden mimpls diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs index 342ac0f8a89..dcfb2f90295 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs @@ -922,6 +922,86 @@ open Module let main _ = let result = T.Invoke(3.14) if result.Value = 3.14 then 0 else 1 +""" + |> withDebug + |> withNoOptimize + |> withReferences [library] + |> asExe + |> compileAndRun + |> shouldSucceed + + [] + let ``Accessibility 06`` () = + let impl = + FsSource """ +module Lib + +module internal Impl = + let inline implFn (x: int) = + x * x + +let inline publicFn (x: int) = + Impl.implFn x + 1 +""" + let fsi = Fsi """ +module Lib + +val inline publicFn: x: int -> int +""" + let library = + fsi + |> withAdditionalSourceFile impl + |> withDebug + |> withNoOptimize + |> asLibrary + + FSharp """ +open Lib + +[] +let main _ = + let i = publicFn 3 + if i = 10 then 0 else 1 +""" + |> withDebug + |> withNoOptimize + |> withReferences [library] + |> asExe + |> compileAndRun + |> shouldSucceed + + [] + let ``Accessibility 07`` () = + let impl = + FsSource """ +module Lib + +module Impl = + let inline implFn (x: int) = + x * x + +let inline publicFn (x: int) = + Impl.implFn x + 1 +""" + let fsi = Fsi """ +module Lib + +val inline publicFn: x: int -> int +""" + let library = + fsi + |> withAdditionalSourceFile impl + |> withDebug + |> withNoOptimize + |> asLibrary + + FSharp """ +open Lib + +[] +let main _ = + let i = publicFn 3 + if i = 10 then 0 else 1 """ |> withDebug |> withNoOptimize From f1f6289a39f8a93bd33a20938f6da02d7ab9d72d Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Tue, 14 Apr 2026 12:59:48 +0200 Subject: [PATCH 18/35] Byref --- src/Compiler/Optimize/Optimizer.fs | 6 +- .../EmittedIL/DebugInlineAsCall.fs | 147 +++++++++++++++++- 2 files changed, 146 insertions(+), 7 deletions(-) diff --git a/src/Compiler/Optimize/Optimizer.fs b/src/Compiler/Optimize/Optimizer.fs index 4c8470c53c2..9f47f31c7e8 100644 --- a/src/Compiler/Optimize/Optimizer.fs +++ b/src/Compiler/Optimize/Optimizer.fs @@ -3509,7 +3509,11 @@ and TryInlineApplication cenv env finfo (valExpr: Expr) (tyargs: TType list, arg // as a closure that captures type variables and witnesses from the enclosing scope. let valReprInfo = if allTyargsAreConcrete then - Some(InferValReprInfoOfExpr g AllowTypeDirectedDetupling.No specLambdaTy [] [] specLambdaR) + match vref.ValReprInfo with + | Some(ValReprInfo(_, argInfos, retInfo)) -> + Some(ValReprInfo([], argInfos, retInfo)) + | None -> + Some(InferValReprInfoOfExpr g AllowTypeDirectedDetupling.No specLambdaTy [] [] specLambdaR) else None diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs index dcfb2f90295..36de5f4536f 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs @@ -171,7 +171,7 @@ let inline triple (x: int) = x + x + x |> withDebug |> withNoOptimize |> asLibrary - |> withName "mylib" + |> withName "Lib" FSharp """ open MyLib @@ -186,7 +186,7 @@ let main _ = |> withReferences [library] |> asExe |> compileAndRun - |> verifyILContains ["call int32 [mylib]MyLib::triple(int32)"] + |> verifyILContains ["call int32 [Lib]MyLib::triple(int32)"] |> shouldSucceed [] @@ -230,6 +230,51 @@ let main _ = "callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0)" ] |> shouldSucceed + [] + let ``Call 13`` () = + FSharp """ +[] +let inline f x = x + 1 + +let inline g x = f x + +g 1 |> ignore +""" + |> withDebug + |> withNoOptimize + |> asExe + |> compileAndRun + + [] + let ``Call 14`` () = + FSharp """ +[] +let inline f x = x + 1 + +let inline g (x: ^T) (y: ^T) = f (x + y) + +g 1 2 |> ignore +""" + |> withDebug + |> withNoOptimize + |> asExe + |> compileAndRun + + [] + let ``Call 15`` () = + FSharp """ +[] +let inline f (x: ^T) = x + +let inline g (x: ^T) (y: ^T) = f (x + y) + +g 1 2 |> ignore +""" + |> withDebug + |> withNoOptimize + |> asExe + |> compileAndRun + [] let ``SRTP 01`` () = FSharp """ @@ -316,7 +361,6 @@ let inline add (x: ^T) (y: ^T) = x + y |> withDebug |> withNoOptimize |> asLibrary - |> withName "mylib2" FSharp """ open MyLib @@ -345,7 +389,6 @@ let inline add (x: ^T) (y: ^T) = x + y |> withDebug |> withNoOptimize |> asLibrary - |> withName "mylib3" FSharp """ open MyLib @@ -683,6 +726,100 @@ type C = static member inline F<'a, 'b, 'c when C<'a, 'b>>(_a: 'a) = () |> compileAndRun |> shouldSucceed + [] + let ``SRTP 19 - byref`` () = + FSharp """ +let inline f<'T, 'U when 'T: (member M: byref<'U> -> unit)> (x: byref<'T>, y: byref<'U>) = + x.M(&y) + +[] +type S = + member _.M(x: byref) = x <- 42 + +[] +let main _ = + let mutable s = S() + let mutable v = 0 + f(&s, &v) + if v = 42 then 0 else 1 +""" + |> withDebug + |> withNoOptimize + |> asExe + |> compileAndRun + |> shouldSucceed + + [] + let ``SRTP 20 - byref`` () = + let library = + FSharp """ +module MyLib + +let inline f<'T, 'U when 'T: (member M: byref<'U> -> unit)> (x: byref<'T>, y: byref<'U>) = + x.M(&y) +""" + |> withDebug + |> withNoOptimize + |> asLibrary + + FSharp """ +open MyLib + +[] +type S = + member _.M(x: byref) = x <- 42 + +[] +let main _ = + let mutable s = S() + let mutable v = 0 + f(&s, &v) + if v = 42 then 0 else 1 +""" + |> withDebug + |> withNoOptimize + |> withReferences [library] + |> asExe + |> compileAndRun + |> shouldSucceed + + [] + let ``SRTP 21 - byref`` () = + let library = + FSharp """ +module MyLib + +let inline f<'T, 'U when 'T: (member M: byref<'U> -> unit)> (x: byref<'T>, y: byref<'U>) = + x.M(&y) + +let inline g<'T, 'U when 'T: (member M: byref<'U> -> unit)> (x: byref<'T>, y: byref<'U>) = + f(&x, &y) +""" + |> withDebug + |> withNoOptimize + |> asLibrary + + FSharp """ +open MyLib + +[] +type S = + member _.M(x: byref) = x <- 42 + +[] +let main _ = + let mutable s = S() + let mutable v = 0 + g(&s, &v) + if v = 42 then 0 else 1 +""" + |> withDebug + |> withNoOptimize + |> withReferences [library] + |> asExe + |> compileAndRun + |> shouldSucceed + [] let ``Member 01 - Non-generic`` () = FSharp """ @@ -851,7 +988,6 @@ type T() = |> withDebug |> withNoOptimize |> asLibrary - |> withName "lib" FSharp """ module App @@ -913,7 +1049,6 @@ type T = |> withDebug |> withNoOptimize |> asLibrary - |> withName "Library" FSharp """ open Module From a74bc4de3891736d6b0e1b83d4586765004752b7 Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Tue, 14 Apr 2026 15:09:27 +0200 Subject: [PATCH 19/35] Add more tests --- .../EmittedIL/DebugInlineAsCall.fs | 96 +++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs index 36de5f4536f..d2a90331e4f 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs @@ -244,6 +244,9 @@ g 1 |> ignore |> withNoOptimize |> asExe |> compileAndRun + |> verifyILContains ["call int32 Test::g(int32)"] + |> shouldSucceed + |> verifyILNotPresent ["Test::'__debug"] [] let ``Call 14`` () = @@ -259,6 +262,9 @@ g 1 2 |> ignore |> withNoOptimize |> asExe |> compileAndRun + |> verifyILContains ["call int32 Test::'__debug@7'(int32,"] + |> shouldSucceed + |> verifyILNotPresent ["Test::'__debug"] [] let ``Call 15`` () = @@ -274,6 +280,9 @@ g 1 2 |> ignore |> withNoOptimize |> asExe |> compileAndRun + |> verifyILContains ["call int32 Test::'__debug@7'(int32,"] + |> shouldSucceed + |> verifyILNotPresent ["Test::'__debug"] [] let ``SRTP 01`` () = @@ -474,6 +483,9 @@ let main _ = |> withNoOptimize |> asExe |> compileAndRun + |> verifyILContains + [ "call int32 Test::'__debug@8'(int32," + "call float64 Test::'__debug@9-1'(float64," ] |> shouldSucceed [] @@ -551,6 +563,7 @@ let main _ = |> withNoOptimize |> asExe |> compileAndRun + |> verifyILContains ["call void Test::'__debug@16'(class Test/T)"] |> shouldSucceed [] @@ -580,6 +593,7 @@ let main _ = |> withNoOptimize |> asExe |> compileAndRun + |> verifyILContains ["Test::'__debug@19'()"] |> shouldSucceed [] @@ -613,6 +627,7 @@ let main _ = |> withNoOptimize |> asExe |> compileAndRun + |> verifyILContains ["call int32 Test::'__debug@23'(valuetype Test/S`1)"] |> shouldSucceed [] @@ -636,6 +651,7 @@ let main _ = |> withNoOptimize |> asExe |> compileAndRun + |> verifyILContains ["call int32 Test::'__debug@13'(valuetype Test/S`1)"] |> shouldSucceed [] @@ -664,6 +680,7 @@ type U = static member inline F<'a, 'b when 'a: (member M: unit -> unit)>(_a: 'a |> withNoOptimize |> asExe |> compileAndRun + |> verifyILContains ["Program::'__debug@10'(class Module/T)"] |> shouldSucceed [] @@ -694,6 +711,7 @@ let main _ = |> withReferences [library] |> asExe |> compileAndRun + |> verifyILContains ["Test::'__debug@8'(int32,"] |> shouldSucceed [] @@ -724,6 +742,7 @@ type C = static member inline F<'a, 'b, 'c when C<'a, 'b>>(_a: 'a) = () |> withNoOptimize |> asExe |> compileAndRun + |> verifyILContains ["Program::'__debug@12'(class Program/T)"] |> shouldSucceed [] @@ -747,6 +766,7 @@ let main _ = |> withNoOptimize |> asExe |> compileAndRun + |> verifyILContains ["call void Test::'__debug@13'(valuetype Test/S&,"] |> shouldSucceed [] @@ -781,6 +801,7 @@ let main _ = |> withReferences [library] |> asExe |> compileAndRun + |> verifyILContains ["call void Test::'__debug@12'(valuetype Test/S&,"] |> shouldSucceed [] @@ -818,6 +839,7 @@ let main _ = |> withReferences [library] |> asExe |> compileAndRun + |> verifyILContains ["call void Test::'__debug@12'(valuetype Test/S&,"] |> shouldSucceed [] @@ -955,6 +977,7 @@ let inline f () = fInternal () |> withNoOptimize |> asLibrary |> compile + |> verifyILContains ["call void Module::'__debug@5'()"] |> shouldSucceed [] @@ -973,6 +996,7 @@ type T() = |> withNoOptimize |> asLibrary |> compile + |> verifyILContains ["call void Module/T::'__debug@9'(class Module/T)"] |> shouldSucceed [] @@ -997,6 +1021,7 @@ let r = Lib.T().G(1) |> withNoOptimize |> withReferences [library] |> compile + |> verifyILContains ["Lib/T::G(!!0)"] |> shouldSucceed @@ -1026,6 +1051,7 @@ let main _ = |> withReferences [library] |> asExe |> compileAndRun + |> verifyILContains ["call int32 Test::'__debug@6'(int32,"] |> shouldSucceed [] @@ -1063,6 +1089,7 @@ let main _ = |> withReferences [library] |> asExe |> compileAndRun + |> verifyILContains ["Test::'__debug@6'(float64)"] |> shouldSucceed [] @@ -1089,6 +1116,7 @@ val inline publicFn: x: int -> int |> withDebug |> withNoOptimize |> asLibrary + |> withName "Lib" FSharp """ open Lib @@ -1103,6 +1131,7 @@ let main _ = |> withReferences [library] |> asExe |> compileAndRun + |> verifyILContains ["call int32 [Lib]Lib::publicFn(int32)"] |> shouldSucceed [] @@ -1129,6 +1158,7 @@ val inline publicFn: x: int -> int |> withDebug |> withNoOptimize |> asLibrary + |> withName "Lib" FSharp """ open Lib @@ -1143,4 +1173,70 @@ let main _ = |> withReferences [library] |> asExe |> compileAndRun + |> verifyILContains ["call int32 [Lib]Lib::publicFn(int32)"] + |> shouldSucceed + + [] + let ``Resumable 01`` () = + FSharp """ +open System.Threading.Tasks + +[] +let main _ = + let t = task { return 1 } + if t.Result = 1 then 0 else 1 +""" + |> withDebug + |> withNoOptimize + |> asExe + |> compileAndRun + |> shouldSucceed + + [] + let ``Resumable 02`` () = + FSharp """ +open System.Threading.Tasks + +[] +let main _ = + let t = task { + let! x = Task.FromResult(1) + let! y = Task.FromResult(2) + return x + y + } + if t.Result = 3 then 0 else 1 +""" + |> withDebug + |> withNoOptimize + |> asExe + |> compileAndRun + |> shouldSucceed + + [] + let ``Resumable 03`` () = + FSharp """ +open Microsoft.FSharp.Core.CompilerServices +open Microsoft.FSharp.Core.CompilerServices.StateMachineHelpers +open Microsoft.FSharp.Core.LanguagePrimitives.IntrinsicOperators + +[] +type S<'T> = member _.M(_: 'T) = () + +let inline g (_: S<'T>) = + if __useResumableCode then + __stateMachine, int> + (MoveNextMethodImpl<_>(fun _ -> ())) + (SetStateMachineMethodImpl<_>(fun _ _ -> ())) + (AfterCode<_, _>(fun _ -> 42)) + else 42 + +[] +let main _ = + let r = g (S()) + if r = 42 then 0 else 1 +""" + |> withDebug + |> withNoOptimize + |> asExe + |> compileAndRun |> shouldSucceed From fd25d7f0264064c783069a98dbae9f8f8d883f0e Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Wed, 15 Apr 2026 09:56:30 +0200 Subject: [PATCH 20/35] Another accessibility attempt --- src/Compiler/Optimize/Optimizer.fs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Compiler/Optimize/Optimizer.fs b/src/Compiler/Optimize/Optimizer.fs index 9f47f31c7e8..f4ce5c2952e 100644 --- a/src/Compiler/Optimize/Optimizer.fs +++ b/src/Compiler/Optimize/Optimizer.fs @@ -1362,14 +1362,14 @@ let AbstractLazyModulInfoByHiding isAssemblyBoundary (cenv: cenv) mhi = // Check for escape in lambda | CurriedLambdaValue (_, _, _, expr, _) | ConstExprValue(_, expr) when - cenv.settings.inlineNamedFunctions && (let fvs = freeInExpr CollectAll expr - (isAssemblyBoundary && not (freeVarsAllPublic fvs)) || - Zset.exists hiddenVal fvs.FreeLocals || - Zset.exists hiddenTycon fvs.FreeTyvars.FreeTycons || Zset.exists hiddenTyconRepr fvs.FreeLocalTyconReprs || Zset.exists hiddenRecdField fvs.FreeRecdFields || - Zset.exists hiddenUnionCase fvs.FreeUnionCases ) -> + Zset.exists hiddenUnionCase fvs.FreeUnionCases || + (cenv.settings.inlineNamedFunctions && + ((isAssemblyBoundary && not (freeVarsAllPublic fvs)) || + Zset.exists hiddenVal fvs.FreeLocals || + Zset.exists hiddenTycon fvs.FreeTyvars.FreeTycons))) -> UnknownValue // Check for escape in constant From 63bd395608898f07c37ef26c7da1ddc495ff074a Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Wed, 15 Apr 2026 12:14:48 +0200 Subject: [PATCH 21/35] Fix inlined definition check --- src/Compiler/Optimize/Optimizer.fs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Compiler/Optimize/Optimizer.fs b/src/Compiler/Optimize/Optimizer.fs index f4ce5c2952e..46391fcce07 100644 --- a/src/Compiler/Optimize/Optimizer.fs +++ b/src/Compiler/Optimize/Optimizer.fs @@ -1704,7 +1704,7 @@ let TryEliminateBinding cenv _env bind e2 _m = not vspec1.IsCompilerGenerated then None elif vspec1.IsFixed then None - elif vspec1.InlineInfo = ValInline.InlinedDefinition then None + elif not cenv.settings.inlineNamedFunctions && vspec1.InlineInfo = ValInline.InlinedDefinition then None elif vspec1.LogicalName.StartsWithOrdinal stackVarPrefix || vspec1.LogicalName.Contains suffixForVariablesThatMayNotBeEliminated then None else @@ -3974,7 +3974,7 @@ and OptimizeLambdas (vspec: Val option) cenv env valReprInfo expr exprTy = // can't inline any values with semi-recursive object references to self or base let value_ = match vspec with - | Some v when v.InlineInfo = ValInline.InlinedDefinition -> UnknownValue + | Some v when not cenv.settings.inlineNamedFunctions && v.InlineInfo = ValInline.InlinedDefinition -> UnknownValue | _ -> match baseValOpt with From 64700f1177ade5eec79d03f39a5748a1e87a99d4 Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Wed, 15 Apr 2026 12:56:35 +0200 Subject: [PATCH 22/35] Fix referencing debug builds from optimized --- src/Compiler/Optimize/Optimizer.fs | 10 +++--- .../EmittedIL/DebugInlineAsCall.fs | 35 +++++++++++++++++++ 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/src/Compiler/Optimize/Optimizer.fs b/src/Compiler/Optimize/Optimizer.fs index 46391fcce07..208df34bffd 100644 --- a/src/Compiler/Optimize/Optimizer.fs +++ b/src/Compiler/Optimize/Optimizer.fs @@ -3096,7 +3096,9 @@ and TryOptimizeVal cenv env (vOpt: ValRef option, shouldInline, inlineIfLambda, | ConstExprValue(_size, expr) -> Some (remarkExpr m (copyExpr g CloneAllAndMarkExprValsAsCompilerGenerated expr)) - | CurriedLambdaValue (_, _, _, expr, _) when shouldInline || inlineIfLambda -> + | CurriedLambdaValue (_, _, _, expr, _) when + shouldInline && (cenv.settings.inlineNamedFunctions || Option.exists (shouldForceInlineInDebug cenv.g) vOpt) || + inlineIfLambda -> let fvs = freeInExpr CollectLocals expr if fvs.UsesMethodLocalConstructs then // Discarding lambda for binding because uses protected members --- TBD: Should we warn or error here @@ -3113,7 +3115,7 @@ and TryOptimizeVal cenv env (vOpt: ValRef option, shouldInline, inlineIfLambda, warning(Error(FSComp.SR.optValueMarkedInlineHasUnexpectedValue(), m)) None - | _ when shouldInline -> + | _ when shouldInline && cenv.settings.inlineNamedFunctions -> warning(Error(FSComp.SR.optValueMarkedInlineCouldNotBeInlined(), m)) None @@ -3973,10 +3975,6 @@ and OptimizeLambdas (vspec: Val option) cenv env valReprInfo expr exprTy = // can't inline any values with semi-recursive object references to self or base let value_ = - match vspec with - | Some v when not cenv.settings.inlineNamedFunctions && v.InlineInfo = ValInline.InlinedDefinition -> UnknownValue - | _ -> - match baseValOpt with | None -> CurriedLambdaValue (lambdaId, arities, bsize, exprR, exprTy) | Some baseVal -> diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs index d2a90331e4f..24c401679dc 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs @@ -284,6 +284,41 @@ g 1 2 |> ignore |> shouldSucceed |> verifyILNotPresent ["Test::'__debug"] + [] + let ``Call 16 - Debug lib called from optimized app`` () = + let lib = + FSharp """ +module Module + +let inline double (x: int) = x + x + +let inline quadruple (x: int) = double (double x) +""" + |> withDebug + |> withNoOptimize + |> asLibrary + + lib + |> compile + |> verifyILContains ["call int32 Module::double(int32)"] + |> shouldSucceed + |> ignore + + FSharp """ +open Module + +[] +let main (args: string[]) = + let i = quadruple args.Length + i +""" + |> withOptimize + |> withReferences [lib] + |> asExe + |> compile + |> verifyILContains ["add"] |> shouldSucceed + |> verifyILNotPresent ["quadruple"; "double"] + [] let ``SRTP 01`` () = FSharp """ From d2cb4a19c44829b48151a8b3e8fc8c33fc1d9a89 Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Wed, 15 Apr 2026 17:22:12 +0200 Subject: [PATCH 23/35] Nested inline with different type args --- src/Compiler/Optimize/Optimizer.fs | 33 ++++++++++++++----- .../EmittedIL/DebugInlineAsCall.fs | 23 +++++++++++++ 2 files changed, 48 insertions(+), 8 deletions(-) diff --git a/src/Compiler/Optimize/Optimizer.fs b/src/Compiler/Optimize/Optimizer.fs index 208df34bffd..0fd81b090a1 100644 --- a/src/Compiler/Optimize/Optimizer.fs +++ b/src/Compiler/Optimize/Optimizer.fs @@ -454,8 +454,12 @@ type IncrementalOptimizationEnv = { /// An identifier to help with name generation latestBoundId: Ident option - /// The set of lambda IDs we've inlined to reach this point. Helps to prevent recursive inlining - dontInline: Zset + /// Prevents recursive inlining/specialization. Maps lambda ID to a list of specialized types + /// currently being processed. An empty list means "block unconditionally" (used by normal + /// inlining and non-concrete debug specialization). A non-empty list means "block only these + /// specific type specializations" (used by concrete debug specialization, allowing different + /// type instantiations of the same function to proceed). + dontInline: Map /// Recursively bound vars. If an sub-expression that is a candidate for method splitting /// contains any of these variables then don't split it, for fear of mucking up tailcalls. @@ -479,7 +483,7 @@ type IncrementalOptimizationEnv = static member Empty = { latestBoundId = None - dontInline = Zset.empty Int64.order + dontInline = Map.empty typarInfos = [] functionVal = None dontSplitVars = ValMap.Empty @@ -3481,22 +3485,35 @@ and TryInlineApplication cenv env finfo (valExpr: Expr) (tyargs: TType list, arg let origFinfo = GetInfoForValWithCheck cenv env m vref match stripValue origFinfo.ValExprInfo with - | CurriedLambdaValue(origLambdaId, _, _, origLambda, origLambdaTy) when not (Zset.contains origLambdaId env.dontInline) -> + | CurriedLambdaValue(origLambdaId, _, _, origLambda, origLambdaTy) -> let f2R = CopyExprForInlining cenv true origLambda m let specLambda = MakeApplicationAndBetaReduce g (f2R, origLambdaTy, [tyargs], [], m) let specLambdaTy = tyOfExpr g specLambda + // For concrete type args, only block the exact same (stamp, type) pair, allowing different + // type instantiations to proceed (e.g. sumint> calling sum in its body). + // For non-concrete type args, block unconditionally. + let shouldInline = + match Map.tryFind origLambdaId env.dontInline with + | Some tys -> not allTyargsAreConcrete || tys.IsEmpty || tys |> List.exists (typeEquiv g specLambdaTy) + | None -> false + + if shouldInline then + None else + let specLambdaR = if allTyargsAreConcrete then match cenv.specializedInlineVals.FindAll(origLambdaId) |> List.tryFind (fun (ty, _) -> typeEquiv g ty specLambdaTy) with | Some (_, body) -> copyExpr g CloneAll body | None -> - let specLambdaR, _ = OptimizeExpr cenv { env with dontInline = Zset.add origLambdaId env.dontInline } specLambda + let existingTypes = defaultArg (Map.tryFind origLambdaId env.dontInline) [] + let env = { env with dontInline = Map.add origLambdaId (specLambdaTy :: existingTypes) env.dontInline } + let specLambdaR, _ = OptimizeExpr cenv env specLambda cenv.specializedInlineVals.Add(origLambdaId, (specLambdaTy, specLambdaR)) specLambdaR else - let specLambdaR, _ = OptimizeExpr cenv { env with dontInline = Zset.add origLambdaId env.dontInline } specLambda + let specLambdaR, _ = OptimizeExpr cenv { env with dontInline = Map.add origLambdaId [] env.dontInline } specLambda specLambdaR let specLambdaR = @@ -3537,7 +3554,7 @@ and TryInlineApplication cenv env finfo (valExpr: Expr) (tyargs: TType list, arg cenv.settings.InlineLambdas && not finfo.HasEffect && // Don't inline recursively! - not (Zset.contains lambdaId env.dontInline) && + not (Map.containsKey lambdaId env.dontInline) && (// Check the number of argument groups is enough to saturate the lambdas of the target. (if tyargs |> List.exists (fun t -> match t with TType_measure _ -> false | _ -> true) then 1 else 0) + args.Length = arities && if size <= cenv.settings.lambdaInlineThreshold + args.Length then true @@ -3609,7 +3626,7 @@ and TryInlineApplication cenv env finfo (valExpr: Expr) (tyargs: TType list, arg // Inlining: beta reducing let exprR = MakeApplicationAndBetaReduce g (f2R, f2ty, [tyargs], argsR, m) // Inlining: reoptimizing - Some(OptimizeExpr cenv {env with dontInline= Zset.add lambdaId env.dontInline} exprR) + Some(OptimizeExpr cenv {env with dontInline = Map.add lambdaId [] env.dontInline} exprR) | _ -> None diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs index 24c401679dc..406ada61691 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs @@ -877,6 +877,29 @@ let main _ = |> verifyILContains ["call void Test::'__debug@12'(valuetype Test/S&,"] |> shouldSucceed + [] + let ``SRTP 22 - Recursive inline with different type arg`` () = + FSharp """ +type T = T with + static member ($) (T, _:int) = (+) + static member ($) (T, _:decimal) = (+) + +let inline sum (i:'a) (x:'a) :'r = (T $ Unchecked.defaultof<'r>) i x + +type T with + static member inline ($) (T, _:'t -> 'rest) = fun (a:'t) x -> sum (x + a) + +[] +let main _ = + let y:int = sum 2 3 4 + if y = 9 then 0 else 1 +""" + |> withDebug + |> withNoOptimize + |> asExe + |> compileAndRun + |> shouldSucceed + [] let ``Member 01 - Non-generic`` () = FSharp """ From 63a77dc115cd0e8cf6a7419a51b795d6279cdf4d Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Thu, 16 Apr 2026 16:17:49 +0200 Subject: [PATCH 24/35] Pickle ValInline.InlinedDefinition as ValInline.Always --- src/Compiler/TypedTree/TypedTree.fs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Compiler/TypedTree/TypedTree.fs b/src/Compiler/TypedTree/TypedTree.fs index 4c43a568bc3..0de0cc80438 100644 --- a/src/Compiler/TypedTree/TypedTree.fs +++ b/src/Compiler/TypedTree/TypedTree.fs @@ -243,7 +243,12 @@ type ValFlags(flags: int64) = // Clear the IsCompiledAsStaticPropertyWithoutField, only used to determine whether to use a true field for a value, and to eliminate the optimization info for observable bindings // Clear the HasBeenReferenced, only used to report "unreferenced variable" warnings and to help collect 'it' values in FSI.EXE // Clear the IsGeneratedEventVal, since there's no use in propagating specialname information for generated add/remove event vals - (flags &&& ~~~0b010011001100000000000L) + let bits = (flags &&& ~~~0b010011001100000000000L) + // Pickle ValInline.InlinedDefinition as ValInline.Always. + if bits &&& 0b00000000000000110000L = 0L then + bits ||| 0b00000000000000010000L + else + bits /// Represents the kind of a type parameter [] From 33c73937609527cfaa63311e0aa262cafbc65437 Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Sat, 18 Apr 2026 11:37:46 +0200 Subject: [PATCH 25/35] Better cross-file name collision fix --- src/Compiler/CodeGen/IlxGen.fs | 14 +++++- src/Compiler/Optimize/Optimizer.fs | 6 --- .../EmittedIL/DebugInlineAsCall.fs | 44 +++++++++++++++++++ 3 files changed, 57 insertions(+), 7 deletions(-) diff --git a/src/Compiler/CodeGen/IlxGen.fs b/src/Compiler/CodeGen/IlxGen.fs index 58c6ef08ee4..c1b181522c3 100644 --- a/src/Compiler/CodeGen/IlxGen.fs +++ b/src/Compiler/CodeGen/IlxGen.fs @@ -7150,7 +7150,19 @@ and GetIlxClosureFreeVars cenv m (thisVars: ValRef list) boxity eenv takenNames let cloName = // Ensure that we have an g.CompilerGlobalState assert (g.CompilerGlobalState |> Option.isSome) - g.CompilerGlobalState.Value.StableNameGenerator.GetUniqueCompilerGeneratedName(basenameSafeForUseAsTypename, expr.Range, uniq) + // The closure name counter is keyed by (basicName, fileIndex). When an expression is copied + // from another file (e.g. specializing an inline function body across files), its ranges + // still point at the original file, so its closures fall into a different counter bucket + // than closures minted for the current file. Since all these closures live under the same + // enclosing type, that can produce two closures with the same final name. Bucket the counter + // by the enclosing type's file while keeping expr.Range's StartLine for the displayed name. + let nameRange = + if expr.Range.FileIndex = eenv.cloc.Range.FileIndex then + expr.Range + else + Range.mkFileIndexRange eenv.cloc.Range.FileIndex expr.Range.Start expr.Range.End + + g.CompilerGlobalState.Value.StableNameGenerator.GetUniqueCompilerGeneratedName(basenameSafeForUseAsTypename, nameRange, uniq) let ilCloTypeRef = NestedTypeRefForCompLoc eenv.cloc cloName diff --git a/src/Compiler/Optimize/Optimizer.fs b/src/Compiler/Optimize/Optimizer.fs index 0fd81b090a1..ab785ee19cf 100644 --- a/src/Compiler/Optimize/Optimizer.fs +++ b/src/Compiler/Optimize/Optimizer.fs @@ -3516,12 +3516,6 @@ and TryInlineApplication cenv env finfo (valExpr: Expr) (tyargs: TType list, arg let specLambdaR, _ = OptimizeExpr cenv { env with dontInline = Map.add origLambdaId [] env.dontInline } specLambda specLambdaR - let specLambdaR = - match specLambdaR with - | Expr.Lambda(uniq, a, b, c, d, _, ty) -> Expr.Lambda(uniq, a, b, c, d, m, ty) - | Expr.TyLambda(uniq, a, b, _, ty) -> Expr.TyLambda(uniq, a, b, m, ty) - | _ -> specLambdaR - let debugVal = let name = $"<{vref.LogicalName}>__debug" // When tyargs have free type variables, omit ValReprInfo so IlxGen compiles this diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs index 406ada61691..42e466a143b 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs @@ -900,6 +900,50 @@ let main _ = |> compileAndRun |> shouldSucceed + [] + let ``SRTP 23 - Cross-file specialization with nested closures at same line`` () = + // Two specializations in wrap's body each contain nested closures whose ranges are in the + // other file. Without bucketing the closure-name counter by the enclosing type's file, the + // two nested closures end up with identical names ('wrap@12-1') and ilwrite rejects them + // with FS2014 duplicate entry in type index table. + let additionalSource = FsSourceWithFileName "Program.fs" """ +module Program +open Module + + +let inline wrap source = + let mutable state = false + monad' { + match state with + | true -> return false + | _ -> + let! _ = source + state <- true + return true } +""" + FSharpWithFileName "Module.fs" """ +module Module +type Bind = + static member inline Invoke (s: 'M) (b: 'T -> 'U) = + ((^M or ^U) : (static member (>>=) : _*_ -> _) s, b) + +type Return = + static member Return (_: 'T list, _: Return) : 'T -> 'T list = Unchecked.defaultof<_> + static member inline Invoke (x: 'T) = + (^A : (static member Return : 'T -> ^A) x) + +type MonadBuilder () = + member inline _.Return x = Return.Invoke x + member inline _.Bind (p, r) = Bind.Invoke p r +let monad' = MonadBuilder () +""" + |> withAdditionalSourceFile additionalSource + |> withDebug + |> withNoOptimize + |> asLibrary + |> compile + |> shouldSucceed + [] let ``Member 01 - Non-generic`` () = FSharp """ From 5b568e06010682ac44bdfc8bc509fed2976b3dd5 Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Sat, 18 Apr 2026 14:37:13 +0200 Subject: [PATCH 26/35] Better byref fix --- src/Compiler/Optimize/Optimizer.fs | 66 ++++++++++---- .../EmittedIL/DebugInlineAsCall.fs | 91 +++++++++++++++++++ 2 files changed, 137 insertions(+), 20 deletions(-) diff --git a/src/Compiler/Optimize/Optimizer.fs b/src/Compiler/Optimize/Optimizer.fs index ab785ee19cf..9c051c02fb5 100644 --- a/src/Compiler/Optimize/Optimizer.fs +++ b/src/Compiler/Optimize/Optimizer.fs @@ -3461,9 +3461,6 @@ and TryInlineApplication cenv env finfo (valExpr: Expr) (tyargs: TType list, arg let tps, _ = tryDestForallTy g vref.Type GetTraitConstraintInfosOfTypars g tps |> List.isEmpty - let allTyargsAreConcrete = - tyargs |> List.forall (fun t -> (freeInType CollectTyparsNoCaching t).FreeTypars.IsEmpty) - let allTyargsAreGeneric = tyargs |> List.forall (fun t -> not (freeInType CollectTyparsNoCaching t).FreeTypars.IsEmpty) @@ -3490,6 +3487,15 @@ and TryInlineApplication cenv env finfo (valExpr: Expr) (tyargs: TType list, arg let specLambda = MakeApplicationAndBetaReduce g (f2R, origLambdaTy, [tyargs], [], m) let specLambdaTy = tyOfExpr g specLambda + // Typars that flow in from the enclosing scope when tyargs are non-concrete. + // specLambdaTy is closed over the vref's typars after beta-reduction, so its free + // typars are exactly the ones carried in by tyargs. + let freeTypars = + (freeInType CollectTyparsNoCaching specLambdaTy).FreeTypars + |> Zset.elements + + let allTyargsAreConcrete = List.isEmpty freeTypars + // For concrete type args, only block the exact same (stamp, type) pair, allowing different // type instantiations to proceed (e.g. sumint> calling sum in its body). // For non-concrete type args, block unconditionally. @@ -3516,26 +3522,46 @@ and TryInlineApplication cenv env finfo (valExpr: Expr) (tyargs: TType list, arg let specLambdaR, _ = OptimizeExpr cenv { env with dontInline = Map.add origLambdaId [] env.dontInline } specLambda specLambdaR - let debugVal = - let name = $"<{vref.LogicalName}>__debug" - // When tyargs have free type variables, omit ValReprInfo so IlxGen compiles this - // as a closure that captures type variables and witnesses from the enclosing scope. - let valReprInfo = - if allTyargsAreConcrete then + // Abstract the specialized lambda over its free typars so IlxGen emits a static + // method with flattened arguments. The alternative closure form (valReprInfo = None) + // wraps args in a reference Tuple<>, which cannot hold byrefs and fails to load at + // runtime. When a free typar carries SRTP constraints the specialized body still + // needs runtime witnesses from the enclosing scope; those only flow through the + // closure path, so keep the closure compilation for that case. + let freeTyparsNeedWitnesses = + not (GetTraitWitnessInfosOfTypars g 0 freeTypars |> List.isEmpty) + + let debugValName = $"<{vref.LogicalName}>__debug" + + if not freeTyparsNeedWitnesses then + let debugValTy = mkForallTyIfNeeded freeTypars specLambdaTy + let debugValBody = mkTypeLambda m freeTypars (specLambdaR, specLambdaTy) + + let debugVal = + let argInfos, retInfo = match vref.ValReprInfo with - | Some(ValReprInfo(_, argInfos, retInfo)) -> - Some(ValReprInfo([], argInfos, retInfo)) + | Some(ValReprInfo(_, argInfos, retInfo)) -> argInfos, retInfo | None -> - Some(InferValReprInfoOfExpr g AllowTypeDirectedDetupling.No specLambdaTy [] [] specLambdaR) - else - None - - Construct.NewVal(name, m, None, specLambdaTy, Immutable, true, valReprInfo, taccessPublic, ValNotInRecScope, None, - NormalVal, [], ValInline.InlinedDefinition, XmlDoc.Empty, false, false, false, false, false, false, None, - ParentNone) + let (ValReprInfo(_, a, r)) = + InferValReprInfoOfExpr g AllowTypeDirectedDetupling.No specLambdaTy [] [] specLambdaR + a, r + let valReprInfo = ValReprInfo(ValReprInfo.InferTyparInfo freeTypars, argInfos, retInfo) + + Construct.NewVal(debugValName, m, None, debugValTy, Immutable, true, Some valReprInfo, taccessPublic, ValNotInRecScope, None, + NormalVal, [], ValInline.InlinedDefinition, XmlDoc.Empty, false, false, false, false, false, false, None, + ParentNone) + + let callTyargs = freeTypars |> List.map mkTyparTy + let callExpr = mkApps g ((exprForVal m debugVal, debugValTy), [callTyargs], argsR, m) + Some(mkCompGenLet m debugVal debugValBody callExpr, info) + else + let debugVal = + Construct.NewVal(debugValName, m, None, specLambdaTy, Immutable, true, None, taccessPublic, ValNotInRecScope, None, + NormalVal, [], ValInline.InlinedDefinition, XmlDoc.Empty, false, false, false, false, false, false, None, + ParentNone) - let callExpr = mkApps g ((exprForVal m debugVal, specLambdaTy), [], argsR, m) - Some(mkCompGenLet m debugVal specLambdaR callExpr, info) + let callExpr = mkApps g ((exprForVal m debugVal, specLambdaTy), [], argsR, m) + Some(mkCompGenLet m debugVal specLambdaR callExpr, info) | _ -> None | _ -> diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs index 42e466a143b..b9139021e0d 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs @@ -944,6 +944,97 @@ let monad' = MonadBuilder () |> compile |> shouldSucceed + [] + let ``SRTP 24 - byref with free typar at callsite`` () = + FSharp """ +type MyBuilder<'T>() = + member _.M(a: byref, b: byref) = () + +let inline callMember<'Builder, 'A + when 'Builder: (member M: byref<'A> * byref<'A> -> unit)> + (builder: 'Builder, a: byref<'A>) = + builder.M(&a, &a) + +let runDynamic (builder: MyBuilder<'T>) = + let mutable x = 0 + callMember (builder, &x) + +[] +let main _ = + runDynamic (MyBuilder()) + 0 +""" + |> withDebug + |> withNoOptimize + |> asExe + |> compileAndRun + |> verifyILContains ["call void Test::'__debug@12'(class Test/MyBuilder`1,"] + |> shouldSucceed + + [] + let ``SRTP 25 - byref with free typar at callsite - large tuple`` () = + // F# represents tuples with 8+ elements as nested System.Tuple. When building a closure + // for such a call the compiler would otherwise pack args into a reference Tuple shape + // that cannot contain byrefs. The debug-call path must flatten to a method regardless + // of arity. + FSharp """ +type MyBuilder<'T>() = + member _.M(a1: byref, a2: byref, a3: byref, + a4: byref, a5: byref, a6: byref, + a7: byref, a8: byref) = + a1 <- 1 + +let inline callMember<'Builder, 'A + when 'Builder: (member M: byref<'A> * byref<'A> * byref<'A> * byref<'A> + * byref<'A> * byref<'A> * byref<'A> * byref<'A> -> unit)> + (builder: 'Builder, + a1: byref<'A>, a2: byref<'A>, a3: byref<'A>, a4: byref<'A>, + a5: byref<'A>, a6: byref<'A>, a7: byref<'A>, a8: byref<'A>) = + builder.M(&a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8) + +let runDynamic (builder: MyBuilder<'T>) = + let mutable x = 0 + callMember (builder, &x, &x, &x, &x, &x, &x, &x, &x) + +[] +let main _ = + runDynamic (MyBuilder()) + 0 +""" + |> withDebug + |> withNoOptimize + |> asExe + |> compileAndRun + |> verifyILContains ["call void Test::'__debug@18'(class Test/MyBuilder`1,"] + |> shouldSucceed + + [] + let ``SRTP 26 - byref with free typar at callsite - three tupled args`` () = + FSharp """ +type MyBuilder<'T>() = + member _.M(a: byref, b: byref) = () + +let inline callMember<'Builder, 'A + when 'Builder: (member M: byref<'A> * byref<'A> -> unit)> + (builder: 'Builder, a: byref<'A>, b: byref<'A>) = + builder.M(&a, &b) + +let runDynamic (builder: MyBuilder<'T>) = + let mutable x = 0 + callMember (builder, &x, &x) + +[] +let main _ = + runDynamic (MyBuilder()) + 0 +""" + |> withDebug + |> withNoOptimize + |> asExe + |> compileAndRun + |> verifyILContains ["call void Test::'__debug@12'(class Test/MyBuilder`1,"] + |> shouldSucceed + [] let ``Member 01 - Non-generic`` () = FSharp """ From f3667185bf932f1203a2f7f764ec90bc23a9eac9 Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Sat, 18 Apr 2026 15:18:36 +0200 Subject: [PATCH 27/35] Better SRTP fix --- src/Compiler/Optimize/Optimizer.fs | 11 ++-- .../EmittedIL/DebugInlineAsCall.fs | 53 +++++++++++++++++++ 2 files changed, 61 insertions(+), 3 deletions(-) diff --git a/src/Compiler/Optimize/Optimizer.fs b/src/Compiler/Optimize/Optimizer.fs index 9c051c02fb5..99705138fc9 100644 --- a/src/Compiler/Optimize/Optimizer.fs +++ b/src/Compiler/Optimize/Optimizer.fs @@ -3461,8 +3461,13 @@ and TryInlineApplication cenv env finfo (valExpr: Expr) (tyargs: TType list, arg let tps, _ = tryDestForallTy g vref.Type GetTraitConstraintInfosOfTypars g tps |> List.isEmpty - let allTyargsAreGeneric = - tyargs |> List.forall (fun t -> not (freeInType CollectTyparsNoCaching t).FreeTypars.IsEmpty) + // Direct-calling an SRTP callee is only safe when every tyarg is a bare typar: then the + // callee's SRTP constraints land on the caller's own typars and IlxGen rewrites the + // call to the $W variant inside the caller's $W compilation context. Non-typar tyargs + // (e.g. MyBuilder<'T>) require static resolution of the trait, which the callee's + // non-$W stub cannot do, so those must go through the specialization path. + let allTyargsAreBareTypars = + tyargs |> List.forall (isTyparTy g) // When inside an inline function body being prepared for export (!cenv.optimizing), // only emit a direct call if the callee is publicly accessible. Non-public vals @@ -3471,7 +3476,7 @@ and TryInlineApplication cenv env finfo (valExpr: Expr) (tyargs: TType list, arg let isHiddenBySignature = cenv.signatureHidingInfo.HiddenVals.Contains vref.Deref let canCallDirectly = (cenv.optimizing || (vref.Accessibility.IsPublic && not isHiddenBySignature)) && - (hasNoTraits || (allTyargsAreGeneric && vref.ValReprInfo.IsSome)) + (hasNoTraits || (allTyargsAreBareTypars && vref.ValReprInfo.IsSome)) let argsR = args |> List.map (OptimizeExpr cenv env >> fst) let info = { TotalSize = 1; FunctionSize = 1; HasEffect = true; MightMakeCriticalTailcall = false; Info = UnknownValue } diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs index b9139021e0d..1641f84312a 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs @@ -1035,6 +1035,59 @@ let main _ = |> verifyILContains ["call void Test::'__debug@12'(class Test/MyBuilder`1,"] |> shouldSucceed + [] + let ``SRTP 27 - non-typar tyarg to SRTP callee - non-inline caller`` () = + // Non-typar tyargs (MyBuilder<'T>) cannot satisfy the callee's SRTP via witness + // propagation; they must go through the specialization path so the trait resolves + // statically to MyBuilder.M. + FSharp """ +type MyBuilder<'T>() = + member _.M() = () + +let inline callMember<'Builder when 'Builder: (member M: unit -> unit)> (builder: 'Builder) = + builder.M() + +let runDynamic (builder: MyBuilder<'T>) = + callMember builder + +[] +let main _ = + runDynamic (MyBuilder()) + 0 +""" + |> withDebug + |> withNoOptimize + |> asExe + |> compileAndRun + |> verifyILContains ["call void Test::'__debug@9'(class Test/MyBuilder`1)"] + |> shouldSucceed + + [] + let ``SRTP 28 - non-typar tyarg to SRTP callee - inline caller`` () = + // Same pattern as SRTP 27 but the caller is itself inline. The non-$W variant of the + // inline caller would otherwise contain a direct call to the SRTP callee's non-$W + // stub and throw at runtime when invoked from non-inline code. + FSharp """ +type MyBuilder<'T>() = + member _.M() = () + +let inline callMember<'Builder when 'Builder: (member M: unit -> unit)> (builder: 'Builder) = + builder.M() + +let inline outerInline<'T> (builder: MyBuilder<'T>) = + callMember builder + +[] +let main _ = + outerInline (MyBuilder()) + 0 +""" + |> withDebug + |> withNoOptimize + |> asExe + |> compileAndRun + |> shouldSucceed + [] let ``Member 01 - Non-generic`` () = FSharp """ From 22e95b107a397e170cb8a2cf3cf4979c8f735a10 Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Mon, 20 Apr 2026 14:56:03 +0200 Subject: [PATCH 28/35] Another byref fix --- src/Compiler/Optimize/Optimizer.fs | 22 ++++++++- .../EmittedIL/DebugInlineAsCall.fs | 46 +++++++++++++++++++ 2 files changed, 67 insertions(+), 1 deletion(-) diff --git a/src/Compiler/Optimize/Optimizer.fs b/src/Compiler/Optimize/Optimizer.fs index 99705138fc9..e8078d357d2 100644 --- a/src/Compiler/Optimize/Optimizer.fs +++ b/src/Compiler/Optimize/Optimizer.fs @@ -3538,7 +3538,27 @@ and TryInlineApplication cenv env finfo (valExpr: Expr) (tyargs: TType list, arg let debugValName = $"<{vref.LogicalName}>__debug" - if not freeTyparsNeedWitnesses then + // The closure form wraps tupled args in a reference Tuple<> and cannot hold byrefs. + // When byrefs appear in the specialized call shape and the closure path is our only + // option (witnesses required), skip specialization entirely and let the outer pass + // emit a regular call - IlxGen handles $W witness rewriting inside inline callers. + let specArgsHaveByref = + let rec check ty = + match tryDestFunTy g ty with + | ValueSome(argTy, retTy) -> + let argHasByref = + if isRefTupleTy g argTy then + destRefTupleTy g argTy |> List.exists (isByrefTy g) + else + isByrefTy g argTy + argHasByref || check retTy + | ValueNone -> false + + check specLambdaTy + + if freeTyparsNeedWitnesses && specArgsHaveByref then + None + elif not freeTyparsNeedWitnesses then let debugValTy = mkForallTyIfNeeded freeTypars specLambdaTy let debugValBody = mkTypeLambda m freeTypars (specLambdaR, specLambdaTy) diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs index 1641f84312a..f1ef78da738 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs @@ -1088,6 +1088,52 @@ let main _ = |> compileAndRun |> shouldSucceed + [] + let ``SRTP 29 - byref callee under SRTP witnesses, nested in delegate bodies`` () = + // The specialized callee shape has byref in a tupled-arg position and the enclosing + // scope needs a trait witness. Neither a byref-bearing closure (invalid System.Tuple + // instantiation) nor a non-$W stub method works here, so the optimizer must leave the + // call as-is and let IlxGen's $W rewriting pick up the witness from the inline caller. + FSharp """ +type Aw(value: int) = + member _.GetResult() = value + +type Code<'T> = delegate of byref<'T> -> unit + +let inline bindDynamic<'TResult1, 'TOverall, 'Awaiter + when 'Awaiter: (member GetResult: unit -> 'TResult1)> + (d: byref<'TOverall>, awaiter: 'Awaiter, continuation: 'TResult1 -> Code<'TOverall>) = + (continuation (awaiter.GetResult())).Invoke(&d) + +let inline wrap<'T1, 'T2, 'Awaiter1, 'Awaiter2 + when 'Awaiter1: (member GetResult: unit -> 'T1) + and 'Awaiter2: (member GetResult: unit -> 'T2)> + (left: 'Awaiter1) (right: 'Awaiter2) : Code<'T1 * 'T2> = + Code<'T1 * 'T2>(fun d -> + bindDynamic (&d, left, fun leftR -> + Code<'T1 * 'T2>(fun d2 -> + bindDynamic (&d2, right, fun rightR -> + Code<'T1 * 'T2>(fun d3 -> d3 <- (leftR, rightR)))))) + +[] +let main _ = + let code = wrap (Aw(1)) (Aw(2)) + let mutable result = (0, 0) + code.Invoke(&result) + printfn "Result = %A" result + 0 +""" + |> withDebug + |> withNoOptimize + |> asExe + |> compileAndRun + |> verifyILContains + [ "call void Test::'__debug@17'(class [runtime]System.Tuple`2&," + "call void Test::'__debug@19-1'(class [runtime]System.Tuple`2&," + "call class Test/Code`1> Test::'__debug@24'(class Test/Aw," ] + |> shouldSucceed + |> withStdOutContains "Result = (1, 2)" + [] let ``Member 01 - Non-generic`` () = FSharp """ From 3ee43317c7be7cf5cbe40ff392aeaad65f406820 Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Tue, 21 Apr 2026 13:07:44 +0200 Subject: [PATCH 29/35] Cleanup --- src/Compiler/Optimize/Optimizer.fs | 61 ++++++++++++++++-------------- 1 file changed, 32 insertions(+), 29 deletions(-) diff --git a/src/Compiler/Optimize/Optimizer.fs b/src/Compiler/Optimize/Optimizer.fs index e8078d357d2..6e1953d9e83 100644 --- a/src/Compiler/Optimize/Optimizer.fs +++ b/src/Compiler/Optimize/Optimizer.fs @@ -1708,7 +1708,7 @@ let TryEliminateBinding cenv _env bind e2 _m = not vspec1.IsCompilerGenerated then None elif vspec1.IsFixed then None - elif not cenv.settings.inlineNamedFunctions && vspec1.InlineInfo = ValInline.InlinedDefinition then None + elif vspec1.InlineInfo = ValInline.InlinedDefinition then None elif vspec1.LogicalName.StartsWithOrdinal stackVarPrefix || vspec1.LogicalName.Contains suffixForVariablesThatMayNotBeEliminated then None else @@ -3501,15 +3501,19 @@ and TryInlineApplication cenv env finfo (valExpr: Expr) (tyargs: TType list, arg let allTyargsAreConcrete = List.isEmpty freeTypars - // For concrete type args, only block the exact same (stamp, type) pair, allowing different - // type instantiations to proceed (e.g. sumint> calling sum in its body). - // For non-concrete type args, block unconditionally. - let shouldInline = + // Proceed with specialization only if this (stamp, type) pair isn't already being + // processed. For concrete type args, allow different type instantiations of the same + // function (e.g. sumint> can call sum in its body). For + // non-concrete type args, never specialize recursively. + let canSpecialize = match Map.tryFind origLambdaId env.dontInline with - | Some tys -> not allTyargsAreConcrete || tys.IsEmpty || tys |> List.exists (typeEquiv g specLambdaTy) - | None -> false + | Some tys -> + allTyargsAreConcrete && + not tys.IsEmpty && + not (tys |> List.exists (typeEquiv g specLambdaTy)) + | None -> true - if shouldInline then + if not canSpecialize then None else let specLambdaR = @@ -3534,7 +3538,7 @@ and TryInlineApplication cenv env finfo (valExpr: Expr) (tyargs: TType list, arg // needs runtime witnesses from the enclosing scope; those only flow through the // closure path, so keep the closure compilation for that case. let freeTyparsNeedWitnesses = - not (GetTraitWitnessInfosOfTypars g 0 freeTypars |> List.isEmpty) + GetTraitWitnessInfosOfTypars g 0 freeTypars |> List.isEmpty |> not let debugValName = $"<{vref.LogicalName}>__debug" @@ -3557,12 +3561,16 @@ and TryInlineApplication cenv env finfo (valExpr: Expr) (tyargs: TType list, arg check specLambdaTy if freeTyparsNeedWitnesses && specArgsHaveByref then - None - elif not freeTyparsNeedWitnesses then - let debugValTy = mkForallTyIfNeeded freeTypars specLambdaTy - let debugValBody = mkTypeLambda m freeTypars (specLambdaR, specLambdaTy) + None else - let debugVal = + // Static method path (no witnesses needed): abstract over free typars so IlxGen emits + // a method with flattened arguments rather than a closure that wraps args in Tuple<>. + // Closure path (witnesses needed, no byref): keep the body as-is; witnesses from the + // enclosing scope flow through the closure, so no typar abstraction is needed. + let debugValTy, debugValBody, valReprInfo, typeInstForCall = + if not freeTyparsNeedWitnesses then + let ty = mkForallTyIfNeeded freeTypars specLambdaTy + let body = mkTypeLambda m freeTypars (specLambdaR, specLambdaTy) let argInfos, retInfo = match vref.ValReprInfo with | Some(ValReprInfo(_, argInfos, retInfo)) -> argInfos, retInfo @@ -3570,23 +3578,18 @@ and TryInlineApplication cenv env finfo (valExpr: Expr) (tyargs: TType list, arg let (ValReprInfo(_, a, r)) = InferValReprInfoOfExpr g AllowTypeDirectedDetupling.No specLambdaTy [] [] specLambdaR a, r - let valReprInfo = ValReprInfo(ValReprInfo.InferTyparInfo freeTypars, argInfos, retInfo) - - Construct.NewVal(debugValName, m, None, debugValTy, Immutable, true, Some valReprInfo, taccessPublic, ValNotInRecScope, None, - NormalVal, [], ValInline.InlinedDefinition, XmlDoc.Empty, false, false, false, false, false, false, None, - ParentNone) + let reprInfo = ValReprInfo(ValReprInfo.InferTyparInfo freeTypars, argInfos, retInfo) + ty, body, Some reprInfo, [List.map mkTyparTy freeTypars] + else + specLambdaTy, specLambdaR, None, [] - let callTyargs = freeTypars |> List.map mkTyparTy - let callExpr = mkApps g ((exprForVal m debugVal, debugValTy), [callTyargs], argsR, m) - Some(mkCompGenLet m debugVal debugValBody callExpr, info) - else - let debugVal = - Construct.NewVal(debugValName, m, None, specLambdaTy, Immutable, true, None, taccessPublic, ValNotInRecScope, None, - NormalVal, [], ValInline.InlinedDefinition, XmlDoc.Empty, false, false, false, false, false, false, None, - ParentNone) + let debugVal = + Construct.NewVal(debugValName, m, None, debugValTy, Immutable, true, valReprInfo, taccessPublic, ValNotInRecScope, None, + NormalVal, [], ValInline.InlinedDefinition, XmlDoc.Empty, false, false, false, false, false, false, None, + ParentNone) - let callExpr = mkApps g ((exprForVal m debugVal, specLambdaTy), [], argsR, m) - Some(mkCompGenLet m debugVal specLambdaR callExpr, info) + let callExpr = mkApps g ((exprForVal m debugVal, debugValTy), typeInstForCall, argsR, m) + Some(mkCompGenLet m debugVal debugValBody callExpr, info) | _ -> None | _ -> From 6202367547ce36459e9a966f4622aaf238a2d255 Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Tue, 21 Apr 2026 13:47:26 +0200 Subject: [PATCH 30/35] Add MSBuild property --- src/FSharp.Build/Fsc.fs | 12 ++++++++++++ src/FSharp.Build/Microsoft.FSharp.Targets | 1 + 2 files changed, 13 insertions(+) diff --git a/src/FSharp.Build/Fsc.fs b/src/FSharp.Build/Fsc.fs index 90793f3e430..c67f56defa9 100644 --- a/src/FSharp.Build/Fsc.fs +++ b/src/FSharp.Build/Fsc.fs @@ -58,6 +58,7 @@ type public Fsc() as this = let mutable preferredUILang: string | null = null let mutable publicSign: bool = false let mutable provideCommandLineArgs: bool = false + let mutable inlineNamedFunctions: bool option = None let mutable realsig: bool option = None let mutable references: ITaskItem[] = [||] let mutable referencePath: string | null = null @@ -200,6 +201,9 @@ type public Fsc() as this = else builder.AppendSwitch("--optimize-") + // InlineNamedFunctions + builder.AppendOptionalSwitch("--inline-named-functions", inlineNamedFunctions) + // realsig builder.AppendOptionalSwitch("--realsig", realsig) @@ -560,6 +564,14 @@ type public Fsc() as this = with get () = publicSign and set (s) = publicSign <- s + // --inline-named-functions[+-] + member _.InlineNamedFunctions + with get () = + match inlineNamedFunctions with + | Some true -> true + | _ -> false + and set (b) = inlineNamedFunctions <- Some b + // --realsig[+-] member _.RealSig with get () = diff --git a/src/FSharp.Build/Microsoft.FSharp.Targets b/src/FSharp.Build/Microsoft.FSharp.Targets index 9049f2f7118..1ad7c6fac63 100644 --- a/src/FSharp.Build/Microsoft.FSharp.Targets +++ b/src/FSharp.Build/Microsoft.FSharp.Targets @@ -389,6 +389,7 @@ this file. PreferredUILang="$(PreferredUILang)" ProvideCommandLineArgs="$(ProvideCommandLineArgs)" PublicSign="$(PublicSign)" + InlineNamedFunctions="$(InlineNamedFunctions)" RealSig="$(RealSig)" References="@(ReferencePathWithRefAssemblies)" ReferencePath="$(ReferencePathWithRefAssemblies)" From d15614dc3fde9e786c3c06e69512acd5f4359d46 Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Tue, 21 Apr 2026 16:51:50 +0200 Subject: [PATCH 31/35] Don't inline lambdas --- src/Compiler/Optimize/Optimizer.fs | 21 ++--- .../EmittedIL/DebugInlineAsCall.fs | 34 ++++++++ ...ealInternalSignatureOff.OptimizeOff.il.bsl | 70 ++++++++++++---- ....fs.RealInternalSignatureOff.il.net472.bsl | 81 +++++++++++++------ ...RealInternalSignatureOn.OptimizeOff.il.bsl | 70 ++++++++++++---- ...1.fs.RealInternalSignatureOn.il.net472.bsl | 81 +++++++++++++------ 6 files changed, 267 insertions(+), 90 deletions(-) diff --git a/src/Compiler/Optimize/Optimizer.fs b/src/Compiler/Optimize/Optimizer.fs index 6e1953d9e83..759d418cdf6 100644 --- a/src/Compiler/Optimize/Optimizer.fs +++ b/src/Compiler/Optimize/Optimizer.fs @@ -3102,7 +3102,7 @@ and TryOptimizeVal cenv env (vOpt: ValRef option, shouldInline, inlineIfLambda, | CurriedLambdaValue (_, _, _, expr, _) when shouldInline && (cenv.settings.inlineNamedFunctions || Option.exists (shouldForceInlineInDebug cenv.g) vOpt) || - inlineIfLambda -> + inlineIfLambda && cenv.settings.inlineNamedFunctions -> let fvs = freeInExpr CollectLocals expr if fvs.UsesMethodLocalConstructs then // Discarding lambda for binding because uses protected members --- TBD: Should we warn or error here @@ -3114,9 +3114,8 @@ and TryOptimizeVal cenv env (vOpt: ValRef option, shouldInline, inlineIfLambda, | TupleValue _ | UnionCaseValue _ | RecdValue _ when shouldInline -> failwith "tuple, union and record values cannot be marked 'inline'" - | UnknownValue when shouldInline -> - if cenv.settings.inlineNamedFunctions then - warning(Error(FSComp.SR.optValueMarkedInlineHasUnexpectedValue(), m)) + | UnknownValue when shouldInline && cenv.settings.inlineNamedFunctions -> + warning(Error(FSComp.SR.optValueMarkedInlineHasUnexpectedValue(), m)) None | _ when shouldInline && cenv.settings.inlineNamedFunctions -> @@ -3165,12 +3164,14 @@ and OptimizeVal cenv env expr (v: ValRef, m) = e, AddValEqualityInfo g m v einfo | None -> - if v.ShouldInline && cenv.settings.inlineNamedFunctions then - match valInfoForVal.ValExprInfo with - | UnknownValue -> error(Error(FSComp.SR.optFailedToInlineValue(v.DisplayName), m)) - | _ -> warning(Error(FSComp.SR.optFailedToInlineValue(v.DisplayName), m)) - if v.InlineIfLambda then - warning(Error(FSComp.SR.optFailedToInlineSuggestedValue(v.DisplayName), m)) + if cenv.settings.inlineNamedFunctions then + if v.ShouldInline then + match valInfoForVal.ValExprInfo with + | UnknownValue -> error(Error(FSComp.SR.optFailedToInlineValue(v.DisplayName), m)) + | _ -> warning(Error(FSComp.SR.optFailedToInlineValue(v.DisplayName), m)) + + if v.InlineIfLambda then + warning(Error(FSComp.SR.optFailedToInlineSuggestedValue(v.DisplayName), m)) expr, (AddValEqualityInfo g m v { Info=valInfoForVal.ValExprInfo diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs index f1ef78da738..a8184b562f5 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/DebugInlineAsCall.fs @@ -1532,3 +1532,37 @@ let main _ = |> asExe |> compileAndRun |> shouldSucceed + + [] + let ``InlineIfLambda 01 - Debug`` () = + FSharp """ +let inline apply ([] f: int -> int) (x: int) : int = + f x + +[] +let main _ = + let result = apply (fun i -> i + 1) 5 + if result = 6 then 0 else 1 +""" + |> withDebug + |> withNoOptimize + |> asExe + |> compileAndRun + |> verifyILContains ["call int32 Test::apply(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,"] + |> shouldSucceed + + [] + let ``InlineIfLambda 02 - Release`` () = + FSharp """ +let inline apply ([] f: int -> int) (x: int) : int = + f x + +[] +let main _ = + let result = apply (fun i -> i + 1) 5 + if result = 6 then 0 else 1 +""" + |> asExe + |> compile + |> shouldSucceed + |> verifyILNotPresent ["call int32 Test::apply(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,"] diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/Lock01.fs.RealInternalSignatureOff.OptimizeOff.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/Lock01.fs.RealInternalSignatureOff.OptimizeOff.il.bsl index 1e2b6f38e6e..c6dff60aed2 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/Lock01.fs.RealInternalSignatureOff.OptimizeOff.il.bsl +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/Lock01.fs.RealInternalSignatureOff.OptimizeOff.il.bsl @@ -38,6 +38,40 @@ extends [runtime]System.Object { .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable sealed nested assembly beforefieldinit clo@20 + extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 + { + .field static assembly initonly class assembly/clo@20 @_instance + .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 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::.ctor() + 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 + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ret + } + + .method private specialname rtspecialname static void .cctor() cil managed + { + + .maxstack 10 + IL_0000: newobj instance void assembly/clo@20::.ctor() + IL_0005: stsfld class assembly/clo@20 assembly/clo@20::@_instance + IL_000a: ret + } + + } + .method public specialname static object get_o() cil managed { @@ -69,35 +103,42 @@ .maxstack 4 .locals init (object V_0, object V_1, - bool V_2) + class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 V_2, + bool V_3) IL_0000: newobj instance void [runtime]System.Object::.ctor() IL_0005: dup IL_0006: stsfld object ''.$assembly::o@19 IL_000b: stloc.0 IL_000c: call object assembly::get_o() IL_0011: stloc.1 - IL_0012: ldc.i4.0 - IL_0013: stloc.2 + IL_0012: ldsfld class assembly/clo@20 assembly/clo@20::@_instance + IL_0017: stloc.2 + IL_0018: ldc.i4.0 + IL_0019: stloc.3 .try { - IL_0014: ldloc.1 - IL_0015: ldloca.s V_2 - IL_0017: call void [netstandard]System.Threading.Monitor::Enter(object, + IL_001a: ldloc.1 + IL_001b: ldloca.s V_3 + IL_001d: call void [netstandard]System.Threading.Monitor::Enter(object, bool&) - IL_001c: leave.s IL_0029 + IL_0022: ldloc.2 + IL_0023: ldnull + IL_0024: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0029: pop + IL_002a: leave.s IL_0037 } finally { - IL_001e: ldloc.2 - IL_001f: brfalse.s IL_0028 + IL_002c: ldloc.3 + IL_002d: brfalse.s IL_0036 - IL_0021: ldloc.1 - IL_0022: call void [netstandard]System.Threading.Monitor::Exit(object) - IL_0027: endfinally - IL_0028: endfinally + IL_002f: ldloc.1 + IL_0030: call void [netstandard]System.Threading.Monitor::Exit(object) + IL_0035: endfinally + IL_0036: endfinally } - IL_0029: ret + IL_0037: ret } } @@ -106,4 +147,3 @@ - diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/Lock01.fs.RealInternalSignatureOff.il.net472.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/Lock01.fs.RealInternalSignatureOff.il.net472.bsl index 804af13e153..1a3d83b9c45 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/Lock01.fs.RealInternalSignatureOff.il.net472.bsl +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/Lock01.fs.RealInternalSignatureOff.il.net472.bsl @@ -8,7 +8,7 @@ .assembly extern netstandard { .publickeytoken = (CC 7B 13 FF CD 2D DD 51 ) - .ver 2:0:0:0 + .ver 2:1:0:0 } .assembly assembly { @@ -21,16 +21,6 @@ .hash algorithm 0x00008004 .ver 0:0:0:0 -} -.mresource public FSharpSignatureCompressedData.assembly -{ - - -} -.mresource public FSharpOptimizationCompressedData.assembly -{ - - } .module assembly.exe @@ -48,6 +38,40 @@ extends [runtime]System.Object { .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable sealed nested assembly beforefieldinit clo@20 + extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 + { + .field static assembly initonly class assembly/clo@20 @_instance + .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 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::.ctor() + 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 + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ret + } + + .method private specialname rtspecialname static void .cctor() cil managed + { + + .maxstack 10 + IL_0000: newobj instance void assembly/clo@20::.ctor() + IL_0005: stsfld class assembly/clo@20 assembly/clo@20::@_instance + IL_000a: ret + } + + } + .method public specialname static object get_o() cil managed { @@ -79,35 +103,42 @@ .maxstack 4 .locals init (object V_0, object V_1, - bool V_2) + class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 V_2, + bool V_3) IL_0000: newobj instance void [runtime]System.Object::.ctor() IL_0005: dup IL_0006: stsfld object ''.$assembly::o@19 IL_000b: stloc.0 IL_000c: call object assembly::get_o() IL_0011: stloc.1 - IL_0012: ldc.i4.0 - IL_0013: stloc.2 + IL_0012: ldsfld class assembly/clo@20 assembly/clo@20::@_instance + IL_0017: stloc.2 + IL_0018: ldc.i4.0 + IL_0019: stloc.3 .try { - IL_0014: ldloc.1 - IL_0015: ldloca.s V_2 - IL_0017: call void [netstandard]System.Threading.Monitor::Enter(object, + IL_001a: ldloc.1 + IL_001b: ldloca.s V_3 + IL_001d: call void [netstandard]System.Threading.Monitor::Enter(object, bool&) - IL_001c: leave.s IL_0029 + IL_0022: ldloc.2 + IL_0023: ldnull + IL_0024: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0029: pop + IL_002a: leave.s IL_0037 } finally { - IL_001e: ldloc.2 - IL_001f: brfalse.s IL_0028 + IL_002c: ldloc.3 + IL_002d: brfalse.s IL_0036 - IL_0021: ldloc.1 - IL_0022: call void [netstandard]System.Threading.Monitor::Exit(object) - IL_0027: endfinally - IL_0028: endfinally + IL_002f: ldloc.1 + IL_0030: call void [netstandard]System.Threading.Monitor::Exit(object) + IL_0035: endfinally + IL_0036: endfinally } - IL_0029: ret + IL_0037: ret } } diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/Lock01.fs.RealInternalSignatureOn.OptimizeOff.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/Lock01.fs.RealInternalSignatureOn.OptimizeOff.il.bsl index f108d21da06..4bda3dfab02 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/Lock01.fs.RealInternalSignatureOn.OptimizeOff.il.bsl +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/Lock01.fs.RealInternalSignatureOn.OptimizeOff.il.bsl @@ -38,6 +38,40 @@ extends [runtime]System.Object { .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable sealed nested assembly beforefieldinit clo@20 + extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 + { + .field static assembly initonly class assembly/clo@20 @_instance + .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 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::.ctor() + 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 + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ret + } + + .method private specialname rtspecialname static void .cctor() cil managed + { + + .maxstack 10 + IL_0000: newobj instance void assembly/clo@20::.ctor() + IL_0005: stsfld class assembly/clo@20 assembly/clo@20::@_instance + IL_000a: ret + } + + } + .field static assembly object o@19 .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) .method public specialname static object get_o() cil managed @@ -64,33 +98,40 @@ .maxstack 4 .locals init (object V_0, - bool V_1) + class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 V_1, + bool V_2) IL_0000: newobj instance void [runtime]System.Object::.ctor() IL_0005: stsfld object assembly::o@19 IL_000a: call object assembly::get_o() IL_000f: stloc.0 - IL_0010: ldc.i4.0 - IL_0011: stloc.1 + IL_0010: ldsfld class assembly/clo@20 assembly/clo@20::@_instance + IL_0015: stloc.1 + IL_0016: ldc.i4.0 + IL_0017: stloc.2 .try { - IL_0012: ldloc.0 - IL_0013: ldloca.s V_1 - IL_0015: call void [netstandard]System.Threading.Monitor::Enter(object, + IL_0018: ldloc.0 + IL_0019: ldloca.s V_2 + IL_001b: call void [netstandard]System.Threading.Monitor::Enter(object, bool&) - IL_001a: leave.s IL_0027 + IL_0020: ldloc.1 + IL_0021: ldnull + IL_0022: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0027: pop + IL_0028: leave.s IL_0035 } finally { - IL_001c: ldloc.1 - IL_001d: brfalse.s IL_0026 + IL_002a: ldloc.2 + IL_002b: brfalse.s IL_0034 - IL_001f: ldloc.0 - IL_0020: call void [netstandard]System.Threading.Monitor::Exit(object) - IL_0025: endfinally - IL_0026: endfinally + IL_002d: ldloc.0 + IL_002e: call void [netstandard]System.Threading.Monitor::Exit(object) + IL_0033: endfinally + IL_0034: endfinally } - IL_0027: ret + IL_0035: ret } .property object o() @@ -122,4 +163,3 @@ - diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/Lock01.fs.RealInternalSignatureOn.il.net472.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/Lock01.fs.RealInternalSignatureOn.il.net472.bsl index 2e8764d5c4e..683e5e3ae72 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/Lock01.fs.RealInternalSignatureOn.il.net472.bsl +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/Lock01.fs.RealInternalSignatureOn.il.net472.bsl @@ -8,7 +8,7 @@ .assembly extern netstandard { .publickeytoken = (CC 7B 13 FF CD 2D DD 51 ) - .ver 2:0:0:0 + .ver 2:1:0:0 } .assembly assembly { @@ -21,16 +21,6 @@ .hash algorithm 0x00008004 .ver 0:0:0:0 -} -.mresource public FSharpSignatureCompressedData.assembly -{ - - -} -.mresource public FSharpOptimizationCompressedData.assembly -{ - - } .module assembly.exe @@ -48,6 +38,40 @@ extends [runtime]System.Object { .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable sealed nested assembly beforefieldinit clo@20 + extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 + { + .field static assembly initonly class assembly/clo@20 @_instance + .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 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::.ctor() + 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 + { + + .maxstack 8 + IL_0000: ldnull + IL_0001: ret + } + + .method private specialname rtspecialname static void .cctor() cil managed + { + + .maxstack 10 + IL_0000: newobj instance void assembly/clo@20::.ctor() + IL_0005: stsfld class assembly/clo@20 assembly/clo@20::@_instance + IL_000a: ret + } + + } + .field static assembly object o@19 .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) .method public specialname static object get_o() cil managed @@ -74,33 +98,40 @@ .maxstack 4 .locals init (object V_0, - bool V_1) + class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 V_1, + bool V_2) IL_0000: newobj instance void [runtime]System.Object::.ctor() IL_0005: stsfld object assembly::o@19 IL_000a: call object assembly::get_o() IL_000f: stloc.0 - IL_0010: ldc.i4.0 - IL_0011: stloc.1 + IL_0010: ldsfld class assembly/clo@20 assembly/clo@20::@_instance + IL_0015: stloc.1 + IL_0016: ldc.i4.0 + IL_0017: stloc.2 .try { - IL_0012: ldloc.0 - IL_0013: ldloca.s V_1 - IL_0015: call void [netstandard]System.Threading.Monitor::Enter(object, + IL_0018: ldloc.0 + IL_0019: ldloca.s V_2 + IL_001b: call void [netstandard]System.Threading.Monitor::Enter(object, bool&) - IL_001a: leave.s IL_0027 + IL_0020: ldloc.1 + IL_0021: ldnull + IL_0022: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0) + IL_0027: pop + IL_0028: leave.s IL_0035 } finally { - IL_001c: ldloc.1 - IL_001d: brfalse.s IL_0026 + IL_002a: ldloc.2 + IL_002b: brfalse.s IL_0034 - IL_001f: ldloc.0 - IL_0020: call void [netstandard]System.Threading.Monitor::Exit(object) - IL_0025: endfinally - IL_0026: endfinally + IL_002d: ldloc.0 + IL_002e: call void [netstandard]System.Threading.Monitor::Exit(object) + IL_0033: endfinally + IL_0034: endfinally } - IL_0027: ret + IL_0035: ret } .property object o() From 28cd8e562592c04ca6a709ea6c7766c9ffe568de Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Tue, 21 Apr 2026 17:14:07 +0200 Subject: [PATCH 32/35] Rename inlineNamedFunctions to alwaysInline --- src/Compiler/CodeGen/IlxGen.fs | 8 +++--- src/Compiler/CodeGen/IlxGen.fsi | 4 +-- src/Compiler/Driver/CompilerConfig.fs | 8 +++--- src/Compiler/Driver/CompilerConfig.fsi | 4 +-- src/Compiler/Driver/CompilerOptions.fs | 6 ++--- src/Compiler/Driver/OptimizeInputs.fs | 4 +-- src/Compiler/FSComp.txt | 2 +- src/Compiler/Optimize/Optimizer.fs | 22 ++++++++-------- src/Compiler/Optimize/Optimizer.fsi | 2 +- src/Compiler/xlf/FSComp.txt.cs.xlf | 26 +++++++++---------- src/Compiler/xlf/FSComp.txt.de.xlf | 26 +++++++++---------- src/Compiler/xlf/FSComp.txt.es.xlf | 26 +++++++++---------- src/Compiler/xlf/FSComp.txt.fr.xlf | 26 +++++++++---------- src/Compiler/xlf/FSComp.txt.it.xlf | 26 +++++++++---------- src/Compiler/xlf/FSComp.txt.ja.xlf | 26 +++++++++---------- src/Compiler/xlf/FSComp.txt.ko.xlf | 26 +++++++++---------- src/Compiler/xlf/FSComp.txt.pl.xlf | 26 +++++++++---------- src/Compiler/xlf/FSComp.txt.pt-BR.xlf | 26 +++++++++---------- src/Compiler/xlf/FSComp.txt.ru.xlf | 26 +++++++++---------- src/Compiler/xlf/FSComp.txt.tr.xlf | 26 +++++++++---------- src/Compiler/xlf/FSComp.txt.zh-Hans.xlf | 26 +++++++++---------- src/Compiler/xlf/FSComp.txt.zh-Hant.xlf | 26 +++++++++---------- src/FSharp.Build/Fsc.fs | 14 +++++----- src/FSharp.Build/Microsoft.FSharp.Targets | 2 +- .../fsc/misc/compiler_help_output.bsl | 1 + .../expected-help-output.bsl | 1 + 26 files changed, 209 insertions(+), 207 deletions(-) diff --git a/src/Compiler/CodeGen/IlxGen.fs b/src/Compiler/CodeGen/IlxGen.fs index c1b181522c3..17611e15161 100644 --- a/src/Compiler/CodeGen/IlxGen.fs +++ b/src/Compiler/CodeGen/IlxGen.fs @@ -270,7 +270,7 @@ type IlxGenOptions = /// When set to true, the IlxGen will delay generation of method bodies and generated them later in parallel (parallelized across files) parallelIlxGenEnabled: bool - inlineNamedFunctions: bool + alwaysInline: bool } /// Compilation environment for compiling a fragment of an assembly @@ -5695,13 +5695,13 @@ and GenTraitCall (cenv: cenv) cgbuf eenv (traitInfo: TraitConstraintInfo, argExp | None -> - // When inlineNamedFunctions is true, all trait calls should be resolved via witnesses in scope. - // When inlineNamedFunctions is false, inline functions are kept as calls rather than inlined. + // When alwaysInline is true, all trait calls should be resolved via witnesses in scope. + // When alwaysInline is false, inline functions are kept as calls rather than inlined. // Their witness arguments may contain TraitCall operations for constraints that were resolved // without a witness (e.g., when the constraint is satisfied by a known concrete type). // In such cases, generateWitnesses can be true (because other witnesses are in scope) but // the specific trait's witness is not found. Fall through to the constraint solver to resolve it. - assert (not generateWitnesses || not cenv.options.inlineNamedFunctions) + assert (not generateWitnesses || not cenv.options.alwaysInline) let exprOpt = CommitOperationResult(ConstraintSolver.CodegenWitnessExprForTraitConstraint cenv.tcVal g cenv.amap m traitInfo argExprs) diff --git a/src/Compiler/CodeGen/IlxGen.fsi b/src/Compiler/CodeGen/IlxGen.fsi index abf5320b697..74cbe72d3fe 100644 --- a/src/Compiler/CodeGen/IlxGen.fsi +++ b/src/Compiler/CodeGen/IlxGen.fsi @@ -62,8 +62,8 @@ type internal IlxGenOptions = /// When set to true, the IlxGen will delay generation of method bodies and generate them later in parallel (parallelized across files) parallelIlxGenEnabled: bool - /// Indicates if inline named functions are being inlined or emitted as calls - inlineNamedFunctions: bool + /// Indicates if inline functions are being inlined or emitted as calls + alwaysInline: bool } /// The results of the ILX compilation of one fragment of an assembly diff --git a/src/Compiler/Driver/CompilerConfig.fs b/src/Compiler/Driver/CompilerConfig.fs index ed8d7914497..ccf0c1fa4f1 100644 --- a/src/Compiler/Driver/CompilerConfig.fs +++ b/src/Compiler/Driver/CompilerConfig.fs @@ -600,7 +600,7 @@ type TcConfigBuilder = mutable strictIndentation: bool option - mutable inlineNamedFunctions: bool option + mutable alwaysInline: bool option mutable exename: string option @@ -855,7 +855,7 @@ type TcConfigBuilder = dumpSignatureData = false realsig = false strictIndentation = None - inlineNamedFunctions = None + alwaysInline = None compilationMode = TcGlobals.CompilationMode.Unset } @@ -1257,8 +1257,8 @@ type TcConfig private (data: TcConfigBuilder, validate: bool) = member _.FxResolver = data.FxResolver member _.strictIndentation = data.strictIndentation - member _.inlineNamedFunctions = - data.inlineNamedFunctions + member _.alwaysInline = + data.alwaysInline |> Option.defaultValue ( not data.debuginfo || data.optSettings.LocalOptimizationsEnabled diff --git a/src/Compiler/Driver/CompilerConfig.fsi b/src/Compiler/Driver/CompilerConfig.fsi index b81a37917c5..9f19b8e59ba 100644 --- a/src/Compiler/Driver/CompilerConfig.fsi +++ b/src/Compiler/Driver/CompilerConfig.fsi @@ -472,7 +472,7 @@ type TcConfigBuilder = mutable strictIndentation: bool option - mutable inlineNamedFunctions: bool option + mutable alwaysInline: bool option mutable exename: string option @@ -816,7 +816,7 @@ type TcConfig = member strictIndentation: bool option - member inlineNamedFunctions: bool + member alwaysInline: bool member GetTargetFrameworkDirectories: unit -> string list diff --git a/src/Compiler/Driver/CompilerOptions.fs b/src/Compiler/Driver/CompilerOptions.fs index 0ba0afb60ca..f54f36fa7f9 100644 --- a/src/Compiler/Driver/CompilerOptions.fs +++ b/src/Compiler/Driver/CompilerOptions.fs @@ -1209,11 +1209,11 @@ let languageFlags tcConfigB = ) CompilerOption( - "inline-named-functions", + "always-inline", tagNone, - OptionSwitch(fun switch -> tcConfigB.inlineNamedFunctions <- Some(switch = OptionSwitch.On)), + OptionSwitch(fun switch -> tcConfigB.alwaysInline <- Some(switch = OptionSwitch.On)), None, - Some(FSComp.SR.optsInlineNamedFunctions ()) + Some(FSComp.SR.optsAlwaysInline ()) ) ] diff --git a/src/Compiler/Driver/OptimizeInputs.fs b/src/Compiler/Driver/OptimizeInputs.fs index 120285358a3..d04ae06be01 100644 --- a/src/Compiler/Driver/OptimizeInputs.fs +++ b/src/Compiler/Driver/OptimizeInputs.fs @@ -327,7 +327,7 @@ let ApplyAllOptimizations // Only do abstractBigTargets in the first phase, and only when TLR is on. abstractBigTargets = tcConfig.doTLR reportingPhase = true - inlineNamedFunctions = tcConfig.inlineNamedFunctions + alwaysInline = tcConfig.alwaysInline } // Only do these two steps in the first phase. @@ -579,7 +579,7 @@ let GenerateIlxCode isInteractiveItExpr = isInteractiveItExpr alwaysCallVirt = tcConfig.alwaysCallVirt parallelIlxGenEnabled = tcConfig.parallelIlxGen - inlineNamedFunctions = tcConfig.inlineNamedFunctions + alwaysInline = tcConfig.alwaysInline } ilxGenerator.GenerateCode(ilxGenOpts, optimizedImpls, topAttrs.assemblyAttrs, topAttrs.netModuleAttrs) diff --git a/src/Compiler/FSComp.txt b/src/Compiler/FSComp.txt index ab355660224..f8926a28543 100644 --- a/src/Compiler/FSComp.txt +++ b/src/Compiler/FSComp.txt @@ -1561,7 +1561,7 @@ optsSetLangVersion,"Specify language version such as 'latest' or 'preview'." optsDisableLanguageFeature,"Disable a specific language feature by name." optsSupportedLangVersions,"Supported language versions:" optsStrictIndentation,"Override indentation rules implied by the language version (%s by default)" -optsInlineNamedFunctions,"Inline named 'inline' functions" +optsAlwaysInline,"Always inline 'inline' functions" nativeResourceFormatError,"Stream does not begin with a null resource and is not in '.RES' format." nativeResourceHeaderMalformed,"Resource header beginning at offset %s is malformed." formatDashItem," - %s" diff --git a/src/Compiler/Optimize/Optimizer.fs b/src/Compiler/Optimize/Optimizer.fs index 759d418cdf6..1468ea7a292 100644 --- a/src/Compiler/Optimize/Optimizer.fs +++ b/src/Compiler/Optimize/Optimizer.fs @@ -329,7 +329,7 @@ type OptimizationSettings = processingMode : OptimizationProcessingMode - inlineNamedFunctions: bool + alwaysInline: bool } static member Defaults = @@ -347,7 +347,7 @@ type OptimizationSettings = reportHasEffect = false reportTotalSizes = false processingMode = OptimizationProcessingMode.Parallel - inlineNamedFunctions = false + alwaysInline = false } /// Determines if JIT optimizations are enabled @@ -513,7 +513,7 @@ let CheckInlineValueIsComplete (v: Val) res = //System.Diagnostics.Debug.Assert(false, sprintf "Break for incomplete inline value %s" v.DisplayName) let check (cenv: cenv) (vref: ValRef) (res: ValInfo) = - if cenv.settings.inlineNamedFunctions then + if cenv.settings.alwaysInline then CheckInlineValueIsComplete vref.Deref res.ValExprInfo (vref, res) @@ -1370,7 +1370,7 @@ let AbstractLazyModulInfoByHiding isAssemblyBoundary (cenv: cenv) mhi = Zset.exists hiddenTyconRepr fvs.FreeLocalTyconReprs || Zset.exists hiddenRecdField fvs.FreeRecdFields || Zset.exists hiddenUnionCase fvs.FreeUnionCases || - (cenv.settings.inlineNamedFunctions && + (cenv.settings.alwaysInline && ((isAssemblyBoundary && not (freeVarsAllPublic fvs)) || Zset.exists hiddenVal fvs.FreeLocals || Zset.exists hiddenTycon fvs.FreeTyvars.FreeTycons))) -> @@ -1415,7 +1415,7 @@ let AbstractLazyModulInfoByHiding isAssemblyBoundary (cenv: cenv) mhi = ValInfos(ss.ValInfos.Entries |> Seq.filter (fun (vref, _) -> not (hiddenVal vref.Deref) || - (not cenv.settings.inlineNamedFunctions && vref.Deref.ShouldInline)) + (not cenv.settings.alwaysInline && vref.Deref.ShouldInline)) |> Seq.map (fun (vref, e) -> check cenv vref (abstractValInfo e) )) } and abstractLazyModulInfo (ss: LazyModuleInfo) = @@ -3101,8 +3101,8 @@ and TryOptimizeVal cenv env (vOpt: ValRef option, shouldInline, inlineIfLambda, Some (remarkExpr m (copyExpr g CloneAllAndMarkExprValsAsCompilerGenerated expr)) | CurriedLambdaValue (_, _, _, expr, _) when - shouldInline && (cenv.settings.inlineNamedFunctions || Option.exists (shouldForceInlineInDebug cenv.g) vOpt) || - inlineIfLambda && cenv.settings.inlineNamedFunctions -> + shouldInline && (cenv.settings.alwaysInline || Option.exists (shouldForceInlineInDebug cenv.g) vOpt) || + inlineIfLambda && cenv.settings.alwaysInline -> let fvs = freeInExpr CollectLocals expr if fvs.UsesMethodLocalConstructs then // Discarding lambda for binding because uses protected members --- TBD: Should we warn or error here @@ -3114,11 +3114,11 @@ and TryOptimizeVal cenv env (vOpt: ValRef option, shouldInline, inlineIfLambda, | TupleValue _ | UnionCaseValue _ | RecdValue _ when shouldInline -> failwith "tuple, union and record values cannot be marked 'inline'" - | UnknownValue when shouldInline && cenv.settings.inlineNamedFunctions -> + | UnknownValue when shouldInline && cenv.settings.alwaysInline -> warning(Error(FSComp.SR.optValueMarkedInlineHasUnexpectedValue(), m)) None - | _ when shouldInline && cenv.settings.inlineNamedFunctions -> + | _ when shouldInline && cenv.settings.alwaysInline -> warning(Error(FSComp.SR.optValueMarkedInlineCouldNotBeInlined(), m)) None @@ -3164,7 +3164,7 @@ and OptimizeVal cenv env expr (v: ValRef, m) = e, AddValEqualityInfo g m v einfo | None -> - if cenv.settings.inlineNamedFunctions then + if cenv.settings.alwaysInline then if v.ShouldInline then match valInfoForVal.ValExprInfo with | UnknownValue -> error(Error(FSComp.SR.optFailedToInlineValue(v.DisplayName), m)) @@ -3456,7 +3456,7 @@ and TryDevirtualizeApplication cenv env (f, tyargs, args, m) = and TryInlineApplication cenv env finfo (valExpr: Expr) (tyargs: TType list, args: Expr list, m) = let g = cenv.g - match cenv.settings.inlineNamedFunctions, stripExpr valExpr with + match cenv.settings.alwaysInline, stripExpr valExpr with | false, Expr.Val(vref, _, _) when vref.ShouldInline && not (shouldForceInlineInDebug cenv.g vref) -> let hasNoTraits = let tps, _ = tryDestForallTy g vref.Type diff --git a/src/Compiler/Optimize/Optimizer.fsi b/src/Compiler/Optimize/Optimizer.fsi index 10335e93a64..1458f5a41b0 100644 --- a/src/Compiler/Optimize/Optimizer.fsi +++ b/src/Compiler/Optimize/Optimizer.fsi @@ -52,7 +52,7 @@ type OptimizationSettings = processingMode: OptimizationProcessingMode - inlineNamedFunctions: bool + alwaysInline: bool } member JitOptimizationsEnabled: bool diff --git a/src/Compiler/xlf/FSComp.txt.cs.xlf b/src/Compiler/xlf/FSComp.txt.cs.xlf index ac2eccfb559..e613f118ef6 100644 --- a/src/Compiler/xlf/FSComp.txt.cs.xlf +++ b/src/Compiler/xlf/FSComp.txt.cs.xlf @@ -1037,9 +1037,9 @@ Zobrazí povolené hodnoty pro jazykovou verzi. - - Inline named 'inline' functions - Inline named 'inline' functions + + Always inline 'inline' functions + Always inline 'inline' functions @@ -8977,16 +8977,16 @@ This expression is a function value. When used in an interpolated string it will be formatted using its 'ToString' method, which is likely not the intended behavior. Consider applying the function to its arguments. - - '{0}' cannot be the final expression in a computation expression. Finish with 'return', 'return!', or a simple expression. - '{0}' cannot be the final expression in a computation expression. Finish with 'return', 'return!', or a simple expression. - - - - This list expression contains a single tuple element. Did you mean to use ';' instead of ',' to separate list elements? - This list expression contains a single tuple element. Did you mean to use ';' instead of ',' to separate list elements? - - + + '{0}' cannot be the final expression in a computation expression. Finish with 'return', 'return!', or a simple expression. + '{0}' cannot be the final expression in a computation expression. Finish with 'return', 'return!', or a simple expression. + + + + This list expression contains a single tuple element. Did you mean to use ';' instead of ',' to separate list elements? + This list expression contains a single tuple element. Did you mean to use ';' instead of ',' to separate list elements? + + \ No newline at end of file diff --git a/src/Compiler/xlf/FSComp.txt.de.xlf b/src/Compiler/xlf/FSComp.txt.de.xlf index c0ab56aa7ac..32c28d30b46 100644 --- a/src/Compiler/xlf/FSComp.txt.de.xlf +++ b/src/Compiler/xlf/FSComp.txt.de.xlf @@ -1037,9 +1037,9 @@ Anzeigen der zulässigen Werte für die Sprachversion. - - Inline named 'inline' functions - Inline named 'inline' functions + + Always inline 'inline' functions + Always inline 'inline' functions @@ -8977,16 +8977,16 @@ This expression is a function value. When used in an interpolated string it will be formatted using its 'ToString' method, which is likely not the intended behavior. Consider applying the function to its arguments. - - '{0}' cannot be the final expression in a computation expression. Finish with 'return', 'return!', or a simple expression. - '{0}' cannot be the final expression in a computation expression. Finish with 'return', 'return!', or a simple expression. - - - - This list expression contains a single tuple element. Did you mean to use ';' instead of ',' to separate list elements? - This list expression contains a single tuple element. Did you mean to use ';' instead of ',' to separate list elements? - - + + '{0}' cannot be the final expression in a computation expression. Finish with 'return', 'return!', or a simple expression. + '{0}' cannot be the final expression in a computation expression. Finish with 'return', 'return!', or a simple expression. + + + + This list expression contains a single tuple element. Did you mean to use ';' instead of ',' to separate list elements? + This list expression contains a single tuple element. Did you mean to use ';' instead of ',' to separate list elements? + + \ No newline at end of file diff --git a/src/Compiler/xlf/FSComp.txt.es.xlf b/src/Compiler/xlf/FSComp.txt.es.xlf index 8e9678d60c8..32132d18525 100644 --- a/src/Compiler/xlf/FSComp.txt.es.xlf +++ b/src/Compiler/xlf/FSComp.txt.es.xlf @@ -1037,9 +1037,9 @@ Muestra los valores permitidos para la versión del lenguaje. - - Inline named 'inline' functions - Inline named 'inline' functions + + Always inline 'inline' functions + Always inline 'inline' functions @@ -8977,16 +8977,16 @@ This expression is a function value. When used in an interpolated string it will be formatted using its 'ToString' method, which is likely not the intended behavior. Consider applying the function to its arguments. - - '{0}' cannot be the final expression in a computation expression. Finish with 'return', 'return!', or a simple expression. - '{0}' cannot be the final expression in a computation expression. Finish with 'return', 'return!', or a simple expression. - - - - This list expression contains a single tuple element. Did you mean to use ';' instead of ',' to separate list elements? - This list expression contains a single tuple element. Did you mean to use ';' instead of ',' to separate list elements? - - + + '{0}' cannot be the final expression in a computation expression. Finish with 'return', 'return!', or a simple expression. + '{0}' cannot be the final expression in a computation expression. Finish with 'return', 'return!', or a simple expression. + + + + This list expression contains a single tuple element. Did you mean to use ';' instead of ',' to separate list elements? + This list expression contains a single tuple element. Did you mean to use ';' instead of ',' to separate list elements? + + \ No newline at end of file diff --git a/src/Compiler/xlf/FSComp.txt.fr.xlf b/src/Compiler/xlf/FSComp.txt.fr.xlf index 4bce8d1951f..336f0c77419 100644 --- a/src/Compiler/xlf/FSComp.txt.fr.xlf +++ b/src/Compiler/xlf/FSComp.txt.fr.xlf @@ -1037,9 +1037,9 @@ Affichez les valeurs autorisées pour la version du langage. - - Inline named 'inline' functions - Inline named 'inline' functions + + Always inline 'inline' functions + Always inline 'inline' functions @@ -8977,16 +8977,16 @@ This expression is a function value. When used in an interpolated string it will be formatted using its 'ToString' method, which is likely not the intended behavior. Consider applying the function to its arguments. - - '{0}' cannot be the final expression in a computation expression. Finish with 'return', 'return!', or a simple expression. - '{0}' cannot be the final expression in a computation expression. Finish with 'return', 'return!', or a simple expression. - - - - This list expression contains a single tuple element. Did you mean to use ';' instead of ',' to separate list elements? - This list expression contains a single tuple element. Did you mean to use ';' instead of ',' to separate list elements? - - + + '{0}' cannot be the final expression in a computation expression. Finish with 'return', 'return!', or a simple expression. + '{0}' cannot be the final expression in a computation expression. Finish with 'return', 'return!', or a simple expression. + + + + This list expression contains a single tuple element. Did you mean to use ';' instead of ',' to separate list elements? + This list expression contains a single tuple element. Did you mean to use ';' instead of ',' to separate list elements? + + \ No newline at end of file diff --git a/src/Compiler/xlf/FSComp.txt.it.xlf b/src/Compiler/xlf/FSComp.txt.it.xlf index f7de737a99d..1844b5d3dd8 100644 --- a/src/Compiler/xlf/FSComp.txt.it.xlf +++ b/src/Compiler/xlf/FSComp.txt.it.xlf @@ -1037,9 +1037,9 @@ Visualizzare i valori consentiti per la versione della lingua. - - Inline named 'inline' functions - Inline named 'inline' functions + + Always inline 'inline' functions + Always inline 'inline' functions @@ -8977,16 +8977,16 @@ This expression is a function value. When used in an interpolated string it will be formatted using its 'ToString' method, which is likely not the intended behavior. Consider applying the function to its arguments. - - '{0}' cannot be the final expression in a computation expression. Finish with 'return', 'return!', or a simple expression. - '{0}' cannot be the final expression in a computation expression. Finish with 'return', 'return!', or a simple expression. - - - - This list expression contains a single tuple element. Did you mean to use ';' instead of ',' to separate list elements? - This list expression contains a single tuple element. Did you mean to use ';' instead of ',' to separate list elements? - - + + '{0}' cannot be the final expression in a computation expression. Finish with 'return', 'return!', or a simple expression. + '{0}' cannot be the final expression in a computation expression. Finish with 'return', 'return!', or a simple expression. + + + + This list expression contains a single tuple element. Did you mean to use ';' instead of ',' to separate list elements? + This list expression contains a single tuple element. Did you mean to use ';' instead of ',' to separate list elements? + + \ No newline at end of file diff --git a/src/Compiler/xlf/FSComp.txt.ja.xlf b/src/Compiler/xlf/FSComp.txt.ja.xlf index 0c9b2825081..f0f6d386924 100644 --- a/src/Compiler/xlf/FSComp.txt.ja.xlf +++ b/src/Compiler/xlf/FSComp.txt.ja.xlf @@ -1037,9 +1037,9 @@ 言語バージョンで許可されている値を表示します。 - - Inline named 'inline' functions - Inline named 'inline' functions + + Always inline 'inline' functions + Always inline 'inline' functions @@ -8977,16 +8977,16 @@ This expression is a function value. When used in an interpolated string it will be formatted using its 'ToString' method, which is likely not the intended behavior. Consider applying the function to its arguments. - - '{0}' cannot be the final expression in a computation expression. Finish with 'return', 'return!', or a simple expression. - '{0}' cannot be the final expression in a computation expression. Finish with 'return', 'return!', or a simple expression. - - - - This list expression contains a single tuple element. Did you mean to use ';' instead of ',' to separate list elements? - This list expression contains a single tuple element. Did you mean to use ';' instead of ',' to separate list elements? - - + + '{0}' cannot be the final expression in a computation expression. Finish with 'return', 'return!', or a simple expression. + '{0}' cannot be the final expression in a computation expression. Finish with 'return', 'return!', or a simple expression. + + + + This list expression contains a single tuple element. Did you mean to use ';' instead of ',' to separate list elements? + This list expression contains a single tuple element. Did you mean to use ';' instead of ',' to separate list elements? + + \ No newline at end of file diff --git a/src/Compiler/xlf/FSComp.txt.ko.xlf b/src/Compiler/xlf/FSComp.txt.ko.xlf index a602a54ae29..72e1392e587 100644 --- a/src/Compiler/xlf/FSComp.txt.ko.xlf +++ b/src/Compiler/xlf/FSComp.txt.ko.xlf @@ -1037,9 +1037,9 @@ 언어 버전에 허용되는 값을 표시합니다. - - Inline named 'inline' functions - Inline named 'inline' functions + + Always inline 'inline' functions + Always inline 'inline' functions @@ -8977,16 +8977,16 @@ This expression is a function value. When used in an interpolated string it will be formatted using its 'ToString' method, which is likely not the intended behavior. Consider applying the function to its arguments. - - '{0}' cannot be the final expression in a computation expression. Finish with 'return', 'return!', or a simple expression. - '{0}' cannot be the final expression in a computation expression. Finish with 'return', 'return!', or a simple expression. - - - - This list expression contains a single tuple element. Did you mean to use ';' instead of ',' to separate list elements? - This list expression contains a single tuple element. Did you mean to use ';' instead of ',' to separate list elements? - - + + '{0}' cannot be the final expression in a computation expression. Finish with 'return', 'return!', or a simple expression. + '{0}' cannot be the final expression in a computation expression. Finish with 'return', 'return!', or a simple expression. + + + + This list expression contains a single tuple element. Did you mean to use ';' instead of ',' to separate list elements? + This list expression contains a single tuple element. Did you mean to use ';' instead of ',' to separate list elements? + + \ No newline at end of file diff --git a/src/Compiler/xlf/FSComp.txt.pl.xlf b/src/Compiler/xlf/FSComp.txt.pl.xlf index eba3456114e..2bc3a0c3913 100644 --- a/src/Compiler/xlf/FSComp.txt.pl.xlf +++ b/src/Compiler/xlf/FSComp.txt.pl.xlf @@ -1037,9 +1037,9 @@ Wyświetl dozwolone wartości dla wersji językowej. - - Inline named 'inline' functions - Inline named 'inline' functions + + Always inline 'inline' functions + Always inline 'inline' functions @@ -8977,16 +8977,16 @@ This expression is a function value. When used in an interpolated string it will be formatted using its 'ToString' method, which is likely not the intended behavior. Consider applying the function to its arguments. - - '{0}' cannot be the final expression in a computation expression. Finish with 'return', 'return!', or a simple expression. - '{0}' cannot be the final expression in a computation expression. Finish with 'return', 'return!', or a simple expression. - - - - This list expression contains a single tuple element. Did you mean to use ';' instead of ',' to separate list elements? - This list expression contains a single tuple element. Did you mean to use ';' instead of ',' to separate list elements? - - + + '{0}' cannot be the final expression in a computation expression. Finish with 'return', 'return!', or a simple expression. + '{0}' cannot be the final expression in a computation expression. Finish with 'return', 'return!', or a simple expression. + + + + This list expression contains a single tuple element. Did you mean to use ';' instead of ',' to separate list elements? + This list expression contains a single tuple element. Did you mean to use ';' instead of ',' to separate list elements? + + \ No newline at end of file diff --git a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf index f14a1e9222f..11e1676d184 100644 --- a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf +++ b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf @@ -1037,9 +1037,9 @@ Exiba os valores permitidos para a versão do idioma. - - Inline named 'inline' functions - Inline named 'inline' functions + + Always inline 'inline' functions + Always inline 'inline' functions @@ -8977,16 +8977,16 @@ This expression is a function value. When used in an interpolated string it will be formatted using its 'ToString' method, which is likely not the intended behavior. Consider applying the function to its arguments. - - '{0}' cannot be the final expression in a computation expression. Finish with 'return', 'return!', or a simple expression. - '{0}' cannot be the final expression in a computation expression. Finish with 'return', 'return!', or a simple expression. - - - - This list expression contains a single tuple element. Did you mean to use ';' instead of ',' to separate list elements? - This list expression contains a single tuple element. Did you mean to use ';' instead of ',' to separate list elements? - - + + '{0}' cannot be the final expression in a computation expression. Finish with 'return', 'return!', or a simple expression. + '{0}' cannot be the final expression in a computation expression. Finish with 'return', 'return!', or a simple expression. + + + + This list expression contains a single tuple element. Did you mean to use ';' instead of ',' to separate list elements? + This list expression contains a single tuple element. Did you mean to use ';' instead of ',' to separate list elements? + + \ No newline at end of file diff --git a/src/Compiler/xlf/FSComp.txt.ru.xlf b/src/Compiler/xlf/FSComp.txt.ru.xlf index f9ec703c7a2..0069b62bcf4 100644 --- a/src/Compiler/xlf/FSComp.txt.ru.xlf +++ b/src/Compiler/xlf/FSComp.txt.ru.xlf @@ -1037,9 +1037,9 @@ Отображение допустимых значений для версии языка. - - Inline named 'inline' functions - Inline named 'inline' functions + + Always inline 'inline' functions + Always inline 'inline' functions @@ -8977,16 +8977,16 @@ This expression is a function value. When used in an interpolated string it will be formatted using its 'ToString' method, which is likely not the intended behavior. Consider applying the function to its arguments. - - '{0}' cannot be the final expression in a computation expression. Finish with 'return', 'return!', or a simple expression. - '{0}' cannot be the final expression in a computation expression. Finish with 'return', 'return!', or a simple expression. - - - - This list expression contains a single tuple element. Did you mean to use ';' instead of ',' to separate list elements? - This list expression contains a single tuple element. Did you mean to use ';' instead of ',' to separate list elements? - - + + '{0}' cannot be the final expression in a computation expression. Finish with 'return', 'return!', or a simple expression. + '{0}' cannot be the final expression in a computation expression. Finish with 'return', 'return!', or a simple expression. + + + + This list expression contains a single tuple element. Did you mean to use ';' instead of ',' to separate list elements? + This list expression contains a single tuple element. Did you mean to use ';' instead of ',' to separate list elements? + + \ No newline at end of file diff --git a/src/Compiler/xlf/FSComp.txt.tr.xlf b/src/Compiler/xlf/FSComp.txt.tr.xlf index 9c2eaaa4ad3..407aa400f3a 100644 --- a/src/Compiler/xlf/FSComp.txt.tr.xlf +++ b/src/Compiler/xlf/FSComp.txt.tr.xlf @@ -1037,9 +1037,9 @@ Dil sürümü için izin verilen değerleri görüntüleyin. - - Inline named 'inline' functions - Inline named 'inline' functions + + Always inline 'inline' functions + Always inline 'inline' functions @@ -8977,16 +8977,16 @@ This expression is a function value. When used in an interpolated string it will be formatted using its 'ToString' method, which is likely not the intended behavior. Consider applying the function to its arguments. - - '{0}' cannot be the final expression in a computation expression. Finish with 'return', 'return!', or a simple expression. - '{0}' cannot be the final expression in a computation expression. Finish with 'return', 'return!', or a simple expression. - - - - This list expression contains a single tuple element. Did you mean to use ';' instead of ',' to separate list elements? - This list expression contains a single tuple element. Did you mean to use ';' instead of ',' to separate list elements? - - + + '{0}' cannot be the final expression in a computation expression. Finish with 'return', 'return!', or a simple expression. + '{0}' cannot be the final expression in a computation expression. Finish with 'return', 'return!', or a simple expression. + + + + This list expression contains a single tuple element. Did you mean to use ';' instead of ',' to separate list elements? + This list expression contains a single tuple element. Did you mean to use ';' instead of ',' to separate list elements? + + \ No newline at end of file diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf index d468814b809..5ff68fe0253 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf @@ -1037,9 +1037,9 @@ 显示语言版本的允许值。 - - Inline named 'inline' functions - Inline named 'inline' functions + + Always inline 'inline' functions + Always inline 'inline' functions @@ -8977,16 +8977,16 @@ This expression is a function value. When used in an interpolated string it will be formatted using its 'ToString' method, which is likely not the intended behavior. Consider applying the function to its arguments. - - '{0}' cannot be the final expression in a computation expression. Finish with 'return', 'return!', or a simple expression. - '{0}' cannot be the final expression in a computation expression. Finish with 'return', 'return!', or a simple expression. - - - - This list expression contains a single tuple element. Did you mean to use ';' instead of ',' to separate list elements? - This list expression contains a single tuple element. Did you mean to use ';' instead of ',' to separate list elements? - - + + '{0}' cannot be the final expression in a computation expression. Finish with 'return', 'return!', or a simple expression. + '{0}' cannot be the final expression in a computation expression. Finish with 'return', 'return!', or a simple expression. + + + + This list expression contains a single tuple element. Did you mean to use ';' instead of ',' to separate list elements? + This list expression contains a single tuple element. Did you mean to use ';' instead of ',' to separate list elements? + + \ No newline at end of file diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf index de67f5633e9..94c8532b129 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf @@ -1037,9 +1037,9 @@ 顯示語言版本的允許值。 - - Inline named 'inline' functions - Inline named 'inline' functions + + Always inline 'inline' functions + Always inline 'inline' functions @@ -8977,16 +8977,16 @@ This expression is a function value. When used in an interpolated string it will be formatted using its 'ToString' method, which is likely not the intended behavior. Consider applying the function to its arguments. - - '{0}' cannot be the final expression in a computation expression. Finish with 'return', 'return!', or a simple expression. - '{0}' cannot be the final expression in a computation expression. Finish with 'return', 'return!', or a simple expression. - - - - This list expression contains a single tuple element. Did you mean to use ';' instead of ',' to separate list elements? - This list expression contains a single tuple element. Did you mean to use ';' instead of ',' to separate list elements? - - + + '{0}' cannot be the final expression in a computation expression. Finish with 'return', 'return!', or a simple expression. + '{0}' cannot be the final expression in a computation expression. Finish with 'return', 'return!', or a simple expression. + + + + This list expression contains a single tuple element. Did you mean to use ';' instead of ',' to separate list elements? + This list expression contains a single tuple element. Did you mean to use ';' instead of ',' to separate list elements? + + \ No newline at end of file diff --git a/src/FSharp.Build/Fsc.fs b/src/FSharp.Build/Fsc.fs index c67f56defa9..173792f0711 100644 --- a/src/FSharp.Build/Fsc.fs +++ b/src/FSharp.Build/Fsc.fs @@ -58,7 +58,7 @@ type public Fsc() as this = let mutable preferredUILang: string | null = null let mutable publicSign: bool = false let mutable provideCommandLineArgs: bool = false - let mutable inlineNamedFunctions: bool option = None + let mutable alwaysInline: bool option = None let mutable realsig: bool option = None let mutable references: ITaskItem[] = [||] let mutable referencePath: string | null = null @@ -201,8 +201,8 @@ type public Fsc() as this = else builder.AppendSwitch("--optimize-") - // InlineNamedFunctions - builder.AppendOptionalSwitch("--inline-named-functions", inlineNamedFunctions) + // AlwaysInline + builder.AppendOptionalSwitch("--always-inline", alwaysInline) // realsig builder.AppendOptionalSwitch("--realsig", realsig) @@ -564,13 +564,13 @@ type public Fsc() as this = with get () = publicSign and set (s) = publicSign <- s - // --inline-named-functions[+-] - member _.InlineNamedFunctions + // --always-inline[+-] + member _.AlwaysInline with get () = - match inlineNamedFunctions with + match alwaysInline with | Some true -> true | _ -> false - and set (b) = inlineNamedFunctions <- Some b + and set (b) = alwaysInline <- Some b // --realsig[+-] member _.RealSig diff --git a/src/FSharp.Build/Microsoft.FSharp.Targets b/src/FSharp.Build/Microsoft.FSharp.Targets index 1ad7c6fac63..eeda4889aaf 100644 --- a/src/FSharp.Build/Microsoft.FSharp.Targets +++ b/src/FSharp.Build/Microsoft.FSharp.Targets @@ -389,7 +389,7 @@ this file. PreferredUILang="$(PreferredUILang)" ProvideCommandLineArgs="$(ProvideCommandLineArgs)" PublicSign="$(PublicSign)" - InlineNamedFunctions="$(InlineNamedFunctions)" + AlwaysInline="$(AlwaysInline)" RealSig="$(RealSig)" References="@(ReferencePathWithRefAssemblies)" ReferencePath="$(ReferencePathWithRefAssemblies)" diff --git a/tests/FSharp.Compiler.ComponentTests/CompilerOptions/fsc/misc/compiler_help_output.bsl b/tests/FSharp.Compiler.ComponentTests/CompilerOptions/fsc/misc/compiler_help_output.bsl index 3cfd389dc8a..56df6419a54 100644 --- a/tests/FSharp.Compiler.ComponentTests/CompilerOptions/fsc/misc/compiler_help_output.bsl +++ b/tests/FSharp.Compiler.ComponentTests/CompilerOptions/fsc/misc/compiler_help_output.bsl @@ -84,6 +84,7 @@ Copyright (c) Microsoft Corporation. All Rights Reserved. --checked[+|-] Generate overflow checks (off by default) --define: Define conditional compilation symbols (Short form: -d) --strict-indentation[+|-] Override indentation rules implied by the language version (off by default) +--always-inline[+|-] Always inline 'inline' functions - MISCELLANEOUS - diff --git a/tests/FSharp.Compiler.Service.Tests/expected-help-output.bsl b/tests/FSharp.Compiler.Service.Tests/expected-help-output.bsl index 8b112b0dadc..bbcf59bb8f5 100644 --- a/tests/FSharp.Compiler.Service.Tests/expected-help-output.bsl +++ b/tests/FSharp.Compiler.Service.Tests/expected-help-output.bsl @@ -131,6 +131,7 @@ --strict-indentation[+|-] Override indentation rules implied by the language version (off by default) +--always-inline[+|-] Always inline 'inline' functions - MISCELLANEOUS - From 125d4a2fb11d10218ea29e4b121f9e41ce25838e Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Wed, 13 May 2026 13:00:56 +0200 Subject: [PATCH 33/35] Check optimize- only --- src/Compiler/Driver/CompilerConfig.fs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Compiler/Driver/CompilerConfig.fs b/src/Compiler/Driver/CompilerConfig.fs index ccf0c1fa4f1..c9203390de4 100644 --- a/src/Compiler/Driver/CompilerConfig.fs +++ b/src/Compiler/Driver/CompilerConfig.fs @@ -1260,8 +1260,7 @@ type TcConfig private (data: TcConfigBuilder, validate: bool) = member _.alwaysInline = data.alwaysInline |> Option.defaultValue ( - not data.debuginfo - || data.optSettings.LocalOptimizationsEnabled + data.optSettings.LocalOptimizationsEnabled || data.extraOptimizationIterations > 0 ) From c7d24eefbe3bb513612fd65a24ea06a45ebc1d83 Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Wed, 13 May 2026 18:10:35 +0200 Subject: [PATCH 34/35] Update baselines --- ...ealInternalSignatureOff.OptimizeOff.il.bsl | 52 +-- ...RealInternalSignatureOn.OptimizeOff.il.bsl | 52 +-- ...ealInternalSignatureOff.OptimizeOff.il.bsl | 145 +----- ...RealInternalSignatureOn.OptimizeOff.il.bsl | 145 +----- ...ealInternalSignatureOff.OptimizeOff.il.bsl | 127 +----- ...RealInternalSignatureOn.OptimizeOff.il.bsl | 127 +----- ...ealInternalSignatureOff.OptimizeOff.il.bsl | 414 +++--------------- ...RealInternalSignatureOn.OptimizeOff.il.bsl | 414 +++--------------- ...ealInternalSignatureOff.OptimizeOff.il.bsl | 3 +- ...RealInternalSignatureOn.OptimizeOff.il.bsl | 2 +- ...ptionalArg01.fs.OptimizeOff.il.netcore.bsl | 404 +---------------- .../ExprTests.fs | 4 +- 12 files changed, 230 insertions(+), 1659 deletions(-) diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/AsyncExpressionStepping/AsyncExpressionSteppingTest3.fs.RealInternalSignatureOff.OptimizeOff.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/AsyncExpressionStepping/AsyncExpressionSteppingTest3.fs.RealInternalSignatureOff.OptimizeOff.il.bsl index 3cd259184db..b95c997fd11 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/AsyncExpressionStepping/AsyncExpressionSteppingTest3.fs.RealInternalSignatureOff.OptimizeOff.il.bsl +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/AsyncExpressionStepping/AsyncExpressionSteppingTest3.fs.RealInternalSignatureOff.OptimizeOff.il.bsl @@ -37,42 +37,6 @@ extends [runtime]System.Object { .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) - .class auto ansi serializable sealed nested assembly beforefieldinit 'f3@10-1' - extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn> - { - .field public int32 'value' - .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - .method assembly specialname rtspecialname instance void .ctor(int32 'value') 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 ) - - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn>::.ctor() - IL_0006: ldarg.0 - IL_0007: ldarg.1 - IL_0008: stfld int32 assembly/assembly/'f3@10-1'::'value' - IL_000d: ret - } - - .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn Invoke(valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1 ctxt) cil managed - { - - .maxstack 8 - IL_0000: ldarg.1 - IL_0001: ldarg.0 - IL_0002: ldfld int32 assembly/assembly/'f3@10-1'::'value' - IL_0007: tail. - IL_0009: call class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1::Success(valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1, - !0) - IL_000e: ret - } - - } - .class auto ansi serializable sealed nested assembly beforefieldinit f3@5 extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> { @@ -100,9 +64,7 @@ .maxstack 7 .locals init (class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1 V_0, class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1 V_1, - int32 V_2, - class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder V_3, - int32 V_4) + int32 V_2) IL_0000: ldc.i4.0 IL_0001: call class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1 [FSharp.Core]Microsoft.FSharp.Core.Operators::Ref(!!0) IL_0006: stloc.0 @@ -131,14 +93,10 @@ IL_0039: stloc.2 IL_003a: ldarg.0 IL_003b: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/f3@5::builder@ - IL_0040: stloc.3 - IL_0041: ldloc.2 - IL_0042: stloc.s V_4 - IL_0044: ldloc.s V_4 - IL_0046: newobj instance void assembly/assembly/'f3@10-1'::.ctor(int32) - IL_004b: tail. - IL_004d: call class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.AsyncPrimitives::MakeAsync(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn>) - IL_0052: ret + IL_0040: ldloc.2 + IL_0041: tail. + IL_0043: callvirt instance class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder::Return(!!0) + IL_0048: ret } } diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/AsyncExpressionStepping/AsyncExpressionSteppingTest3.fs.RealInternalSignatureOn.OptimizeOff.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/AsyncExpressionStepping/AsyncExpressionSteppingTest3.fs.RealInternalSignatureOn.OptimizeOff.il.bsl index 1f5c0f27046..e71ecaac097 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/AsyncExpressionStepping/AsyncExpressionSteppingTest3.fs.RealInternalSignatureOn.OptimizeOff.il.bsl +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/AsyncExpressionStepping/AsyncExpressionSteppingTest3.fs.RealInternalSignatureOn.OptimizeOff.il.bsl @@ -37,42 +37,6 @@ extends [runtime]System.Object { .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) - .class auto ansi serializable sealed nested assembly beforefieldinit 'f3@10-1' - extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn> - { - .field public int32 'value' - .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - .method assembly specialname rtspecialname instance void .ctor(int32 'value') 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 ) - - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn>::.ctor() - IL_0006: ldarg.0 - IL_0007: ldarg.1 - IL_0008: stfld int32 assembly/assembly/'f3@10-1'::'value' - IL_000d: ret - } - - .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn Invoke(valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1 ctxt) cil managed - { - - .maxstack 8 - IL_0000: ldarg.1 - IL_0001: ldarg.0 - IL_0002: ldfld int32 assembly/assembly/'f3@10-1'::'value' - IL_0007: tail. - IL_0009: call class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1::Success(valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1, - !0) - IL_000e: ret - } - - } - .class auto ansi serializable sealed nested assembly beforefieldinit f3@5 extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> { @@ -100,9 +64,7 @@ .maxstack 7 .locals init (class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1 V_0, class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1 V_1, - int32 V_2, - class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder V_3, - int32 V_4) + int32 V_2) IL_0000: ldc.i4.0 IL_0001: call class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1 [FSharp.Core]Microsoft.FSharp.Core.Operators::Ref(!!0) IL_0006: stloc.0 @@ -131,14 +93,10 @@ IL_0039: stloc.2 IL_003a: ldarg.0 IL_003b: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/f3@5::builder@ - IL_0040: stloc.3 - IL_0041: ldloc.2 - IL_0042: stloc.s V_4 - IL_0044: ldloc.s V_4 - IL_0046: newobj instance void assembly/assembly/'f3@10-1'::.ctor(int32) - IL_004b: tail. - IL_004d: call class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.AsyncPrimitives::MakeAsync(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn>) - IL_0052: ret + IL_0040: ldloc.2 + IL_0041: tail. + IL_0043: callvirt instance class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder::Return(!!0) + IL_0048: ret } } diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/AsyncExpressionStepping/AsyncExpressionSteppingTest4.fs.RealInternalSignatureOff.OptimizeOff.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/AsyncExpressionStepping/AsyncExpressionSteppingTest4.fs.RealInternalSignatureOff.OptimizeOff.il.bsl index 348b1d1471d..c6dc4802db1 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/AsyncExpressionStepping/AsyncExpressionSteppingTest4.fs.RealInternalSignatureOff.OptimizeOff.il.bsl +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/AsyncExpressionStepping/AsyncExpressionSteppingTest4.fs.RealInternalSignatureOff.OptimizeOff.il.bsl @@ -37,42 +37,6 @@ extends [runtime]System.Object { .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) - .class auto ansi serializable sealed nested assembly beforefieldinit 'f4@10-2' - extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn> - { - .field public int32 'value' - .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - .method assembly specialname rtspecialname instance void .ctor(int32 'value') 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 ) - - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn>::.ctor() - IL_0006: ldarg.0 - IL_0007: ldarg.1 - IL_0008: stfld int32 assembly/assembly/'f4@10-2'::'value' - IL_000d: ret - } - - .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn Invoke(valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1 ctxt) cil managed - { - - .maxstack 8 - IL_0000: ldarg.1 - IL_0001: ldarg.0 - IL_0002: ldfld int32 assembly/assembly/'f4@10-2'::'value' - IL_0007: tail. - IL_0009: call class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1::Success(valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1, - !0) - IL_000e: ret - } - - } - .class auto ansi serializable sealed nested assembly beforefieldinit 'f4@7-1' extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> { @@ -103,9 +67,7 @@ .maxstack 6 .locals init (class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1 V_0, - int32 V_1, - class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder V_2, - int32 V_3) + int32 V_1) IL_0000: nop IL_0001: ldc.i4.0 IL_0002: call class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1 [FSharp.Core]Microsoft.FSharp.Core.Operators::Ref(!!0) @@ -124,19 +86,15 @@ IL_0027: stloc.1 IL_0028: ldarg.0 IL_0029: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/'f4@7-1'::builder@ - IL_002e: stloc.2 - IL_002f: ldloc.1 - IL_0030: stloc.3 - IL_0031: ldloc.3 - IL_0032: newobj instance void assembly/assembly/'f4@10-2'::.ctor(int32) - IL_0037: tail. - IL_0039: call class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.AsyncPrimitives::MakeAsync(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn>) - IL_003e: ret + IL_002e: ldloc.1 + IL_002f: tail. + IL_0031: callvirt instance class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder::Return(!!0) + IL_0036: ret } } - .class auto ansi serializable sealed nested assembly beforefieldinit 'f4@12-3' + .class auto ansi serializable sealed nested assembly beforefieldinit 'f4@12-2' extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 { .field public class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1 x @@ -150,7 +108,7 @@ IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::.ctor() IL_0006: ldarg.0 IL_0007: ldarg.1 - IL_0008: stfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1 assembly/assembly/'f4@12-3'::x + IL_0008: stfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1 assembly/assembly/'f4@12-2'::x IL_000d: ret } @@ -160,9 +118,9 @@ .maxstack 8 IL_0000: nop IL_0001: ldarg.0 - IL_0002: ldfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1 assembly/assembly/'f4@12-3'::x + IL_0002: ldfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1 assembly/assembly/'f4@12-2'::x IL_0007: ldarg.0 - IL_0008: ldfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1 assembly/assembly/'f4@12-3'::x + IL_0008: ldfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1 assembly/assembly/'f4@12-2'::x IL_000d: callvirt instance !0 class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1::get_Value() IL_0012: callvirt instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1::set_Value(!0) IL_0017: nop @@ -175,52 +133,6 @@ } - .class auto ansi serializable sealed nested assembly beforefieldinit 'f4@6-4' - extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn> - { - .field public class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 computation - .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - .field public class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 compensation - .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - .method assembly specialname rtspecialname instance void .ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 computation, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 compensation) 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 ) - - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn>::.ctor() - IL_0006: ldarg.0 - IL_0007: ldarg.1 - IL_0008: stfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 assembly/assembly/'f4@6-4'::computation - IL_000d: ldarg.0 - IL_000e: ldarg.2 - IL_000f: stfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 assembly/assembly/'f4@6-4'::compensation - IL_0014: ret - } - - .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn Invoke(valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1 ctxt) cil managed - { - - .maxstack 8 - IL_0000: ldarg.1 - IL_0001: ldarg.0 - IL_0002: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 assembly/assembly/'f4@6-4'::computation - IL_0007: ldarg.0 - IL_0008: ldfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 assembly/assembly/'f4@6-4'::compensation - IL_000d: tail. - IL_000f: call class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn [FSharp.Core]Microsoft.FSharp.Control.AsyncPrimitives::TryFinally(valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1, - class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) - IL_0014: ret - } - - } - .class auto ansi serializable sealed nested assembly beforefieldinit f4@5 extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> { @@ -245,36 +157,27 @@ .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 Invoke(class [FSharp.Core]Microsoft.FSharp.Core.Unit unitVar) cil managed { - .maxstack 7 - .locals init (class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1 V_0, - class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder V_1, - class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 V_2, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 V_3) + .maxstack 8 + .locals init (class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1 V_0) IL_0000: ldc.i4.0 IL_0001: call class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1 [FSharp.Core]Microsoft.FSharp.Core.Operators::Ref(!!0) IL_0006: stloc.0 IL_0007: ldarg.0 IL_0008: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/f4@5::builder@ - IL_000d: stloc.1 - IL_000e: ldarg.0 - IL_000f: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/f4@5::builder@ - IL_0014: ldarg.0 - IL_0015: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/f4@5::builder@ - IL_001a: ldloc.0 - IL_001b: newobj instance void assembly/assembly/'f4@7-1'::.ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder, + IL_000d: ldarg.0 + IL_000e: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/f4@5::builder@ + IL_0013: ldarg.0 + IL_0014: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/f4@5::builder@ + IL_0019: ldloc.0 + IL_001a: newobj instance void assembly/assembly/'f4@7-1'::.ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder, class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1) - IL_0020: callvirt instance class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder::Delay(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_0025: stloc.2 - IL_0026: ldloc.0 - IL_0027: newobj instance void assembly/assembly/'f4@12-3'::.ctor(class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1) - IL_002c: stloc.3 - IL_002d: ldloc.2 - IL_002e: ldloc.3 - IL_002f: newobj instance void assembly/assembly/'f4@6-4'::.ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) - IL_0034: tail. - IL_0036: call class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.AsyncPrimitives::MakeAsync(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn>) - IL_003b: ret + IL_001f: callvirt instance class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder::Delay(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) + IL_0024: ldloc.0 + IL_0025: newobj instance void assembly/assembly/'f4@12-2'::.ctor(class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1) + IL_002a: tail. + IL_002c: callvirt instance class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder::TryFinally(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1, + class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) + IL_0031: ret } } diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/AsyncExpressionStepping/AsyncExpressionSteppingTest4.fs.RealInternalSignatureOn.OptimizeOff.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/AsyncExpressionStepping/AsyncExpressionSteppingTest4.fs.RealInternalSignatureOn.OptimizeOff.il.bsl index 143ba00c7de..0f4b2257cbb 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/AsyncExpressionStepping/AsyncExpressionSteppingTest4.fs.RealInternalSignatureOn.OptimizeOff.il.bsl +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/AsyncExpressionStepping/AsyncExpressionSteppingTest4.fs.RealInternalSignatureOn.OptimizeOff.il.bsl @@ -37,42 +37,6 @@ extends [runtime]System.Object { .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) - .class auto ansi serializable sealed nested assembly beforefieldinit 'f4@10-2' - extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn> - { - .field public int32 'value' - .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - .method assembly specialname rtspecialname instance void .ctor(int32 'value') 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 ) - - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn>::.ctor() - IL_0006: ldarg.0 - IL_0007: ldarg.1 - IL_0008: stfld int32 assembly/assembly/'f4@10-2'::'value' - IL_000d: ret - } - - .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn Invoke(valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1 ctxt) cil managed - { - - .maxstack 8 - IL_0000: ldarg.1 - IL_0001: ldarg.0 - IL_0002: ldfld int32 assembly/assembly/'f4@10-2'::'value' - IL_0007: tail. - IL_0009: call class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1::Success(valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1, - !0) - IL_000e: ret - } - - } - .class auto ansi serializable sealed nested assembly beforefieldinit 'f4@7-1' extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> { @@ -103,9 +67,7 @@ .maxstack 6 .locals init (class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1 V_0, - int32 V_1, - class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder V_2, - int32 V_3) + int32 V_1) IL_0000: nop IL_0001: ldc.i4.0 IL_0002: call class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1 [FSharp.Core]Microsoft.FSharp.Core.Operators::Ref(!!0) @@ -124,19 +86,15 @@ IL_0027: stloc.1 IL_0028: ldarg.0 IL_0029: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/'f4@7-1'::builder@ - IL_002e: stloc.2 - IL_002f: ldloc.1 - IL_0030: stloc.3 - IL_0031: ldloc.3 - IL_0032: newobj instance void assembly/assembly/'f4@10-2'::.ctor(int32) - IL_0037: tail. - IL_0039: call class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.AsyncPrimitives::MakeAsync(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn>) - IL_003e: ret + IL_002e: ldloc.1 + IL_002f: tail. + IL_0031: callvirt instance class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder::Return(!!0) + IL_0036: ret } } - .class auto ansi serializable sealed nested assembly beforefieldinit 'f4@12-3' + .class auto ansi serializable sealed nested assembly beforefieldinit 'f4@12-2' extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 { .field public class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1 x @@ -150,7 +108,7 @@ IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2::.ctor() IL_0006: ldarg.0 IL_0007: ldarg.1 - IL_0008: stfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1 assembly/assembly/'f4@12-3'::x + IL_0008: stfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1 assembly/assembly/'f4@12-2'::x IL_000d: ret } @@ -160,9 +118,9 @@ .maxstack 8 IL_0000: nop IL_0001: ldarg.0 - IL_0002: ldfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1 assembly/assembly/'f4@12-3'::x + IL_0002: ldfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1 assembly/assembly/'f4@12-2'::x IL_0007: ldarg.0 - IL_0008: ldfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1 assembly/assembly/'f4@12-3'::x + IL_0008: ldfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1 assembly/assembly/'f4@12-2'::x IL_000d: callvirt instance !0 class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1::get_Value() IL_0012: callvirt instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1::set_Value(!0) IL_0017: nop @@ -175,52 +133,6 @@ } - .class auto ansi serializable sealed nested assembly beforefieldinit 'f4@6-4' - extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn> - { - .field public class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 computation - .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - .field public class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 compensation - .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - .method assembly specialname rtspecialname instance void .ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 computation, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 compensation) 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 ) - - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn>::.ctor() - IL_0006: ldarg.0 - IL_0007: ldarg.1 - IL_0008: stfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 assembly/assembly/'f4@6-4'::computation - IL_000d: ldarg.0 - IL_000e: ldarg.2 - IL_000f: stfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 assembly/assembly/'f4@6-4'::compensation - IL_0014: ret - } - - .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn Invoke(valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1 ctxt) cil managed - { - - .maxstack 8 - IL_0000: ldarg.1 - IL_0001: ldarg.0 - IL_0002: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 assembly/assembly/'f4@6-4'::computation - IL_0007: ldarg.0 - IL_0008: ldfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 assembly/assembly/'f4@6-4'::compensation - IL_000d: tail. - IL_000f: call class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn [FSharp.Core]Microsoft.FSharp.Control.AsyncPrimitives::TryFinally(valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1, - class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) - IL_0014: ret - } - - } - .class auto ansi serializable sealed nested assembly beforefieldinit f4@5 extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> { @@ -245,36 +157,27 @@ .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 Invoke(class [FSharp.Core]Microsoft.FSharp.Core.Unit unitVar) cil managed { - .maxstack 7 - .locals init (class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1 V_0, - class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder V_1, - class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 V_2, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2 V_3) + .maxstack 8 + .locals init (class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1 V_0) IL_0000: ldc.i4.0 IL_0001: call class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1 [FSharp.Core]Microsoft.FSharp.Core.Operators::Ref(!!0) IL_0006: stloc.0 IL_0007: ldarg.0 IL_0008: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/f4@5::builder@ - IL_000d: stloc.1 - IL_000e: ldarg.0 - IL_000f: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/f4@5::builder@ - IL_0014: ldarg.0 - IL_0015: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/f4@5::builder@ - IL_001a: ldloc.0 - IL_001b: newobj instance void assembly/assembly/'f4@7-1'::.ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder, + IL_000d: ldarg.0 + IL_000e: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/f4@5::builder@ + IL_0013: ldarg.0 + IL_0014: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/f4@5::builder@ + IL_0019: ldloc.0 + IL_001a: newobj instance void assembly/assembly/'f4@7-1'::.ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder, class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1) - IL_0020: callvirt instance class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder::Delay(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_0025: stloc.2 - IL_0026: ldloc.0 - IL_0027: newobj instance void assembly/assembly/'f4@12-3'::.ctor(class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1) - IL_002c: stloc.3 - IL_002d: ldloc.2 - IL_002e: ldloc.3 - IL_002f: newobj instance void assembly/assembly/'f4@6-4'::.ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) - IL_0034: tail. - IL_0036: call class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.AsyncPrimitives::MakeAsync(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn>) - IL_003b: ret + IL_001f: callvirt instance class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder::Delay(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) + IL_0024: ldloc.0 + IL_0025: newobj instance void assembly/assembly/'f4@12-2'::.ctor(class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1) + IL_002a: tail. + IL_002c: callvirt instance class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder::TryFinally(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1, + class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2) + IL_0031: ret } } diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/AsyncExpressionStepping/AsyncExpressionSteppingTest5.fs.RealInternalSignatureOff.OptimizeOff.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/AsyncExpressionStepping/AsyncExpressionSteppingTest5.fs.RealInternalSignatureOff.OptimizeOff.il.bsl index 1c4d13e1c30..e9d89b5a241 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/AsyncExpressionStepping/AsyncExpressionSteppingTest5.fs.RealInternalSignatureOff.OptimizeOff.il.bsl +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/AsyncExpressionStepping/AsyncExpressionSteppingTest5.fs.RealInternalSignatureOff.OptimizeOff.il.bsl @@ -166,84 +166,6 @@ } - .class auto ansi serializable sealed nested assembly beforefieldinit 'f7@6-4' - extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> - { - .field public class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 computation2 - .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - .method assembly specialname rtspecialname instance void .ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 computation2) 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 ) - - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>::.ctor() - IL_0006: ldarg.0 - IL_0007: ldarg.1 - IL_0008: stfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 assembly/assembly/'f7@6-4'::computation2 - IL_000d: ret - } - - .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 Invoke(class [FSharp.Core]Microsoft.FSharp.Core.Unit unitVar0) cil managed - { - - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 assembly/assembly/'f7@6-4'::computation2 - IL_0006: ret - } - - } - - .class auto ansi serializable sealed nested assembly beforefieldinit 'f7@6-5' - extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn> - { - .field public class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 computation1 - .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - .field public class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> part2 - .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - .method assembly specialname rtspecialname instance void .ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 computation1, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> part2) 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 ) - - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn>::.ctor() - IL_0006: ldarg.0 - IL_0007: ldarg.1 - IL_0008: stfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 assembly/assembly/'f7@6-5'::computation1 - IL_000d: ldarg.0 - IL_000e: ldarg.2 - IL_000f: stfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> assembly/assembly/'f7@6-5'::part2 - IL_0014: ret - } - - .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn Invoke(valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1 ctxt) cil managed - { - - .maxstack 8 - IL_0000: ldarg.1 - IL_0001: ldarg.0 - IL_0002: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 assembly/assembly/'f7@6-5'::computation1 - IL_0007: ldarg.0 - IL_0008: ldfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> assembly/assembly/'f7@6-5'::part2 - IL_000d: tail. - IL_000f: call class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn [FSharp.Core]Microsoft.FSharp.Control.AsyncPrimitives::Bind(valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1, - class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_0014: ret - } - - } - .class auto ansi serializable sealed nested assembly beforefieldinit f7@6 extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> { @@ -268,40 +190,27 @@ .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 Invoke(class [FSharp.Core]Microsoft.FSharp.Core.Unit unitVar) cil managed { - .maxstack 7 - .locals init (class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder V_0, - class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 V_1, - class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 V_2, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> V_3) + .maxstack 8 IL_0000: ldarg.0 IL_0001: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/f7@6::builder@ - IL_0006: stloc.0 - IL_0007: ldarg.0 - IL_0008: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/f7@6::builder@ - IL_000d: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 assembly/assembly::get_es() - IL_0012: ldarg.0 - IL_0013: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/f7@6::builder@ - IL_0018: newobj instance void assembly/assembly/'f7@6-1'::.ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder) - IL_001d: callvirt instance class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder::For(class [runtime]System.Collections.Generic.IEnumerable`1, + IL_0006: ldarg.0 + IL_0007: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/f7@6::builder@ + IL_000c: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 assembly/assembly::get_es() + IL_0011: ldarg.0 + IL_0012: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/f7@6::builder@ + IL_0017: newobj instance void assembly/assembly/'f7@6-1'::.ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder) + IL_001c: callvirt instance class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder::For(class [runtime]System.Collections.Generic.IEnumerable`1, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_0022: stloc.1 - IL_0023: ldarg.0 - IL_0024: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/f7@6::builder@ - IL_0029: ldarg.0 - IL_002a: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/f7@6::builder@ - IL_002f: newobj instance void assembly/assembly/'f7@9-2'::.ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder) - IL_0034: callvirt instance class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder::Delay(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_0039: stloc.2 - IL_003a: ldloc.2 - IL_003b: newobj instance void assembly/assembly/'f7@6-4'::.ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1) - IL_0040: stloc.3 - IL_0041: ldloc.1 - IL_0042: ldloc.3 - IL_0043: newobj instance void assembly/assembly/'f7@6-5'::.ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_0048: tail. - IL_004a: call class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.AsyncPrimitives::MakeAsync(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn>) - IL_004f: ret + IL_0021: ldarg.0 + IL_0022: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/f7@6::builder@ + IL_0027: ldarg.0 + IL_0028: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/f7@6::builder@ + IL_002d: newobj instance void assembly/assembly/'f7@9-2'::.ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder) + IL_0032: callvirt instance class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder::Delay(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) + IL_0037: tail. + IL_0039: callvirt instance class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder::Combine(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1, + class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1) + IL_003e: ret } } diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/AsyncExpressionStepping/AsyncExpressionSteppingTest5.fs.RealInternalSignatureOn.OptimizeOff.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/AsyncExpressionStepping/AsyncExpressionSteppingTest5.fs.RealInternalSignatureOn.OptimizeOff.il.bsl index f2f84fbd489..abc834a81f4 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/AsyncExpressionStepping/AsyncExpressionSteppingTest5.fs.RealInternalSignatureOn.OptimizeOff.il.bsl +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/AsyncExpressionStepping/AsyncExpressionSteppingTest5.fs.RealInternalSignatureOn.OptimizeOff.il.bsl @@ -166,84 +166,6 @@ } - .class auto ansi serializable sealed nested assembly beforefieldinit 'f7@6-4' - extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> - { - .field public class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 computation2 - .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - .method assembly specialname rtspecialname instance void .ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 computation2) 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 ) - - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>::.ctor() - IL_0006: ldarg.0 - IL_0007: ldarg.1 - IL_0008: stfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 assembly/assembly/'f7@6-4'::computation2 - IL_000d: ret - } - - .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 Invoke(class [FSharp.Core]Microsoft.FSharp.Core.Unit unitVar0) cil managed - { - - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 assembly/assembly/'f7@6-4'::computation2 - IL_0006: ret - } - - } - - .class auto ansi serializable sealed nested assembly beforefieldinit 'f7@6-5' - extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn> - { - .field public class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 computation1 - .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - .field public class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> part2 - .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - .method assembly specialname rtspecialname instance void .ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 computation1, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> part2) 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 ) - - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn>::.ctor() - IL_0006: ldarg.0 - IL_0007: ldarg.1 - IL_0008: stfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 assembly/assembly/'f7@6-5'::computation1 - IL_000d: ldarg.0 - IL_000e: ldarg.2 - IL_000f: stfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> assembly/assembly/'f7@6-5'::part2 - IL_0014: ret - } - - .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn Invoke(valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1 ctxt) cil managed - { - - .maxstack 8 - IL_0000: ldarg.1 - IL_0001: ldarg.0 - IL_0002: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 assembly/assembly/'f7@6-5'::computation1 - IL_0007: ldarg.0 - IL_0008: ldfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> assembly/assembly/'f7@6-5'::part2 - IL_000d: tail. - IL_000f: call class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn [FSharp.Core]Microsoft.FSharp.Control.AsyncPrimitives::Bind(valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1, - class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_0014: ret - } - - } - .class auto ansi serializable sealed nested assembly beforefieldinit f7@6 extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> { @@ -268,40 +190,27 @@ .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 Invoke(class [FSharp.Core]Microsoft.FSharp.Core.Unit unitVar) cil managed { - .maxstack 7 - .locals init (class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder V_0, - class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 V_1, - class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 V_2, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> V_3) + .maxstack 8 IL_0000: ldarg.0 IL_0001: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/f7@6::builder@ - IL_0006: stloc.0 - IL_0007: ldarg.0 - IL_0008: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/f7@6::builder@ - IL_000d: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 assembly/assembly::get_es() - IL_0012: ldarg.0 - IL_0013: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/f7@6::builder@ - IL_0018: newobj instance void assembly/assembly/'f7@6-1'::.ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder) - IL_001d: callvirt instance class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder::For(class [runtime]System.Collections.Generic.IEnumerable`1, + IL_0006: ldarg.0 + IL_0007: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/f7@6::builder@ + IL_000c: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1 assembly/assembly::get_es() + IL_0011: ldarg.0 + IL_0012: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/f7@6::builder@ + IL_0017: newobj instance void assembly/assembly/'f7@6-1'::.ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder) + IL_001c: callvirt instance class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder::For(class [runtime]System.Collections.Generic.IEnumerable`1, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_0022: stloc.1 - IL_0023: ldarg.0 - IL_0024: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/f7@6::builder@ - IL_0029: ldarg.0 - IL_002a: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/f7@6::builder@ - IL_002f: newobj instance void assembly/assembly/'f7@9-2'::.ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder) - IL_0034: callvirt instance class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder::Delay(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_0039: stloc.2 - IL_003a: ldloc.2 - IL_003b: newobj instance void assembly/assembly/'f7@6-4'::.ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1) - IL_0040: stloc.3 - IL_0041: ldloc.1 - IL_0042: ldloc.3 - IL_0043: newobj instance void assembly/assembly/'f7@6-5'::.ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_0048: tail. - IL_004a: call class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.AsyncPrimitives::MakeAsync(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn>) - IL_004f: ret + IL_0021: ldarg.0 + IL_0022: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/f7@6::builder@ + IL_0027: ldarg.0 + IL_0028: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/f7@6::builder@ + IL_002d: newobj instance void assembly/assembly/'f7@9-2'::.ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder) + IL_0032: callvirt instance class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder::Delay(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) + IL_0037: tail. + IL_0039: callvirt instance class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder::Combine(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1, + class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1) + IL_003e: ret } } diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/AsyncExpressionStepping/AsyncExpressionSteppingTest6.fs.RealInternalSignatureOff.OptimizeOff.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/AsyncExpressionStepping/AsyncExpressionSteppingTest6.fs.RealInternalSignatureOff.OptimizeOff.il.bsl index 791fe74ed50..05684073110 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/AsyncExpressionStepping/AsyncExpressionSteppingTest6.fs.RealInternalSignatureOff.OptimizeOff.il.bsl +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/AsyncExpressionStepping/AsyncExpressionSteppingTest6.fs.RealInternalSignatureOff.OptimizeOff.il.bsl @@ -37,42 +37,6 @@ extends [runtime]System.Object { .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) - .class auto ansi serializable sealed nested assembly beforefieldinit 'f2@10-1' - extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn> - { - .field public int32 'value' - .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - .method assembly specialname rtspecialname instance void .ctor(int32 'value') 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 ) - - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn>::.ctor() - IL_0006: ldarg.0 - IL_0007: ldarg.1 - IL_0008: stfld int32 assembly/assembly/'f2@10-1'::'value' - IL_000d: ret - } - - .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn Invoke(valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1 ctxt) cil managed - { - - .maxstack 8 - IL_0000: ldarg.1 - IL_0001: ldarg.0 - IL_0002: ldfld int32 assembly/assembly/'f2@10-1'::'value' - IL_0007: tail. - IL_0009: call class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1::Success(valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1, - !0) - IL_000e: ret - } - - } - .class auto ansi serializable sealed nested assembly beforefieldinit f2@5 extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> { @@ -100,9 +64,7 @@ .maxstack 7 .locals init (class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1 V_0, class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1 V_1, - int32 V_2, - class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder V_3, - int32 V_4) + int32 V_2) IL_0000: ldc.i4.0 IL_0001: call class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1 [FSharp.Core]Microsoft.FSharp.Core.Operators::Ref(!!0) IL_0006: stloc.0 @@ -131,50 +93,10 @@ IL_0039: stloc.2 IL_003a: ldarg.0 IL_003b: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/f2@5::builder@ - IL_0040: stloc.3 - IL_0041: ldloc.2 - IL_0042: stloc.s V_4 - IL_0044: ldloc.s V_4 - IL_0046: newobj instance void assembly/assembly/'f2@10-1'::.ctor(int32) - IL_004b: tail. - IL_004d: call class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.AsyncPrimitives::MakeAsync(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn>) - IL_0052: ret - } - - } - - .class auto ansi serializable sealed nested assembly beforefieldinit 'f3@20-5' - extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn> - { - .field public int32 'value' - .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - .method assembly specialname rtspecialname instance void .ctor(int32 'value') 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 ) - - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn>::.ctor() - IL_0006: ldarg.0 - IL_0007: ldarg.1 - IL_0008: stfld int32 assembly/assembly/'f3@20-5'::'value' - IL_000d: ret - } - - .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn Invoke(valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1 ctxt) cil managed - { - - .maxstack 8 - IL_0000: ldarg.1 - IL_0001: ldarg.0 - IL_0002: ldfld int32 assembly/assembly/'f3@20-5'::'value' - IL_0007: tail. - IL_0009: call class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1::Success(valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1, - !0) - IL_000e: ret + IL_0040: ldloc.2 + IL_0041: tail. + IL_0043: callvirt instance class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder::Return(!!0) + IL_0048: ret } } @@ -216,9 +138,7 @@ .maxstack 6 .locals init (int32 V_0, - int32 V_1, - class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder V_2, - int32 V_3) + int32 V_1) IL_0000: ldarg.1 IL_0001: stloc.0 IL_0002: ldarg.0 @@ -232,60 +152,10 @@ IL_0016: stloc.1 IL_0017: ldarg.0 IL_0018: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/'f3@19-4'::builder@ - IL_001d: stloc.2 - IL_001e: ldloc.1 - IL_001f: stloc.3 - IL_0020: ldloc.3 - IL_0021: newobj instance void assembly/assembly/'f3@20-5'::.ctor(int32) - IL_0026: tail. - IL_0028: call class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.AsyncPrimitives::MakeAsync(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn>) - IL_002d: ret - } - - } - - .class auto ansi serializable sealed nested assembly beforefieldinit 'f3@19-6' - extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn> - { - .field public class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 computation - .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - .field public class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> binder - .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - .method assembly specialname rtspecialname instance void .ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 computation, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> binder) 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 ) - - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn>::.ctor() - IL_0006: ldarg.0 - IL_0007: ldarg.1 - IL_0008: stfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 assembly/assembly/'f3@19-6'::computation - IL_000d: ldarg.0 - IL_000e: ldarg.2 - IL_000f: stfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> assembly/assembly/'f3@19-6'::binder - IL_0014: ret - } - - .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn Invoke(valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1 ctxt) cil managed - { - - .maxstack 8 - IL_0000: ldarg.1 - IL_0001: ldarg.0 - IL_0002: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 assembly/assembly/'f3@19-6'::computation - IL_0007: ldarg.0 - IL_0008: ldfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> assembly/assembly/'f3@19-6'::binder - IL_000d: tail. - IL_000f: call class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn [FSharp.Core]Microsoft.FSharp.Control.AsyncPrimitives::Bind(valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1, - class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_0014: ret + IL_001d: ldloc.1 + IL_001e: tail. + IL_0020: callvirt instance class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder::Return(!!0) + IL_0025: ret } } @@ -318,12 +188,9 @@ .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 Invoke(int32 _arg3) cil managed { - .maxstack 7 + .maxstack 9 .locals init (int32 V_0, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1 V_1, - class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder V_2, - class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 V_3, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> V_4) + class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1 V_1) IL_0000: ldarg.1 IL_0001: stloc.0 IL_0002: ldc.i4.0 @@ -338,71 +205,19 @@ IL_0017: nop IL_0018: ldarg.0 IL_0019: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/'f3@16-3'::builder@ - IL_001e: stloc.2 - IL_001f: call class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 assembly/assembly::f2() - IL_0024: stloc.3 - IL_0025: ldarg.0 - IL_0026: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/'f3@16-3'::builder@ - IL_002b: ldarg.0 - IL_002c: ldfld int32 assembly/assembly/'f3@16-3'::x1 - IL_0031: ldloc.1 - IL_0032: newobj instance void assembly/assembly/'f3@19-4'::.ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder, + IL_001e: call class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 assembly/assembly::f2() + IL_0023: ldarg.0 + IL_0024: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/'f3@16-3'::builder@ + IL_0029: ldarg.0 + IL_002a: ldfld int32 assembly/assembly/'f3@16-3'::x1 + IL_002f: ldloc.1 + IL_0030: newobj instance void assembly/assembly/'f3@19-4'::.ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder, int32, class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1) - IL_0037: stloc.s V_4 - IL_0039: ldloc.3 - IL_003a: ldloc.s V_4 - IL_003c: newobj instance void assembly/assembly/'f3@19-6'::.ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_0041: tail. - IL_0043: call class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.AsyncPrimitives::MakeAsync(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn>) - IL_0048: ret - } - - } - - .class auto ansi serializable sealed nested assembly beforefieldinit 'f3@16-7' - extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn> - { - .field public class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 computation - .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - .field public class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> binder - .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - .method assembly specialname rtspecialname instance void .ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 computation, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> binder) 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 ) - - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn>::.ctor() - IL_0006: ldarg.0 - IL_0007: ldarg.1 - IL_0008: stfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 assembly/assembly/'f3@16-7'::computation - IL_000d: ldarg.0 - IL_000e: ldarg.2 - IL_000f: stfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> assembly/assembly/'f3@16-7'::binder - IL_0014: ret - } - - .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn Invoke(valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1 ctxt) cil managed - { - - .maxstack 8 - IL_0000: ldarg.1 - IL_0001: ldarg.0 - IL_0002: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 assembly/assembly/'f3@16-7'::computation - IL_0007: ldarg.0 - IL_0008: ldfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> assembly/assembly/'f3@16-7'::binder - IL_000d: tail. - IL_000f: call class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn [FSharp.Core]Microsoft.FSharp.Control.AsyncPrimitives::Bind(valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1, - class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_0014: ret + IL_0035: tail. + IL_0037: callvirt instance class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder::Bind(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1, + class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) + IL_003c: ret } } @@ -435,78 +250,23 @@ .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 Invoke(int32 _arg2) cil managed { - .maxstack 6 - .locals init (int32 V_0, - class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder V_1, - class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 V_2, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> V_3) + .maxstack 8 + .locals init (int32 V_0) IL_0000: ldarg.1 IL_0001: stloc.0 IL_0002: ldarg.0 IL_0003: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/'f3@15-2'::builder@ - IL_0008: stloc.1 - IL_0009: call class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 assembly/assembly::f2() - IL_000e: stloc.2 - IL_000f: ldarg.0 - IL_0010: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/'f3@15-2'::builder@ - IL_0015: ldarg.0 - IL_0016: ldfld int32 assembly/assembly/'f3@15-2'::x1 - IL_001b: newobj instance void assembly/assembly/'f3@16-3'::.ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder, - int32) - IL_0020: stloc.3 - IL_0021: ldloc.2 - IL_0022: ldloc.3 - IL_0023: newobj instance void assembly/assembly/'f3@16-7'::.ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_0028: tail. - IL_002a: call class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.AsyncPrimitives::MakeAsync(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn>) - IL_002f: ret - } - - } - - .class auto ansi serializable sealed nested assembly beforefieldinit 'f3@16-8' - extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn> - { - .field public class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 computation - .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - .field public class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> binder - .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - .method assembly specialname rtspecialname instance void .ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 computation, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> binder) 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 ) - - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn>::.ctor() - IL_0006: ldarg.0 - IL_0007: ldarg.1 - IL_0008: stfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 assembly/assembly/'f3@16-8'::computation + IL_0008: call class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 assembly/assembly::f2() IL_000d: ldarg.0 - IL_000e: ldarg.2 - IL_000f: stfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> assembly/assembly/'f3@16-8'::binder - IL_0014: ret - } - - .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn Invoke(valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1 ctxt) cil managed - { - - .maxstack 8 - IL_0000: ldarg.1 - IL_0001: ldarg.0 - IL_0002: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 assembly/assembly/'f3@16-8'::computation - IL_0007: ldarg.0 - IL_0008: ldfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> assembly/assembly/'f3@16-8'::binder - IL_000d: tail. - IL_000f: call class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn [FSharp.Core]Microsoft.FSharp.Control.AsyncPrimitives::Bind(valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1, - class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_0014: ret + IL_000e: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/'f3@15-2'::builder@ + IL_0013: ldarg.0 + IL_0014: ldfld int32 assembly/assembly/'f3@15-2'::x1 + IL_0019: newobj instance void assembly/assembly/'f3@16-3'::.ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder, + int32) + IL_001e: tail. + IL_0020: callvirt instance class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder::Bind(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1, + class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) + IL_0025: ret } } @@ -535,77 +295,22 @@ .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 Invoke(int32 _arg1) cil managed { - .maxstack 6 - .locals init (int32 V_0, - class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder V_1, - class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 V_2, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> V_3) + .maxstack 8 + .locals init (int32 V_0) IL_0000: ldarg.1 IL_0001: stloc.0 IL_0002: ldarg.0 IL_0003: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/'f3@14-1'::builder@ - IL_0008: stloc.1 - IL_0009: call class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 assembly/assembly::f2() - IL_000e: stloc.2 - IL_000f: ldarg.0 - IL_0010: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/'f3@14-1'::builder@ - IL_0015: ldloc.0 - IL_0016: newobj instance void assembly/assembly/'f3@15-2'::.ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder, - int32) - IL_001b: stloc.3 - IL_001c: ldloc.2 - IL_001d: ldloc.3 - IL_001e: newobj instance void assembly/assembly/'f3@16-8'::.ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_0023: tail. - IL_0025: call class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.AsyncPrimitives::MakeAsync(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn>) - IL_002a: ret - } - - } - - .class auto ansi serializable sealed nested assembly beforefieldinit 'f3@16-9' - extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn> - { - .field public class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 computation - .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - .field public class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> binder - .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - .method assembly specialname rtspecialname instance void .ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 computation, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> binder) 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 ) - - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn>::.ctor() - IL_0006: ldarg.0 - IL_0007: ldarg.1 - IL_0008: stfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 assembly/assembly/'f3@16-9'::computation + IL_0008: call class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 assembly/assembly::f2() IL_000d: ldarg.0 - IL_000e: ldarg.2 - IL_000f: stfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> assembly/assembly/'f3@16-9'::binder - IL_0014: ret - } - - .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn Invoke(valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1 ctxt) cil managed - { - - .maxstack 8 - IL_0000: ldarg.1 - IL_0001: ldarg.0 - IL_0002: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 assembly/assembly/'f3@16-9'::computation - IL_0007: ldarg.0 - IL_0008: ldfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> assembly/assembly/'f3@16-9'::binder - IL_000d: tail. - IL_000f: call class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn [FSharp.Core]Microsoft.FSharp.Control.AsyncPrimitives::Bind(valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1, - class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_0014: ret + IL_000e: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/'f3@14-1'::builder@ + IL_0013: ldloc.0 + IL_0014: newobj instance void assembly/assembly/'f3@15-2'::.ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder, + int32) + IL_0019: tail. + IL_001b: callvirt instance class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder::Bind(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1, + class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) + IL_0020: ret } } @@ -634,26 +339,17 @@ .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 Invoke(class [FSharp.Core]Microsoft.FSharp.Core.Unit unitVar) cil managed { - .maxstack 6 - .locals init (class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder V_0, - class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 V_1, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> V_2) + .maxstack 8 IL_0000: ldarg.0 IL_0001: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/f3@16::builder@ - IL_0006: stloc.0 - IL_0007: call class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 assembly/assembly::f2() - IL_000c: stloc.1 - IL_000d: ldarg.0 - IL_000e: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/f3@16::builder@ - IL_0013: newobj instance void assembly/assembly/'f3@14-1'::.ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder) - IL_0018: stloc.2 - IL_0019: ldloc.1 - IL_001a: ldloc.2 - IL_001b: newobj instance void assembly/assembly/'f3@16-9'::.ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_0020: tail. - IL_0022: call class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.AsyncPrimitives::MakeAsync(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn>) - IL_0027: ret + IL_0006: call class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 assembly/assembly::f2() + IL_000b: ldarg.0 + IL_000c: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/f3@16::builder@ + IL_0011: newobj instance void assembly/assembly/'f3@14-1'::.ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder) + IL_0016: tail. + IL_0018: callvirt instance class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder::Bind(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1, + class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) + IL_001d: ret } } diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/AsyncExpressionStepping/AsyncExpressionSteppingTest6.fs.RealInternalSignatureOn.OptimizeOff.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/AsyncExpressionStepping/AsyncExpressionSteppingTest6.fs.RealInternalSignatureOn.OptimizeOff.il.bsl index 8afb27a6f74..22e4769fcca 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/AsyncExpressionStepping/AsyncExpressionSteppingTest6.fs.RealInternalSignatureOn.OptimizeOff.il.bsl +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/AsyncExpressionStepping/AsyncExpressionSteppingTest6.fs.RealInternalSignatureOn.OptimizeOff.il.bsl @@ -37,42 +37,6 @@ extends [runtime]System.Object { .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) - .class auto ansi serializable sealed nested assembly beforefieldinit 'f2@10-1' - extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn> - { - .field public int32 'value' - .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - .method assembly specialname rtspecialname instance void .ctor(int32 'value') 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 ) - - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn>::.ctor() - IL_0006: ldarg.0 - IL_0007: ldarg.1 - IL_0008: stfld int32 assembly/assembly/'f2@10-1'::'value' - IL_000d: ret - } - - .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn Invoke(valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1 ctxt) cil managed - { - - .maxstack 8 - IL_0000: ldarg.1 - IL_0001: ldarg.0 - IL_0002: ldfld int32 assembly/assembly/'f2@10-1'::'value' - IL_0007: tail. - IL_0009: call class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1::Success(valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1, - !0) - IL_000e: ret - } - - } - .class auto ansi serializable sealed nested assembly beforefieldinit f2@5 extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> { @@ -100,9 +64,7 @@ .maxstack 7 .locals init (class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1 V_0, class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1 V_1, - int32 V_2, - class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder V_3, - int32 V_4) + int32 V_2) IL_0000: ldc.i4.0 IL_0001: call class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1 [FSharp.Core]Microsoft.FSharp.Core.Operators::Ref(!!0) IL_0006: stloc.0 @@ -131,50 +93,10 @@ IL_0039: stloc.2 IL_003a: ldarg.0 IL_003b: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/f2@5::builder@ - IL_0040: stloc.3 - IL_0041: ldloc.2 - IL_0042: stloc.s V_4 - IL_0044: ldloc.s V_4 - IL_0046: newobj instance void assembly/assembly/'f2@10-1'::.ctor(int32) - IL_004b: tail. - IL_004d: call class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.AsyncPrimitives::MakeAsync(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn>) - IL_0052: ret - } - - } - - .class auto ansi serializable sealed nested assembly beforefieldinit 'f3@20-5' - extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn> - { - .field public int32 'value' - .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - .method assembly specialname rtspecialname instance void .ctor(int32 'value') 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 ) - - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn>::.ctor() - IL_0006: ldarg.0 - IL_0007: ldarg.1 - IL_0008: stfld int32 assembly/assembly/'f3@20-5'::'value' - IL_000d: ret - } - - .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn Invoke(valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1 ctxt) cil managed - { - - .maxstack 8 - IL_0000: ldarg.1 - IL_0001: ldarg.0 - IL_0002: ldfld int32 assembly/assembly/'f3@20-5'::'value' - IL_0007: tail. - IL_0009: call class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1::Success(valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1, - !0) - IL_000e: ret + IL_0040: ldloc.2 + IL_0041: tail. + IL_0043: callvirt instance class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder::Return(!!0) + IL_0048: ret } } @@ -216,9 +138,7 @@ .maxstack 6 .locals init (int32 V_0, - int32 V_1, - class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder V_2, - int32 V_3) + int32 V_1) IL_0000: ldarg.1 IL_0001: stloc.0 IL_0002: ldarg.0 @@ -232,60 +152,10 @@ IL_0016: stloc.1 IL_0017: ldarg.0 IL_0018: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/'f3@19-4'::builder@ - IL_001d: stloc.2 - IL_001e: ldloc.1 - IL_001f: stloc.3 - IL_0020: ldloc.3 - IL_0021: newobj instance void assembly/assembly/'f3@20-5'::.ctor(int32) - IL_0026: tail. - IL_0028: call class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.AsyncPrimitives::MakeAsync(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn>) - IL_002d: ret - } - - } - - .class auto ansi serializable sealed nested assembly beforefieldinit 'f3@19-6' - extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn> - { - .field public class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 computation - .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - .field public class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> binder - .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - .method assembly specialname rtspecialname instance void .ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 computation, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> binder) 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 ) - - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn>::.ctor() - IL_0006: ldarg.0 - IL_0007: ldarg.1 - IL_0008: stfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 assembly/assembly/'f3@19-6'::computation - IL_000d: ldarg.0 - IL_000e: ldarg.2 - IL_000f: stfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> assembly/assembly/'f3@19-6'::binder - IL_0014: ret - } - - .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn Invoke(valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1 ctxt) cil managed - { - - .maxstack 8 - IL_0000: ldarg.1 - IL_0001: ldarg.0 - IL_0002: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 assembly/assembly/'f3@19-6'::computation - IL_0007: ldarg.0 - IL_0008: ldfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> assembly/assembly/'f3@19-6'::binder - IL_000d: tail. - IL_000f: call class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn [FSharp.Core]Microsoft.FSharp.Control.AsyncPrimitives::Bind(valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1, - class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_0014: ret + IL_001d: ldloc.1 + IL_001e: tail. + IL_0020: callvirt instance class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder::Return(!!0) + IL_0025: ret } } @@ -318,12 +188,9 @@ .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 Invoke(int32 _arg3) cil managed { - .maxstack 7 + .maxstack 9 .locals init (int32 V_0, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1 V_1, - class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder V_2, - class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 V_3, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> V_4) + class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1 V_1) IL_0000: ldarg.1 IL_0001: stloc.0 IL_0002: ldc.i4.0 @@ -338,71 +205,19 @@ IL_0017: nop IL_0018: ldarg.0 IL_0019: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/'f3@16-3'::builder@ - IL_001e: stloc.2 - IL_001f: call class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 assembly/assembly::f2() - IL_0024: stloc.3 - IL_0025: ldarg.0 - IL_0026: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/'f3@16-3'::builder@ - IL_002b: ldarg.0 - IL_002c: ldfld int32 assembly/assembly/'f3@16-3'::x1 - IL_0031: ldloc.1 - IL_0032: newobj instance void assembly/assembly/'f3@19-4'::.ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder, + IL_001e: call class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 assembly/assembly::f2() + IL_0023: ldarg.0 + IL_0024: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/'f3@16-3'::builder@ + IL_0029: ldarg.0 + IL_002a: ldfld int32 assembly/assembly/'f3@16-3'::x1 + IL_002f: ldloc.1 + IL_0030: newobj instance void assembly/assembly/'f3@19-4'::.ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder, int32, class [FSharp.Core]Microsoft.FSharp.Core.FSharpRef`1) - IL_0037: stloc.s V_4 - IL_0039: ldloc.3 - IL_003a: ldloc.s V_4 - IL_003c: newobj instance void assembly/assembly/'f3@19-6'::.ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_0041: tail. - IL_0043: call class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.AsyncPrimitives::MakeAsync(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn>) - IL_0048: ret - } - - } - - .class auto ansi serializable sealed nested assembly beforefieldinit 'f3@16-7' - extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn> - { - .field public class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 computation - .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - .field public class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> binder - .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - .method assembly specialname rtspecialname instance void .ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 computation, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> binder) 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 ) - - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn>::.ctor() - IL_0006: ldarg.0 - IL_0007: ldarg.1 - IL_0008: stfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 assembly/assembly/'f3@16-7'::computation - IL_000d: ldarg.0 - IL_000e: ldarg.2 - IL_000f: stfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> assembly/assembly/'f3@16-7'::binder - IL_0014: ret - } - - .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn Invoke(valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1 ctxt) cil managed - { - - .maxstack 8 - IL_0000: ldarg.1 - IL_0001: ldarg.0 - IL_0002: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 assembly/assembly/'f3@16-7'::computation - IL_0007: ldarg.0 - IL_0008: ldfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> assembly/assembly/'f3@16-7'::binder - IL_000d: tail. - IL_000f: call class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn [FSharp.Core]Microsoft.FSharp.Control.AsyncPrimitives::Bind(valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1, - class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_0014: ret + IL_0035: tail. + IL_0037: callvirt instance class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder::Bind(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1, + class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) + IL_003c: ret } } @@ -435,78 +250,23 @@ .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 Invoke(int32 _arg2) cil managed { - .maxstack 6 - .locals init (int32 V_0, - class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder V_1, - class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 V_2, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> V_3) + .maxstack 8 + .locals init (int32 V_0) IL_0000: ldarg.1 IL_0001: stloc.0 IL_0002: ldarg.0 IL_0003: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/'f3@15-2'::builder@ - IL_0008: stloc.1 - IL_0009: call class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 assembly/assembly::f2() - IL_000e: stloc.2 - IL_000f: ldarg.0 - IL_0010: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/'f3@15-2'::builder@ - IL_0015: ldarg.0 - IL_0016: ldfld int32 assembly/assembly/'f3@15-2'::x1 - IL_001b: newobj instance void assembly/assembly/'f3@16-3'::.ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder, - int32) - IL_0020: stloc.3 - IL_0021: ldloc.2 - IL_0022: ldloc.3 - IL_0023: newobj instance void assembly/assembly/'f3@16-7'::.ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_0028: tail. - IL_002a: call class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.AsyncPrimitives::MakeAsync(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn>) - IL_002f: ret - } - - } - - .class auto ansi serializable sealed nested assembly beforefieldinit 'f3@16-8' - extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn> - { - .field public class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 computation - .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - .field public class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> binder - .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - .method assembly specialname rtspecialname instance void .ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 computation, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> binder) 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 ) - - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn>::.ctor() - IL_0006: ldarg.0 - IL_0007: ldarg.1 - IL_0008: stfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 assembly/assembly/'f3@16-8'::computation + IL_0008: call class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 assembly/assembly::f2() IL_000d: ldarg.0 - IL_000e: ldarg.2 - IL_000f: stfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> assembly/assembly/'f3@16-8'::binder - IL_0014: ret - } - - .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn Invoke(valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1 ctxt) cil managed - { - - .maxstack 8 - IL_0000: ldarg.1 - IL_0001: ldarg.0 - IL_0002: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 assembly/assembly/'f3@16-8'::computation - IL_0007: ldarg.0 - IL_0008: ldfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> assembly/assembly/'f3@16-8'::binder - IL_000d: tail. - IL_000f: call class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn [FSharp.Core]Microsoft.FSharp.Control.AsyncPrimitives::Bind(valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1, - class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_0014: ret + IL_000e: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/'f3@15-2'::builder@ + IL_0013: ldarg.0 + IL_0014: ldfld int32 assembly/assembly/'f3@15-2'::x1 + IL_0019: newobj instance void assembly/assembly/'f3@16-3'::.ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder, + int32) + IL_001e: tail. + IL_0020: callvirt instance class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder::Bind(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1, + class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) + IL_0025: ret } } @@ -535,77 +295,22 @@ .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 Invoke(int32 _arg1) cil managed { - .maxstack 6 - .locals init (int32 V_0, - class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder V_1, - class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 V_2, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> V_3) + .maxstack 8 + .locals init (int32 V_0) IL_0000: ldarg.1 IL_0001: stloc.0 IL_0002: ldarg.0 IL_0003: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/'f3@14-1'::builder@ - IL_0008: stloc.1 - IL_0009: call class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 assembly/assembly::f2() - IL_000e: stloc.2 - IL_000f: ldarg.0 - IL_0010: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/'f3@14-1'::builder@ - IL_0015: ldloc.0 - IL_0016: newobj instance void assembly/assembly/'f3@15-2'::.ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder, - int32) - IL_001b: stloc.3 - IL_001c: ldloc.2 - IL_001d: ldloc.3 - IL_001e: newobj instance void assembly/assembly/'f3@16-8'::.ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_0023: tail. - IL_0025: call class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.AsyncPrimitives::MakeAsync(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn>) - IL_002a: ret - } - - } - - .class auto ansi serializable sealed nested assembly beforefieldinit 'f3@16-9' - extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn> - { - .field public class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 computation - .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - .field public class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> binder - .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) - .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) - .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) - .method assembly specialname rtspecialname instance void .ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 computation, class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> binder) 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 ) - - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn>::.ctor() - IL_0006: ldarg.0 - IL_0007: ldarg.1 - IL_0008: stfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 assembly/assembly/'f3@16-9'::computation + IL_0008: call class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 assembly/assembly::f2() IL_000d: ldarg.0 - IL_000e: ldarg.2 - IL_000f: stfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> assembly/assembly/'f3@16-9'::binder - IL_0014: ret - } - - .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn Invoke(valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1 ctxt) cil managed - { - - .maxstack 8 - IL_0000: ldarg.1 - IL_0001: ldarg.0 - IL_0002: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 assembly/assembly/'f3@16-9'::computation - IL_0007: ldarg.0 - IL_0008: ldfld class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> assembly/assembly/'f3@16-9'::binder - IL_000d: tail. - IL_000f: call class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn [FSharp.Core]Microsoft.FSharp.Control.AsyncPrimitives::Bind(valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1, - class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_0014: ret + IL_000e: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/'f3@14-1'::builder@ + IL_0013: ldloc.0 + IL_0014: newobj instance void assembly/assembly/'f3@15-2'::.ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder, + int32) + IL_0019: tail. + IL_001b: callvirt instance class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder::Bind(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1, + class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) + IL_0020: ret } } @@ -634,26 +339,17 @@ .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 Invoke(class [FSharp.Core]Microsoft.FSharp.Core.Unit unitVar) cil managed { - .maxstack 6 - .locals init (class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder V_0, - class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 V_1, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2> V_2) + .maxstack 8 IL_0000: ldarg.0 IL_0001: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/f3@16::builder@ - IL_0006: stloc.0 - IL_0007: call class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 assembly/assembly::f2() - IL_000c: stloc.1 - IL_000d: ldarg.0 - IL_000e: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/f3@16::builder@ - IL_0013: newobj instance void assembly/assembly/'f3@14-1'::.ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder) - IL_0018: stloc.2 - IL_0019: ldloc.1 - IL_001a: ldloc.2 - IL_001b: newobj instance void assembly/assembly/'f3@16-9'::.ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) - IL_0020: tail. - IL_0022: call class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.AsyncPrimitives::MakeAsync(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn>) - IL_0027: ret + IL_0006: call class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 assembly/assembly::f2() + IL_000b: ldarg.0 + IL_000c: ldfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder assembly/assembly/f3@16::builder@ + IL_0011: newobj instance void assembly/assembly/'f3@14-1'::.ctor(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder) + IL_0016: tail. + IL_0018: callvirt instance class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder::Bind(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1, + class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) + IL_001d: ret } } diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/MethodImplNoInline02.fs.RealInternalSignatureOff.OptimizeOff.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/MethodImplNoInline02.fs.RealInternalSignatureOff.OptimizeOff.il.bsl index 0168c04c588..5090f0e752e 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/MethodImplNoInline02.fs.RealInternalSignatureOff.OptimizeOff.il.bsl +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/MethodImplNoInline02.fs.RealInternalSignatureOff.OptimizeOff.il.bsl @@ -67,7 +67,7 @@ .entrypoint .maxstack 8 - IL_0000: call void assembly::g() + IL_0000: call void assembly::f() IL_0005: nop IL_0006: ret } @@ -78,4 +78,3 @@ - diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/MethodImplNoInline02.fs.RealInternalSignatureOn.OptimizeOff.il.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/MethodImplNoInline02.fs.RealInternalSignatureOn.OptimizeOff.il.bsl index 170b3c6df09..7d67a6cf637 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/MethodImplNoInline02.fs.RealInternalSignatureOn.OptimizeOff.il.bsl +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Misc/MethodImplNoInline02.fs.RealInternalSignatureOn.OptimizeOff.il.bsl @@ -68,7 +68,7 @@ { .maxstack 8 - IL_0000: call void assembly::g() + IL_0000: call void assembly::f() IL_0005: nop IL_0006: ret } diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Tuples/OptionalArg01.fs.OptimizeOff.il.netcore.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Tuples/OptionalArg01.fs.OptimizeOff.il.netcore.bsl index bfce2457d09..85086b6d488 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Tuples/OptionalArg01.fs.OptimizeOff.il.netcore.bsl +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Tuples/OptionalArg01.fs.OptimizeOff.il.netcore.bsl @@ -177,409 +177,49 @@ .method public static class [runtime]System.Collections.Generic.List`1 test() cil managed { - .maxstack 4 - .locals init (class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_0, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_1, - int32 V_2, - int32 V_3, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_4, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_5, - int32 V_6, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_7, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_8, - class [runtime]System.Collections.Generic.List`1 V_9, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_10, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_11, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_12, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_13) + .maxstack 8 IL_0000: ldnull - IL_0001: stloc.0 - IL_0002: ldnull - IL_0003: stloc.1 - IL_0004: ldc.i4.0 - IL_0005: stloc.2 - IL_0006: ldloc.0 - IL_0007: stloc.s V_4 - IL_0009: ldloc.s V_4 - IL_000b: brfalse.s IL_000f - - IL_000d: br.s IL_0013 - - IL_000f: ldloc.2 - IL_0010: nop - IL_0011: br.s IL_001b - - IL_0013: ldloc.s V_4 - IL_0015: stloc.s V_5 - IL_0017: ldloc.2 - IL_0018: ldc.i4.1 - IL_0019: add - IL_001a: nop - IL_001b: stloc.3 - IL_001c: ldloc.1 - IL_001d: stloc.s V_7 - IL_001f: ldloc.s V_7 - IL_0021: brfalse.s IL_0025 - - IL_0023: br.s IL_0029 - - IL_0025: ldloc.3 - IL_0026: nop - IL_0027: br.s IL_0031 - - IL_0029: ldloc.s V_7 - IL_002b: stloc.s V_8 - IL_002d: ldloc.3 - IL_002e: ldc.i4.1 - IL_002f: add - IL_0030: nop - IL_0031: stloc.s V_6 - IL_0033: ldloc.s V_6 - IL_0035: newobj instance void class [runtime]System.Collections.Generic.List`1::.ctor(int32) - IL_003a: stloc.s V_9 - IL_003c: ldloc.0 - IL_003d: stloc.s V_10 - IL_003f: ldloc.s V_10 - IL_0041: brfalse.s IL_0045 - - IL_0043: br.s IL_0048 - - IL_0045: nop - IL_0046: br.s IL_005b - - IL_0048: ldloc.s V_10 - IL_004a: stloc.s V_11 - IL_004c: ldloc.s V_9 - IL_004e: ldloc.s V_11 - IL_0050: call instance !0 class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1::get_Value() - IL_0055: callvirt instance void class [runtime]System.Collections.Generic.List`1::Add(!0) - IL_005a: nop - IL_005b: ldloc.1 - IL_005c: stloc.s V_12 - IL_005e: ldloc.s V_12 - IL_0060: brfalse.s IL_0064 - - IL_0062: br.s IL_0067 - - IL_0064: nop - IL_0065: br.s IL_007a - - IL_0067: ldloc.s V_12 - IL_0069: stloc.s V_13 - IL_006b: ldloc.s V_9 - IL_006d: ldloc.s V_13 - IL_006f: call instance !0 class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1::get_Value() - IL_0074: callvirt instance void class [runtime]System.Collections.Generic.List`1::Add(!0) - IL_0079: nop - IL_007a: ldloc.s V_9 - IL_007c: ret + IL_0001: ldnull + IL_0002: call class [runtime]System.Collections.Generic.List`1 assembly/C::F(class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1, + class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1) + IL_0007: ret } .method public static class [runtime]System.Collections.Generic.List`1 test2() cil managed { - .maxstack 4 - .locals init (class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_0, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_1, - int32 V_2, - int32 V_3, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_4, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_5, - int32 V_6, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_7, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_8, - class [runtime]System.Collections.Generic.List`1 V_9, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_10, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_11, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_12, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_13) + .maxstack 8 IL_0000: newobj instance void assembly/A::.ctor() IL_0005: call class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1::Some(!0) - IL_000a: stloc.0 - IL_000b: ldnull - IL_000c: stloc.1 - IL_000d: ldc.i4.0 - IL_000e: stloc.2 - IL_000f: ldloc.0 - IL_0010: stloc.s V_4 - IL_0012: ldloc.s V_4 - IL_0014: brfalse.s IL_0018 - - IL_0016: br.s IL_001c - - IL_0018: ldloc.2 - IL_0019: nop - IL_001a: br.s IL_0024 - - IL_001c: ldloc.s V_4 - IL_001e: stloc.s V_5 - IL_0020: ldloc.2 - IL_0021: ldc.i4.1 - IL_0022: add - IL_0023: nop - IL_0024: stloc.3 - IL_0025: ldloc.1 - IL_0026: stloc.s V_7 - IL_0028: ldloc.s V_7 - IL_002a: brfalse.s IL_002e - - IL_002c: br.s IL_0032 - - IL_002e: ldloc.3 - IL_002f: nop - IL_0030: br.s IL_003a - - IL_0032: ldloc.s V_7 - IL_0034: stloc.s V_8 - IL_0036: ldloc.3 - IL_0037: ldc.i4.1 - IL_0038: add - IL_0039: nop - IL_003a: stloc.s V_6 - IL_003c: ldloc.s V_6 - IL_003e: newobj instance void class [runtime]System.Collections.Generic.List`1::.ctor(int32) - IL_0043: stloc.s V_9 - IL_0045: ldloc.0 - IL_0046: stloc.s V_10 - IL_0048: ldloc.s V_10 - IL_004a: brfalse.s IL_004e - - IL_004c: br.s IL_0051 - - IL_004e: nop - IL_004f: br.s IL_0064 - - IL_0051: ldloc.s V_10 - IL_0053: stloc.s V_11 - IL_0055: ldloc.s V_9 - IL_0057: ldloc.s V_11 - IL_0059: call instance !0 class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1::get_Value() - IL_005e: callvirt instance void class [runtime]System.Collections.Generic.List`1::Add(!0) - IL_0063: nop - IL_0064: ldloc.1 - IL_0065: stloc.s V_12 - IL_0067: ldloc.s V_12 - IL_0069: brfalse.s IL_006d - - IL_006b: br.s IL_0070 - - IL_006d: nop - IL_006e: br.s IL_0083 - - IL_0070: ldloc.s V_12 - IL_0072: stloc.s V_13 - IL_0074: ldloc.s V_9 - IL_0076: ldloc.s V_13 - IL_0078: call instance !0 class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1::get_Value() - IL_007d: callvirt instance void class [runtime]System.Collections.Generic.List`1::Add(!0) - IL_0082: nop - IL_0083: ldloc.s V_9 - IL_0085: ret + IL_000a: ldnull + IL_000b: call class [runtime]System.Collections.Generic.List`1 assembly/C::F(class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1, + class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1) + IL_0010: ret } .method public static class [runtime]System.Collections.Generic.List`1 test3() cil managed { - .maxstack 4 - .locals init (class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_0, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_1, - int32 V_2, - int32 V_3, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_4, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_5, - int32 V_6, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_7, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_8, - class [runtime]System.Collections.Generic.List`1 V_9, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_10, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_11, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_12, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_13) + .maxstack 8 IL_0000: ldnull - IL_0001: stloc.0 - IL_0002: newobj instance void assembly/A::.ctor() - IL_0007: call class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1::Some(!0) - IL_000c: stloc.1 - IL_000d: ldc.i4.0 - IL_000e: stloc.2 - IL_000f: ldloc.0 - IL_0010: stloc.s V_4 - IL_0012: ldloc.s V_4 - IL_0014: brfalse.s IL_0018 - - IL_0016: br.s IL_001c - - IL_0018: ldloc.2 - IL_0019: nop - IL_001a: br.s IL_0024 - - IL_001c: ldloc.s V_4 - IL_001e: stloc.s V_5 - IL_0020: ldloc.2 - IL_0021: ldc.i4.1 - IL_0022: add - IL_0023: nop - IL_0024: stloc.3 - IL_0025: ldloc.1 - IL_0026: stloc.s V_7 - IL_0028: ldloc.s V_7 - IL_002a: brfalse.s IL_002e - - IL_002c: br.s IL_0032 - - IL_002e: ldloc.3 - IL_002f: nop - IL_0030: br.s IL_003a - - IL_0032: ldloc.s V_7 - IL_0034: stloc.s V_8 - IL_0036: ldloc.3 - IL_0037: ldc.i4.1 - IL_0038: add - IL_0039: nop - IL_003a: stloc.s V_6 - IL_003c: ldloc.s V_6 - IL_003e: newobj instance void class [runtime]System.Collections.Generic.List`1::.ctor(int32) - IL_0043: stloc.s V_9 - IL_0045: ldloc.0 - IL_0046: stloc.s V_10 - IL_0048: ldloc.s V_10 - IL_004a: brfalse.s IL_004e - - IL_004c: br.s IL_0051 - - IL_004e: nop - IL_004f: br.s IL_0064 - - IL_0051: ldloc.s V_10 - IL_0053: stloc.s V_11 - IL_0055: ldloc.s V_9 - IL_0057: ldloc.s V_11 - IL_0059: call instance !0 class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1::get_Value() - IL_005e: callvirt instance void class [runtime]System.Collections.Generic.List`1::Add(!0) - IL_0063: nop - IL_0064: ldloc.1 - IL_0065: stloc.s V_12 - IL_0067: ldloc.s V_12 - IL_0069: brfalse.s IL_006d - - IL_006b: br.s IL_0070 - - IL_006d: nop - IL_006e: br.s IL_0083 - - IL_0070: ldloc.s V_12 - IL_0072: stloc.s V_13 - IL_0074: ldloc.s V_9 - IL_0076: ldloc.s V_13 - IL_0078: call instance !0 class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1::get_Value() - IL_007d: callvirt instance void class [runtime]System.Collections.Generic.List`1::Add(!0) - IL_0082: nop - IL_0083: ldloc.s V_9 - IL_0085: ret + IL_0001: newobj instance void assembly/A::.ctor() + IL_0006: call class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1::Some(!0) + IL_000b: call class [runtime]System.Collections.Generic.List`1 assembly/C::F(class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1, + class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1) + IL_0010: ret } .method public static class [runtime]System.Collections.Generic.List`1 test4() cil managed { - .maxstack 4 - .locals init (class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_0, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_1, - int32 V_2, - int32 V_3, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_4, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_5, - int32 V_6, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_7, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_8, - class [runtime]System.Collections.Generic.List`1 V_9, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_10, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_11, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_12, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_13) + .maxstack 8 IL_0000: newobj instance void assembly/A::.ctor() IL_0005: call class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1::Some(!0) - IL_000a: stloc.0 - IL_000b: newobj instance void assembly/A::.ctor() - IL_0010: call class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1::Some(!0) - IL_0015: stloc.1 - IL_0016: ldc.i4.0 - IL_0017: stloc.2 - IL_0018: ldloc.0 - IL_0019: stloc.s V_4 - IL_001b: ldloc.s V_4 - IL_001d: brfalse.s IL_0021 - - IL_001f: br.s IL_0025 - - IL_0021: ldloc.2 - IL_0022: nop - IL_0023: br.s IL_002d - - IL_0025: ldloc.s V_4 - IL_0027: stloc.s V_5 - IL_0029: ldloc.2 - IL_002a: ldc.i4.1 - IL_002b: add - IL_002c: nop - IL_002d: stloc.3 - IL_002e: ldloc.1 - IL_002f: stloc.s V_7 - IL_0031: ldloc.s V_7 - IL_0033: brfalse.s IL_0037 - - IL_0035: br.s IL_003b - - IL_0037: ldloc.3 - IL_0038: nop - IL_0039: br.s IL_0043 - - IL_003b: ldloc.s V_7 - IL_003d: stloc.s V_8 - IL_003f: ldloc.3 - IL_0040: ldc.i4.1 - IL_0041: add - IL_0042: nop - IL_0043: stloc.s V_6 - IL_0045: ldloc.s V_6 - IL_0047: newobj instance void class [runtime]System.Collections.Generic.List`1::.ctor(int32) - IL_004c: stloc.s V_9 - IL_004e: ldloc.0 - IL_004f: stloc.s V_10 - IL_0051: ldloc.s V_10 - IL_0053: brfalse.s IL_0057 - - IL_0055: br.s IL_005a - - IL_0057: nop - IL_0058: br.s IL_006d - - IL_005a: ldloc.s V_10 - IL_005c: stloc.s V_11 - IL_005e: ldloc.s V_9 - IL_0060: ldloc.s V_11 - IL_0062: call instance !0 class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1::get_Value() - IL_0067: callvirt instance void class [runtime]System.Collections.Generic.List`1::Add(!0) - IL_006c: nop - IL_006d: ldloc.1 - IL_006e: stloc.s V_12 - IL_0070: ldloc.s V_12 - IL_0072: brfalse.s IL_0076 - - IL_0074: br.s IL_0079 - - IL_0076: nop - IL_0077: br.s IL_008c - - IL_0079: ldloc.s V_12 - IL_007b: stloc.s V_13 - IL_007d: ldloc.s V_9 - IL_007f: ldloc.s V_13 - IL_0081: call instance !0 class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1::get_Value() - IL_0086: callvirt instance void class [runtime]System.Collections.Generic.List`1::Add(!0) - IL_008b: nop - IL_008c: ldloc.s V_9 - IL_008e: ret + IL_000a: newobj instance void assembly/A::.ctor() + IL_000f: call class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1::Some(!0) + IL_0014: call class [runtime]System.Collections.Generic.List`1 assembly/C::F(class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1, + class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1) + IL_0019: ret } } diff --git a/tests/FSharp.Compiler.Service.Tests/ExprTests.fs b/tests/FSharp.Compiler.Service.Tests/ExprTests.fs index e2cb6787ebd..40f674b4f8b 100644 --- a/tests/FSharp.Compiler.Service.Tests/ExprTests.fs +++ b/tests/FSharp.Compiler.Service.Tests/ExprTests.fs @@ -917,8 +917,8 @@ let ``Test Optimized Declarations Project1`` () = "let testTypeOf(x) = Operators.TypeOf<'T> () @ (17,24--17,30)"; "let mutableVar(x) = (if Operators.op_GreaterThan (x,0) then let mutable acc: Microsoft.FSharp.Core.int = x in acc <- x else ()) @ (20,4--22,16)"; "let mutableConst(unitVar0) = let mutable acc: Microsoft.FSharp.Core.unit = () in acc <- () @ (25,16--25,19)"; - "let testMutableVar = let x: Microsoft.FSharp.Core.int = 1 in (if Operators.op_GreaterThan (x,0) then let mutable acc: Microsoft.FSharp.Core.int = x in acc <- x else ()) @ (28,21--28,33)"; - "let testMutableConst = let mutable acc: Microsoft.FSharp.Core.unit = () in acc <- () @ (29,23--29,38)"] + "let testMutableVar = N.mutableVar (1) @ (28,21--28,33)"; + "let testMutableConst = N.mutableConst (()) @ (29,23--29,38)"] // printFSharpDecls "" file2.Declarations |> Seq.iter (printfn "%s") printfn "// optimized" From 4987ff40d01c07b33cdf5d5de5c9f1f7b94eea94 Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Thu, 14 May 2026 11:50:00 +0200 Subject: [PATCH 35/35] Update baselines --- ...OptionalArg01.fs.OptimizeOff.il.net472.bsl | 430 ++---------------- 1 file changed, 35 insertions(+), 395 deletions(-) diff --git a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Tuples/OptionalArg01.fs.OptimizeOff.il.net472.bsl b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Tuples/OptionalArg01.fs.OptimizeOff.il.net472.bsl index 1db5018d510..46e66821bf5 100644 --- a/tests/FSharp.Compiler.ComponentTests/EmittedIL/Tuples/OptionalArg01.fs.OptimizeOff.il.net472.bsl +++ b/tests/FSharp.Compiler.ComponentTests/EmittedIL/Tuples/OptionalArg01.fs.OptimizeOff.il.net472.bsl @@ -188,417 +188,57 @@ } - .method public static class [runtime]System.Collections.Generic.List`1 + .method public static class [runtime]System.Collections.Generic.List`1 test() cil managed { - - .maxstack 4 - .locals init (class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_0, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_1, - int32 V_2, - int32 V_3, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_4, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_5, - int32 V_6, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_7, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_8, - class [runtime]System.Collections.Generic.List`1 V_9, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_10, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_11, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_12, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_13) + + .maxstack 8 IL_0000: ldnull - IL_0001: stloc.0 - IL_0002: ldnull - IL_0003: stloc.1 - IL_0004: ldc.i4.0 - IL_0005: stloc.2 - IL_0006: ldloc.0 - IL_0007: stloc.s V_4 - IL_0009: ldloc.s V_4 - IL_000b: brfalse.s IL_000f - - IL_000d: br.s IL_0013 - - IL_000f: ldloc.2 - IL_0010: nop - IL_0011: br.s IL_001b - - IL_0013: ldloc.s V_4 - IL_0015: stloc.s V_5 - IL_0017: ldloc.2 - IL_0018: ldc.i4.1 - IL_0019: add - IL_001a: nop - IL_001b: stloc.3 - IL_001c: ldloc.1 - IL_001d: stloc.s V_7 - IL_001f: ldloc.s V_7 - IL_0021: brfalse.s IL_0025 - - IL_0023: br.s IL_0029 - - IL_0025: ldloc.3 - IL_0026: nop - IL_0027: br.s IL_0031 - - IL_0029: ldloc.s V_7 - IL_002b: stloc.s V_8 - IL_002d: ldloc.3 - IL_002e: ldc.i4.1 - IL_002f: add - IL_0030: nop - IL_0031: stloc.s V_6 - IL_0033: ldloc.s V_6 - IL_0035: newobj instance void class [runtime]System.Collections.Generic.List`1::.ctor(int32) - IL_003a: stloc.s V_9 - IL_003c: ldloc.0 - IL_003d: stloc.s V_10 - IL_003f: ldloc.s V_10 - IL_0041: brfalse.s IL_0045 - - IL_0043: br.s IL_0048 - - IL_0045: nop - IL_0046: br.s IL_005b - - IL_0048: ldloc.s V_10 - IL_004a: stloc.s V_11 - IL_004c: ldloc.s V_9 - IL_004e: ldloc.s V_11 - IL_0050: call instance !0 class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1::get_Value() - IL_0055: callvirt instance void class [runtime]System.Collections.Generic.List`1::Add(!0) - IL_005a: nop - IL_005b: ldloc.1 - IL_005c: stloc.s V_12 - IL_005e: ldloc.s V_12 - IL_0060: brfalse.s IL_0064 - - IL_0062: br.s IL_0067 - - IL_0064: nop - IL_0065: br.s IL_007a - - IL_0067: ldloc.s V_12 - IL_0069: stloc.s V_13 - IL_006b: ldloc.s V_9 - IL_006d: ldloc.s V_13 - IL_006f: call instance !0 class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1::get_Value() - IL_0074: callvirt instance void class [runtime]System.Collections.Generic.List`1::Add(!0) - IL_0079: nop - IL_007a: ldloc.s V_9 - IL_007c: ret - } + IL_0001: ldnull + IL_0002: call class [runtime]System.Collections.Generic.List`1 assembly/C::F(class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1, + class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1) + IL_0007: ret + } - .method public static class [runtime]System.Collections.Generic.List`1 + .method public static class [runtime]System.Collections.Generic.List`1 test2() cil managed { - - .maxstack 4 - .locals init (class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_0, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_1, - int32 V_2, - int32 V_3, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_4, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_5, - int32 V_6, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_7, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_8, - class [runtime]System.Collections.Generic.List`1 V_9, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_10, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_11, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_12, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_13) + + .maxstack 8 IL_0000: newobj instance void assembly/A::.ctor() IL_0005: call class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1::Some(!0) - IL_000a: stloc.0 - IL_000b: ldnull - IL_000c: stloc.1 - IL_000d: ldc.i4.0 - IL_000e: stloc.2 - IL_000f: ldloc.0 - IL_0010: stloc.s V_4 - IL_0012: ldloc.s V_4 - IL_0014: brfalse.s IL_0018 - - IL_0016: br.s IL_001c - - IL_0018: ldloc.2 - IL_0019: nop - IL_001a: br.s IL_0024 - - IL_001c: ldloc.s V_4 - IL_001e: stloc.s V_5 - IL_0020: ldloc.2 - IL_0021: ldc.i4.1 - IL_0022: add - IL_0023: nop - IL_0024: stloc.3 - IL_0025: ldloc.1 - IL_0026: stloc.s V_7 - IL_0028: ldloc.s V_7 - IL_002a: brfalse.s IL_002e - - IL_002c: br.s IL_0032 - - IL_002e: ldloc.3 - IL_002f: nop - IL_0030: br.s IL_003a - - IL_0032: ldloc.s V_7 - IL_0034: stloc.s V_8 - IL_0036: ldloc.3 - IL_0037: ldc.i4.1 - IL_0038: add - IL_0039: nop - IL_003a: stloc.s V_6 - IL_003c: ldloc.s V_6 - IL_003e: newobj instance void class [runtime]System.Collections.Generic.List`1::.ctor(int32) - IL_0043: stloc.s V_9 - IL_0045: ldloc.0 - IL_0046: stloc.s V_10 - IL_0048: ldloc.s V_10 - IL_004a: brfalse.s IL_004e - - IL_004c: br.s IL_0051 - - IL_004e: nop - IL_004f: br.s IL_0064 - - IL_0051: ldloc.s V_10 - IL_0053: stloc.s V_11 - IL_0055: ldloc.s V_9 - IL_0057: ldloc.s V_11 - IL_0059: call instance !0 class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1::get_Value() - IL_005e: callvirt instance void class [runtime]System.Collections.Generic.List`1::Add(!0) - IL_0063: nop - IL_0064: ldloc.1 - IL_0065: stloc.s V_12 - IL_0067: ldloc.s V_12 - IL_0069: brfalse.s IL_006d - - IL_006b: br.s IL_0070 - - IL_006d: nop - IL_006e: br.s IL_0083 - - IL_0070: ldloc.s V_12 - IL_0072: stloc.s V_13 - IL_0074: ldloc.s V_9 - IL_0076: ldloc.s V_13 - IL_0078: call instance !0 class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1::get_Value() - IL_007d: callvirt instance void class [runtime]System.Collections.Generic.List`1::Add(!0) - IL_0082: nop - IL_0083: ldloc.s V_9 - IL_0085: ret - } + IL_000a: ldnull + IL_000b: call class [runtime]System.Collections.Generic.List`1 assembly/C::F(class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1, + class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1) + IL_0010: ret + } - .method public static class [runtime]System.Collections.Generic.List`1 + .method public static class [runtime]System.Collections.Generic.List`1 test3() cil managed { - - .maxstack 4 - .locals init (class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_0, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_1, - int32 V_2, - int32 V_3, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_4, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_5, - int32 V_6, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_7, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_8, - class [runtime]System.Collections.Generic.List`1 V_9, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_10, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_11, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_12, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_13) - IL_0000: ldnull - IL_0001: stloc.0 - IL_0002: newobj instance void assembly/A::.ctor() - IL_0007: call class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1::Some(!0) - IL_000c: stloc.1 - IL_000d: ldc.i4.0 - IL_000e: stloc.2 - IL_000f: ldloc.0 - IL_0010: stloc.s V_4 - IL_0012: ldloc.s V_4 - IL_0014: brfalse.s IL_0018 - - IL_0016: br.s IL_001c - - IL_0018: ldloc.2 - IL_0019: nop - IL_001a: br.s IL_0024 - - IL_001c: ldloc.s V_4 - IL_001e: stloc.s V_5 - IL_0020: ldloc.2 - IL_0021: ldc.i4.1 - IL_0022: add - IL_0023: nop - IL_0024: stloc.3 - IL_0025: ldloc.1 - IL_0026: stloc.s V_7 - IL_0028: ldloc.s V_7 - IL_002a: brfalse.s IL_002e - - IL_002c: br.s IL_0032 - - IL_002e: ldloc.3 - IL_002f: nop - IL_0030: br.s IL_003a - - IL_0032: ldloc.s V_7 - IL_0034: stloc.s V_8 - IL_0036: ldloc.3 - IL_0037: ldc.i4.1 - IL_0038: add - IL_0039: nop - IL_003a: stloc.s V_6 - IL_003c: ldloc.s V_6 - IL_003e: newobj instance void class [runtime]System.Collections.Generic.List`1::.ctor(int32) - IL_0043: stloc.s V_9 - IL_0045: ldloc.0 - IL_0046: stloc.s V_10 - IL_0048: ldloc.s V_10 - IL_004a: brfalse.s IL_004e - - IL_004c: br.s IL_0051 - - IL_004e: nop - IL_004f: br.s IL_0064 - - IL_0051: ldloc.s V_10 - IL_0053: stloc.s V_11 - IL_0055: ldloc.s V_9 - IL_0057: ldloc.s V_11 - IL_0059: call instance !0 class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1::get_Value() - IL_005e: callvirt instance void class [runtime]System.Collections.Generic.List`1::Add(!0) - IL_0063: nop - IL_0064: ldloc.1 - IL_0065: stloc.s V_12 - IL_0067: ldloc.s V_12 - IL_0069: brfalse.s IL_006d - - IL_006b: br.s IL_0070 - - IL_006d: nop - IL_006e: br.s IL_0083 - - IL_0070: ldloc.s V_12 - IL_0072: stloc.s V_13 - IL_0074: ldloc.s V_9 - IL_0076: ldloc.s V_13 - IL_0078: call instance !0 class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1::get_Value() - IL_007d: callvirt instance void class [runtime]System.Collections.Generic.List`1::Add(!0) - IL_0082: nop - IL_0083: ldloc.s V_9 - IL_0085: ret - } - .method public static class [runtime]System.Collections.Generic.List`1 + .maxstack 8 + IL_0000: ldnull + IL_0001: newobj instance void assembly/A::.ctor() + IL_0006: call class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1::Some(!0) + IL_000b: call class [runtime]System.Collections.Generic.List`1 assembly/C::F(class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1, + class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1) + IL_0010: ret + } + + .method public static class [runtime]System.Collections.Generic.List`1 test4() cil managed { - - .maxstack 4 - .locals init (class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_0, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_1, - int32 V_2, - int32 V_3, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_4, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_5, - int32 V_6, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_7, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_8, - class [runtime]System.Collections.Generic.List`1 V_9, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_10, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_11, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_12, - class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 V_13) + + .maxstack 8 IL_0000: newobj instance void assembly/A::.ctor() IL_0005: call class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1::Some(!0) - IL_000a: stloc.0 - IL_000b: newobj instance void assembly/A::.ctor() - IL_0010: call class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1::Some(!0) - IL_0015: stloc.1 - IL_0016: ldc.i4.0 - IL_0017: stloc.2 - IL_0018: ldloc.0 - IL_0019: stloc.s V_4 - IL_001b: ldloc.s V_4 - IL_001d: brfalse.s IL_0021 - - IL_001f: br.s IL_0025 - - IL_0021: ldloc.2 - IL_0022: nop - IL_0023: br.s IL_002d - - IL_0025: ldloc.s V_4 - IL_0027: stloc.s V_5 - IL_0029: ldloc.2 - IL_002a: ldc.i4.1 - IL_002b: add - IL_002c: nop - IL_002d: stloc.3 - IL_002e: ldloc.1 - IL_002f: stloc.s V_7 - IL_0031: ldloc.s V_7 - IL_0033: brfalse.s IL_0037 - - IL_0035: br.s IL_003b - - IL_0037: ldloc.3 - IL_0038: nop - IL_0039: br.s IL_0043 - - IL_003b: ldloc.s V_7 - IL_003d: stloc.s V_8 - IL_003f: ldloc.3 - IL_0040: ldc.i4.1 - IL_0041: add - IL_0042: nop - IL_0043: stloc.s V_6 - IL_0045: ldloc.s V_6 - IL_0047: newobj instance void class [runtime]System.Collections.Generic.List`1::.ctor(int32) - IL_004c: stloc.s V_9 - IL_004e: ldloc.0 - IL_004f: stloc.s V_10 - IL_0051: ldloc.s V_10 - IL_0053: brfalse.s IL_0057 - - IL_0055: br.s IL_005a - - IL_0057: nop - IL_0058: br.s IL_006d - - IL_005a: ldloc.s V_10 - IL_005c: stloc.s V_11 - IL_005e: ldloc.s V_9 - IL_0060: ldloc.s V_11 - IL_0062: call instance !0 class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1::get_Value() - IL_0067: callvirt instance void class [runtime]System.Collections.Generic.List`1::Add(!0) - IL_006c: nop - IL_006d: ldloc.1 - IL_006e: stloc.s V_12 - IL_0070: ldloc.s V_12 - IL_0072: brfalse.s IL_0076 - - IL_0074: br.s IL_0079 - - IL_0076: nop - IL_0077: br.s IL_008c - - IL_0079: ldloc.s V_12 - IL_007b: stloc.s V_13 - IL_007d: ldloc.s V_9 - IL_007f: ldloc.s V_13 - IL_0081: call instance !0 class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1::get_Value() - IL_0086: callvirt instance void class [runtime]System.Collections.Generic.List`1::Add(!0) - IL_008b: nop - IL_008c: ldloc.s V_9 - IL_008e: ret - } + IL_000a: newobj instance void assembly/A::.ctor() + IL_000f: call class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1::Some(!0) + IL_0014: call class [runtime]System.Collections.Generic.List`1 assembly/C::F(class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1, + class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1) + IL_0019: ret + } }