diff --git a/eng/Versions.props b/eng/Versions.props index 3e989e6aa60..e80315e3e49 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -25,7 +25,7 @@ 16 - 1 + 2 $(VSMajorVersion).0 $(VSMajorVersion).$(VSMinorVersion).0 $(VSAssemblyVersionPrefix).0 diff --git a/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj b/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj index d3e78c9f637..ef30acc7efc 100644 --- a/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj +++ b/fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj @@ -434,6 +434,9 @@ Logic/CheckFormatStrings.fs + + Logic/FindUnsolved.fsi + Logic/FindUnsolved.fs @@ -473,9 +476,15 @@ Optimize/InnerLambdasToTopLevelFuncs.fs + + Optimize/LowerCallsAndSeqs.fsi + Optimize/LowerCallsAndSeqs.fs + + Optimize/autobox.fsi + Optimize/autobox.fs diff --git a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj index b4e55930431..b770a3cb615 100644 --- a/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj +++ b/src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj @@ -447,6 +447,9 @@ Logic\CheckFormatStrings.fs + + Logic\FindUnsolved.fsi + Logic\FindUnsolved.fs @@ -468,8 +471,6 @@ Logic\TypeChecker.fs - - Optimize\Optimizer.fsi @@ -488,9 +489,15 @@ Optimize\InnerLambdasToTopLevelFuncs.fs + + Optimize\LowerCallsAndSeqs.fsi + Optimize\LowerCallsAndSeqs.fs + + Optimize\autobox.fsi + Optimize\autobox.fs diff --git a/src/fsharp/FindUnsolved.fsi b/src/fsharp/FindUnsolved.fsi new file mode 100644 index 00000000000..c7c63d8335e --- /dev/null +++ b/src/fsharp/FindUnsolved.fsi @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + + +module internal FSharp.Compiler.FindUnsolved + +open FSharp.Compiler.Tast +open FSharp.Compiler.Tastops +open FSharp.Compiler.TcGlobals +open FSharp.Compiler.Import + +/// Find all unsolved inference variables after type inference for an entire file +val UnsolvedTyparsOfModuleDef: g: TcGlobals -> amap: ImportMap -> denv: DisplayEnv -> mdef : ModuleOrNamespaceExpr * extraAttribs: Attrib list -> Typar list diff --git a/src/fsharp/LowerCallsAndSeqs.fs b/src/fsharp/LowerCallsAndSeqs.fs index 2e2e0f7db18..6bc583faae1 100644 --- a/src/fsharp/LowerCallsAndSeqs.fs +++ b/src/fsharp/LowerCallsAndSeqs.fs @@ -65,10 +65,6 @@ let LowerImplFile g assembly = let mkLambdaNoType g m uv e = mkLambda m uv (e, tyOfExpr g e) -let mkUnitDelayLambda (g: TcGlobals) m e = - let uv, _ue = mkCompGenLocal m "unitVar" g.unit_ty - mkLambdaNoType g m uv e - let callNonOverloadedMethod g amap m methName ty args = match TryFindIntrinsicMethInfo (InfoReader(g, amap)) m AccessibleFromSomeFSharpCode methName ty with | [] -> error(InternalError("No method called '"+methName+"' was found", m)) @@ -81,21 +77,33 @@ let callNonOverloadedMethod g amap m methName ty args = type LoweredSeqFirstPhaseResult = - { /// The code to run in the second phase, to rebuild the expressions, once all code labels and their mapping to program counters have been determined - /// 'nextVar' is the argument variable for the GenerateNext method that represents the byref argument that holds the "goto" destination for a tailcalling sequence expression + { + /// The second phase of the transformation. This rebuilds the 'generate', 'dispose' and 'checkDispose' expressions for the + /// state machine. It is run after all code labels and their mapping to program counters have been determined + /// after the first phase. + /// + /// The arguments to phase2 are as follows: + /// 'pc' is the state machine variable allocated to hold the "program counter" for the state machine + /// 'current' is the state machine variable allocated to hold the "current" value being yielded from the enumeration + /// 'nextVar' is the argument variable for the GenerateNext method that represents the byref argument + /// that holds the "goto" destination for a tailcalling sequence expression + /// 'pcMap' is the mapping from code labels to values for 'pc' + /// + /// The phase2 function returns the core of the generate, dipsose and checkDispose implementations. phase2 : ((* pc: *) ValRef * (* current: *) ValRef * (* nextVar: *) ValRef * Map -> Expr * Expr * Expr) /// The labels allocated for one portion of the sequence expression labels : int list - /// any actual work done in Close + /// Indicates if any actual work is done in dispose, i.e. is there a 'try-finally' (or 'use') in the computation. significantClose : bool /// The state variables allocated for one portion of the sequence expression (i.e. the local let-bound variables which become state variables) stateVars: ValRef list /// The vars captured by the non-synchronous path - capturedVars: FreeVars } + capturedVars: FreeVars + } let isVarFreeInExpr v e = Zset.contains v (freeInExpr CollectTyparsAndLocals e).FreeLocals @@ -179,8 +187,9 @@ let LowerSeqExpr g amap overallExpr = | Expr.App (Expr.Val (vref, _, _), _f0ty, [elemTy], [e], _m) when valRefEq g vref g.seq_vref -> Some (e, elemTy) | _ -> None + /// Implement a decision to represent a 'let' binding as a non-escaping local variable (rather than a state machine variable) let RepresentBindingAsLocal (bind: Binding) res2 m = - // printfn "found letrec state variable %s" bind.Var.DisplayName + // printfn "LowerSeq: found local variable %s" bind.Var.DisplayName { res2 with phase2 = (fun ctxt -> let generate2, dispose2, checkDispose2 = res2.phase2 ctxt @@ -190,8 +199,9 @@ let LowerSeqExpr g amap overallExpr = generate, dispose, checkDispose) stateVars = res2.stateVars } + /// Implement a decision to represent a 'let' binding as a state machine variable let RepresentBindingAsStateMachineLocal (bind: Binding) res2 m = - // printfn "found letrec state variable %s" bind.Var.DisplayName + // printfn "LowerSeq: found state variable %s" bind.Var.DisplayName let (TBind(v, e, sp)) = bind let sp, spm = match sp with @@ -238,12 +248,12 @@ let LowerSeqExpr g amap overallExpr = //return true //NEXT: let label = IL.generateCodeLabel() - Some { phase2 = (fun (pcv, currv, _nextv, pcMap) -> + Some { phase2 = (fun (pcVar, currVar, _nextv, pcMap) -> let generate = mkCompGenSequential m - (mkValSet m pcv (mkInt32 g m pcMap.[label])) + (mkValSet m pcVar (mkInt32 g m pcMap.[label])) (mkSequential SequencePointsAtSeq m - (mkValSet m currv e) + (mkValSet m currVar e) (mkCompGenSequential m (Expr.Op (TOp.Return, [], [mkOne g m], m)) (Expr.Op (TOp.Label label, [], [], m)))) @@ -354,7 +364,7 @@ let LowerSeqExpr g amap overallExpr = match resBody with | Some res1 -> let capturedVars = unionFreeVars res1.capturedVars (freeInExpr CollectLocals compensation) - Some { phase2 = (fun ((pcv, _currv, _, pcMap) as ctxt) -> + Some { phase2 = (fun ((pcVar, _currv, _, pcMap) as ctxt) -> let generate1, dispose1, checkDispose1 = res1.phase2 ctxt let generate = // copy the compensation expression - one copy for the success continuation and one for the exception @@ -362,13 +372,13 @@ let LowerSeqExpr g amap overallExpr = mkCompGenSequential m // set the PC to the inner finally, so that if an exception happens we run the right finally (mkCompGenSequential m - (mkValSet m pcv (mkInt32 g m pcMap.[innerDisposeContinuationLabel])) + (mkValSet m pcVar (mkInt32 g m pcMap.[innerDisposeContinuationLabel])) generate1 ) // set the PC past the try/finally before trying to run it, to make sure we only run it once (mkCompGenSequential m (Expr.Op (TOp.Label innerDisposeContinuationLabel, [], [], m)) (mkCompGenSequential m - (mkValSet m pcv (mkInt32 g m pcMap.[currentDisposeContinuationLabel])) + (mkValSet m pcVar (mkInt32 g m pcMap.[currentDisposeContinuationLabel])) compensation)) let dispose = // generate inner try/finallys, then outer try/finallys @@ -378,7 +388,7 @@ let LowerSeqExpr g amap overallExpr = (mkCompGenSequential m (Expr.Op (TOp.Label innerDisposeContinuationLabel, [], [], m)) (mkCompGenSequential m - (mkValSet m pcv (mkInt32 g m pcMap.[currentDisposeContinuationLabel])) + (mkValSet m pcVar (mkInt32 g m pcMap.[currentDisposeContinuationLabel])) (mkCompGenSequential m compensation (Expr.Op (TOp.Goto currentDisposeContinuationLabel, [], [], m))))) @@ -512,12 +522,12 @@ let LowerSeqExpr g amap overallExpr = // Note, however, this leads to a loss of tailcalls: the case not // handled correctly yet is sequence expressions that use yield! in the last position // This can give rise to infinite iterator chains when implemented by the naive expansion to - // �for x in e yield e�. For example consider this: + // 'for x in e yield e'. For example consider this: // // let rec rwalk x = { yield x // yield! rwalk (x + rand()) } // - // This is the moral equivalent of a tailcall optimization. These also don�t compile well + // This is the moral equivalent of a tailcall optimization. These also don't compile well // in the C# compilation model | arbitrarySeqExpr -> @@ -540,12 +550,12 @@ let LowerSeqExpr g amap overallExpr = //return 2 //NEXT: let label = IL.generateCodeLabel() - Some { phase2 = (fun (pcv, _currv, nextv, pcMap) -> + Some { phase2 = (fun (pcVar, _currv, nextVar, pcMap) -> let generate = mkCompGenSequential m - (mkValSet m pcv (mkInt32 g m pcMap.[label])) + (mkValSet m pcVar (mkInt32 g m pcMap.[label])) (mkSequential SequencePointsAtSeq m - (mkAddrSet m nextv arbitrarySeqExpr) + (mkAddrSet m nextVar arbitrarySeqExpr) (mkCompGenSequential m (Expr.Op (TOp.Return, [], [mkTwo g m], m)) (Expr.Op (TOp.Label label, [], [], m)))) @@ -573,54 +583,77 @@ let LowerSeqExpr g amap overallExpr = let m = e.Range let initLabel = IL.generateCodeLabel() let noDisposeContinuationLabel = IL.generateCodeLabel() + + // Perform phase1 match Lower true true noDisposeContinuationLabel noDisposeContinuationLabel e with | Some res -> + + // After phase1, create the variables for the state machine and work out a program counter for each label. let labs = res.labels let stateVars = res.stateVars // printfn "successfully lowered, found %d state variables and %d labels!" stateVars.Length labs.Length - let pcv, pce = mkMutableCompGenLocal m "pc" g.int32_ty - let currv, _curre = mkMutableCompGenLocal m "current" ty - let nextv, _nexte = mkMutableCompGenLocal m "next" (mkByrefTy g (mkSeqTy g ty)) - let nextvref = mkLocalValRef nextv - let pcvref = mkLocalValRef pcv - let currvref = mkLocalValRef currv + let pcVar, pcExpr = mkMutableCompGenLocal m "pc" g.int32_ty + let currVar, _currExpr = mkMutableCompGenLocal m "current" ty + let nextVar, _nextExpr = mkMutableCompGenLocal m "next" (mkByrefTy g (mkSeqTy g ty)) + let nextVarRef = mkLocalValRef nextVar + let pcVarRef = mkLocalValRef pcVar + let currVarRef = mkLocalValRef currVar let pcs = labs |> List.mapi (fun i _ -> i + 1) let pcDone = labs.Length + 1 let pcInit = 0 let pc2lab = Map.ofList ((pcInit, initLabel) :: (pcDone, noDisposeContinuationLabel) :: List.zip pcs labs) let lab2pc = Map.ofList ((initLabel, pcInit) :: (noDisposeContinuationLabel, pcDone) :: List.zip labs pcs) - let stateMachineExpr, disposalExpr, checkDisposeExpr = res.phase2 (pcvref, currvref, nextvref, lab2pc) - // Add on the final 'return false' to indicate the iteration is complete - let stateMachineExpr = + + // Execute phase2, building the core of the the GenerateNext, Dispose and CheckDispose methods + let generateExprCore, disposalExprCore, checkDisposeExprCore = + res.phase2 (pcVarRef, currVarRef, nextVarRef, lab2pc) + + // Add on the final label and cleanup to the GenerateNext method + // generateExpr; + // pc <- PC_DONE + // noDispose: + // current <- null + // return 0 + let generateExprWithCleanup = mkCompGenSequential m - stateMachineExpr + generateExprCore (mkCompGenSequential m // set the pc to "finished" - (mkValSet m pcvref (mkInt32 g m pcDone)) + (mkValSet m pcVarRef (mkInt32 g m pcDone)) (mkCompGenSequential m (Expr.Op (TOp.Label noDisposeContinuationLabel, [], [], m)) (mkCompGenSequential m // zero out the current value to free up its memory - (mkValSet m currvref (mkDefault (m, currvref.Type))) + (mkValSet m currVarRef (mkDefault (m, currVarRef.Type))) (Expr.Op (TOp.Return, [], [mkZero g m], m))))) - let checkDisposeExpr = + + // Add on the final label to the 'CheckDispose' method + // checkDisposeExprCore + // noDispose: + // return false + let checkDisposeExprWithCleanup = mkCompGenSequential m - checkDisposeExpr + checkDisposeExprCore (mkCompGenSequential m (Expr.Op (TOp.Label noDisposeContinuationLabel, [], [], m)) (Expr.Op (TOp.Return, [], [mkFalse g m], m))) + // A utility to add a jump table to the three generated methods let addJumpTable isDisposal expr = let mbuilder = new MatchBuilder(NoSequencePointAtInvisibleBinding, m ) let mkGotoLabelTarget lab = mbuilder.AddResultTarget(Expr.Op (TOp.Goto lab, [], [], m), SuppressSequencePointAtTarget) let dtree = - TDSwitch(pce, + TDSwitch(pcExpr, [ - // no disposal action for the initial state (pc = 0) + // Add an empty disposal action for the initial state (pc = 0) if isDisposal then yield mkCase(DecisionTreeTest.Const(Const.Int32 pcInit), mkGotoLabelTarget noDisposeContinuationLabel) + + // Yield one target for each PC, where the action of the target is to goto the appropriate label for pc in pcs do yield mkCase(DecisionTreeTest.Const(Const.Int32 pc), mkGotoLabelTarget pc2lab.[pc]) + + // Yield one target for the 'done' program counter, where the action of the target is to continuation label yield mkCase(DecisionTreeTest.Const(Const.Int32 pcDone), mkGotoLabelTarget noDisposeContinuationLabel) ], Some(mkGotoLabelTarget pc2lab.[pcInit]), m) @@ -628,21 +661,31 @@ let LowerSeqExpr g amap overallExpr = let table = mbuilder.Close(dtree, m, g.int_ty) mkCompGenSequential m table (mkCompGenSequential m (Expr.Op (TOp.Label initLabel, [], [], m)) expr) + // A utility to handle the cases where exceptions are raised by the disposal logic. + // We wrap the disposal state machine in a loop that repeatedly drives the disposal logic of the + // state machine through each disposal state, then re-raise the last exception raised. + // + // let mutable exn : exn = null + // while(this.pc <> END_STATE) do + // try + // ``disposalExpr`` + // with e -> exn <- e + // if exn <> null then raise exn let handleExeceptionsInDispose disposalExpr = - // let mutable exn : exn = null - // while(this.pc <> END_STATE) do - // try - // ``disposalExpr'' - // with e -> exn <- e - // if exn <> null then raise exn let exnV, exnE = mkMutableCompGenLocal m "exn" g.exn_ty let exnVref = mkLocalValRef exnV let startLabel = IL.generateCodeLabel() - let doneLabel = IL.generateCodeLabel () + let doneDisposeLabel = IL.generateCodeLabel () // try ``disposalExpr'' with e -> exn <- e let eV, eE = mkLocal m "e" g.exn_ty let efV, _ = mkLocal m "ef" g.exn_ty + + // exn <- e let assignToExn = Expr.Op (TOp.LValueOp (LValueOperation.LSet, exnVref), [], [eE], m) + + // try + // ``disposalExpr`` + // with e -> exn <- e let exceptionCatcher = mkTryWith g (disposalExpr, @@ -651,14 +694,24 @@ let LowerSeqExpr g amap overallExpr = m, g.unit_ty, NoSequencePointAtTry, NoSequencePointAtWith) - - // while(this.pc != END_STATE) + // Make the loop + // + // startLabel: + // match this.pc with + // | PC_DONE -> goto DONE_DISPOSE + // | _ -> () + // try + // ``disposalExpr`` + // with e -> + // exn <- e + // goto startLabel + // DONE_DISPOSE: let whileLoop = let mbuilder = new MatchBuilder(NoSequencePointAtInvisibleBinding, m) let addResultTarget e = mbuilder.AddResultTarget(e, SuppressSequencePointAtTarget) let dtree = - TDSwitch(pce, - [ mkCase((DecisionTreeTest.Const(Const.Int32 pcDone)), addResultTarget (Expr.Op (TOp.Goto doneLabel, [], [], m)) ) ], + TDSwitch(pcExpr, + [ mkCase((DecisionTreeTest.Const(Const.Int32 pcDone)), addResultTarget (Expr.Op (TOp.Goto doneDisposeLabel, [], [], m)) ) ], Some (addResultTarget (mkUnit g m)), m) let pcIsEndStateComparison = mbuilder.Close(dtree, m, g.unit_ty) @@ -670,7 +723,7 @@ let LowerSeqExpr g amap overallExpr = exceptionCatcher (mkCompGenSequential m (Expr.Op ((TOp.Goto startLabel), [], [], m)) - (Expr.Op ((TOp.Label doneLabel), [], [], m)) + (Expr.Op ((TOp.Label doneDisposeLabel), [], [], m)) ) ) ) @@ -678,32 +731,42 @@ let LowerSeqExpr g amap overallExpr = let doRaise = mkNonNullCond g m g.unit_ty exnE (mkThrow m g.unit_ty exnE) (Expr.Const (Const.Unit, m, g.unit_ty)) + // let mutable exn = null + // --loop-- + // if exn != null then raise exn mkLet NoSequencePointAtLetBinding m exnV (Expr.Const (Const.Zero, m, g.exn_ty)) (mkCompGenSequential m whileLoop doRaise) - let stateMachineExprWithJumpTable = addJumpTable false stateMachineExpr - let disposalExpr = + // Add the jumptable to the GenerateNext method + let generateExprWithJumpTable = + addJumpTable false generateExprWithCleanup + + // Add the jumptable to the Dispose method + let disposalExprWithJumpTable = if res.significantClose then let disposalExpr = mkCompGenSequential m - disposalExpr + disposalExprCore (mkCompGenSequential m (Expr.Op (TOp.Label noDisposeContinuationLabel, [], [], m)) (mkCompGenSequential m // set the pc to "finished" - (mkValSet m pcvref (mkInt32 g m pcDone)) + (mkValSet m pcVarRef (mkInt32 g m pcDone)) // zero out the current value to free up its memory - (mkValSet m currvref (mkDefault (m, currvref.Type))))) + (mkValSet m currVarRef (mkDefault (m, currVarRef.Type))))) disposalExpr |> addJumpTable true |> handleExeceptionsInDispose else - (mkValSet m pcvref (mkInt32 g m pcDone)) + mkValSet m pcVarRef (mkInt32 g m pcDone) + + // Add the jumptable to the CheckDispose method + let checkDisposeExprWithJumpTable = + addJumpTable true checkDisposeExprWithCleanup - let checkDisposeExprWithJumpTable = addJumpTable true checkDisposeExpr - // all done, no return the results - Some (nextvref, pcvref, currvref, stateVars, stateMachineExprWithJumpTable, disposalExpr, checkDisposeExprWithJumpTable, ty, m) + // all done, now return the results + Some (nextVarRef, pcVarRef, currVarRef, stateVars, generateExprWithJumpTable, disposalExprWithJumpTable, checkDisposeExprWithJumpTable, ty, m) | None -> // printfn "FAILED: no compilation found! %s" (stringOfRange m) diff --git a/src/fsharp/LowerCallsAndSeqs.fsi b/src/fsharp/LowerCallsAndSeqs.fsi new file mode 100644 index 00000000000..5abcb8288dc --- /dev/null +++ b/src/fsharp/LowerCallsAndSeqs.fsi @@ -0,0 +1,22 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +module internal FSharp.Compiler.LowerCallsAndSeqs + +open FSharp.Compiler.Tast +open FSharp.Compiler.TcGlobals +open FSharp.Compiler.Import +open FSharp.Compiler.Range + +/// An "expr -> expr" pass that eta-expands under-applied values of +/// known arity to lambda expressions and beta-var-reduces to bind +/// any known arguments. The results are later optimized by the peephole +/// optimizer in opt.fs +val LowerImplFile: g: TcGlobals -> assembly: TypedImplFile -> TypedImplFile + +/// Analyze a TAST expression to detect the elaborated form of a sequence expression. +/// Then compile it to a state machine represented as a TAST containing goto, return and label nodes. +/// The returned state machine will also contain references to state variables (from internal 'let' bindings), +/// a program counter (pc) that records the current state, and a current generated value (current). +/// All these variables are then represented as fields in a hosting closure object along with any additional +/// free variables of the sequence expression. +val LowerSeqExpr: g: TcGlobals -> amap: ImportMap -> overallExpr: Expr -> (ValRef * ValRef * ValRef * ValRef list * Expr * Expr * Expr * TType * range) option diff --git a/src/fsharp/Optimizer.fs b/src/fsharp/Optimizer.fs index 226c87d3b2b..2eea2ef8db4 100644 --- a/src/fsharp/Optimizer.fs +++ b/src/fsharp/Optimizer.fs @@ -1689,10 +1689,6 @@ let (|AnyQueryBuilderOpTrans|_|) g = function Some (src, (fun newSource -> Expr.App (v, vty, tyargs, [builder; replaceArgs(newSource :: rest)], m))) | _ -> None -let mkUnitDelayLambda (g: TcGlobals) m e = - let uv, _ = mkCompGenLocal m "unitVar" g.unit_ty - mkLambda m uv (e, tyOfExpr g e) - /// If this returns "Some" then the source is not IQueryable. // := // | query.Select(, ) --> Seq.map(qexprInner', ...) diff --git a/src/fsharp/autobox.fsi b/src/fsharp/autobox.fsi new file mode 100644 index 00000000000..2ec2e9ba7fb --- /dev/null +++ b/src/fsharp/autobox.fsi @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +module internal FSharp.Compiler.AutoBox + +open FSharp.Compiler.Tast +open FSharp.Compiler.TcGlobals +open FSharp.Compiler.Import + +/// Rewrite mutable locals to reference cells across an entire implementation file +val TransformImplFile: g: TcGlobals -> amap: ImportMap -> implFile: TypedImplFile -> TypedImplFile + + diff --git a/src/fsharp/import.fs b/src/fsharp/import.fs index f6063ec6b41..dbe4296e0fd 100644 --- a/src/fsharp/import.fs +++ b/src/fsharp/import.fs @@ -37,8 +37,6 @@ type AssemblyLoader = abstract RecordGeneratedTypeRoot : ProviderGeneratedType -> unit #endif - - //------------------------------------------------------------------------- // Import an IL types as F# types. //------------------------------------------------------------------------- diff --git a/vsintegration/Utils/LanguageServiceProfiling/Options.fs b/vsintegration/Utils/LanguageServiceProfiling/Options.fs index fe87ff09658..07d3b5804ee 100644 --- a/vsintegration/Utils/LanguageServiceProfiling/Options.fs +++ b/vsintegration/Utils/LanguageServiceProfiling/Options.fs @@ -142,6 +142,7 @@ let FCS (repositoryDir: string) : Options = @"src\fsharp\ConstraintSolver.fs" @"src\fsharp\CheckFormatStrings.fsi" @"src\fsharp\CheckFormatStrings.fs" + @"src\fsharp\FindUnsolved.fsi" @"src\fsharp\FindUnsolved.fs" @"src\fsharp\QuotationTranslator.fsi" @"src\fsharp\QuotationTranslator.fs" @@ -155,7 +156,9 @@ let FCS (repositoryDir: string) : Options = @"src\fsharp\DetupleArgs.fs" @"src\fsharp\InnerLambdasToTopLevelFuncs.fsi" @"src\fsharp\InnerLambdasToTopLevelFuncs.fs" + @"src\fsharp\LowerCallsAndSeqs.fsi" @"src\fsharp\LowerCallsAndSeqs.fs" + @"src\fsharp\autobox.fsi" @"src\fsharp\autobox.fs" @"src\fsharp\IlxGen.fsi" @"src\fsharp\IlxGen.fs"